Index: .fossil-settings/crlf-glob ================================================================== --- .fossil-settings/crlf-glob +++ .fossil-settings/crlf-glob @@ -1,20 +1,22 @@ -compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs +compat/zlib/contrib/dotzlib/readme.txt +compat/zlib/contrib/dotzlib/*.cs compat/zlib/contrib/vstudio/readme.txt compat/zlib/contrib/vstudio/*/zlib.rc +compat/zlib/contrib/vstudio/*/zlibvc.def compat/zlib/contrib/vstudio/*/*.sln +compat/zlib/win32/zlib.def compat/zlib/win32/*.txt compat/zlib/win64/*.txt +compat/zlib/zlib.map libtommath/*.dsp libtommath/*.sln libtommath/*.vcproj -tools/tcl.hpj.in tools/tcl.wse.in win/buildall.vc.bat win/coffbase.txt win/makefile.vc win/rules.vc win/rules-ext.vc win/targets.vc win/tcl.dsp win/tcl.dsw -win/tcl.hpj.in Index: .fossil-settings/encoding-glob ================================================================== --- .fossil-settings/encoding-glob +++ .fossil-settings/encoding-glob @@ -1,9 +1,7 @@ -tools/tcl.hpj.in tools/tcl.wse.in win/buildall.vc.bat win/coffbase.txt win/makefile.vc win/rules.vc win/tcl.dsp win/tcl.dsw -win/tcl.hpj.in Index: .fossil-settings/ignore-glob ================================================================== --- .fossil-settings/ignore-glob +++ .fossil-settings/ignore-glob @@ -22,11 +22,12 @@ */tclsh* */tcltest* */versions.vc */version.vc */libtcl.vfs -*/libtcl_*.zip +*/libtcl*.zip +*/tclUuid.h html libtommath/bn.ilg libtommath/bn.ind libtommath/pretty.build libtommath/tommath.src @@ -45,13 +46,15 @@ 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 Index: .gitattributes ================================================================== --- .gitattributes +++ .gitattributes @@ -20,10 +20,11 @@ *.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 Index: .github/ISSUE_TEMPLATE.md ================================================================== --- .github/ISSUE_TEMPLATE.md +++ .github/ISSUE_TEMPLATE.md @@ -1,3 +1,3 @@ Important Note ========== -Please do not file issues with Tcl on Github. They are unlikely to be noticed in a timely fashion. Tcl issues are hosted in the [tcl fossil repository on core.tcl.tk](https://core.tcl.tk/tcl/tktnew); please post them there. +Please do not file issues with Tcl on Github. They are unlikely to be noticed in a timely fashion. Tcl issues are hosted in the [tcl fossil repository on core.tcl-lang.org](https://core.tcl-lang.org/tcl/tktnew); please post them there. Index: .github/PULL_REQUEST_TEMPLATE.md ================================================================== --- .github/PULL_REQUEST_TEMPLATE.md +++ .github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,3 @@ Important Note ========== -Please do not file pull requests with Tcl on Github. They are unlikely to be noticed in a timely fashion. Tcl issues (including patches) are hosted in the [tcl fossil repository on core.tcl.tk](https://core.tcl.tk/tcl/tktnew); please post them there. +Please do not file pull requests with Tcl on Github. They are unlikely to be noticed in a timely fashion. Tcl issues (including patches) are hosted in the [tcl fossil repository on core.tcl-lang.org](https://core.tcl-lang.org/tcl/tktnew); please post them there. ADDED .github/dependabot.yml Index: .github/dependabot.yml ================================================================== --- /dev/null +++ .github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" ADDED .github/workflows/linux-build.yml Index: .github/workflows/linux-build.yml ================================================================== --- /dev/null +++ .github/workflows/linux-build.yml @@ -0,0 +1,70 @@ +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: + cfgopt: + - "" + - "CFLAGS=-DTCL_NO_DEPRECATED=1" + - "--disable-shared" + - "--disable-zipfs" + - "--enable-symbols" + - "--enable-symbols=mem" + - "--enable-symbols=all" + - "CFLAGS=-ftrapv" + 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 + working-directory: generic + - name: Configure ${{ matrix.cfgopt }} + run: | + mkdir "${HOME}/install dir" + ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1) + env: + CFGOPT: ${{ matrix.cfgopt }} + 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 Index: .github/workflows/mac-build.yml ================================================================== --- /dev/null +++ .github/workflows/mac-build.yml @@ -0,0 +1,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: + cfgopt: + - "" + - "--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.cfgopt }} + # 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.cfgopt }} + 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 Index: .github/workflows/onefiledist.yml ================================================================== --- /dev/null +++ .github/workflows/onefiledist.yml @@ -0,0 +1,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@v3 + 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 <> $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@v3 + with: + name: Tclsh ${{ env.TCL_PATCHLEVEL }} Windows single-file build (snapshot) + path: '1dist/*_snapshot.exe' ADDED .github/workflows/win-build.yml Index: .github/workflows/win-build.yml ================================================================== --- /dev/null +++ .github/workflows/win-build.yml @@ -0,0 +1,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: + cfgopt: + - "" + - "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.cfgopt }} + run: | + &nmake -f makefile.vc ${{ matrix.cfgopt }} all + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + timeout-minutes: 5 + - name: Build Test Harness ${{ matrix.cfgopt }} + run: | + &nmake -f makefile.vc ${{ matrix.cfgopt }} tcltest + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + timeout-minutes: 5 + - name: Run Tests ${{ matrix.cfgopt }} + run: | + &nmake -f makefile.vc ${{ matrix.cfgopt }} 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: + cfgopt: + - "" + - "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.cfgopt }} + run: | + ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1) + env: + CFGOPT: --enable-64bit ${{ matrix.cfgopt }} + 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. Index: .gitignore ================================================================== --- .gitignore +++ .gitignore @@ -24,15 +24,16 @@ html manifest.uuid _FOSSIL_ */tclConfig.sh */tclsh* -*/tcltest* +*/tcltest */versions.vc */version.vc */libtcl.vfs -*/libtcl_*.zip +*/libtcl*.zip +*/tclUuid.h libtommath/bn.ilg libtommath/bn.ind libtommath/pretty.build libtommath/tommath.src libtommath/*.log @@ -50,10 +51,11 @@ libtommath/*.out libtommath/*.tex macosx/configure unix/autoMkindex.tcl unix/dltest.marker +unix/dltest/embtest unix/tcl.pc unix/tclIndex unix/pkgs/* win/Debug* win/Release* Index: .travis.yml ================================================================== --- .travis.yml +++ .travis.yml @@ -18,17 +18,10 @@ 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: @@ -53,18 +46,10 @@ 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 @@ -138,18 +123,10 @@ 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: @@ -215,11 +192,10 @@ 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: @@ -230,21 +206,21 @@ 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 + - 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,msvcrt' '-f' makefile.vc all tcltest - - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'OPTS=static,msvcrt' '-f' makefile.vc test + - 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 @@ -276,21 +252,21 @@ 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 + - 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,msvcrt' '-f' makefile.vc all tcltest - - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'OPTS=static,msvcrt' '-f' makefile.vc test + - 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 @@ -313,37 +289,20 @@ 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 @@ -368,33 +327,17 @@ 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 @@ -422,11 +365,10 @@ 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) DELETED ChangeLog Index: ChangeLog ================================================================== --- ChangeLog +++ /dev/null @@ -1,8856 +0,0 @@ -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 - - *** 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 - - * doc/next.n (METHOD SEARCH ORDER): Bug [3606943]: Corrected - description of method search order. - -2013-09-18 Donal Fellows - - Bump TclOO version to 1.0.1 for release. - -2013-09-17 Donal Fellows - - * 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 - - * 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 - - * 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 - - * library/auto.tcl: [Patch 3611643]: Allow TclOO classes to be found - by the autoloading mechanism. - -2013-08-02 Donal Fellows - - * 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 - - * 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 - - * 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 - - * unix/tclXtNotify.c: Bug [817249]: bring tclXtNotify.c up to date with - Tcl_SetNotifier() change. - -2013-07-02 Jan Nijtmans - - * unix/tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4 - * unix/configure: (thanks to Brian Griffin) - -2013-06-27 Jan Nijtmans - - * generic/tclConfig.c: Bug [9b2e636361]: Tcl_CreateInterp() needs - * generic/tclMain.c: initialized encodings. - -2013-06-18 Jan Nijtmans - - * generic/tclEvent.c: Bug [3611974]: InitSubsystems multiple thread - issue. - -2013-06-17 Jan Nijtmans - - * generic/regc_locale.c: Bug [a876646efe]: re_expr character class - [:cntrl:] should contain \u0000 - \u001f - -2013-06-09 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tclCompile.c: Removed duplicate const qualifier causing the HP - native cc to error out. - -2013-05-22 Donal K. Fellows - - * 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 - - * 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 - - * unix/tclUnixFCmd.c (DefaultTempDir): [Bug 3613567]: Corrected logic - for checking return code of access() system call, which was inverted. - -2013-05-19 Jan Nijtmans - - * 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 - - * generic/tclCompCmdsGR.c: Split tclCompCmds.c again to keep size of - code down. - -2013-05-16 Jan Nijtmans - - * generic/tclBasic.c: Add panic in order to detect incompatible - mingw32 sys/stat.h and sys/time.h headers. - -2013-05-13 Jan Nijtmans - - * compat/zlib/*: Upgrade to zlib 1.2.8 - -2013-05-10 Donal K. Fellows - - 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 - - * 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 - - * 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 - - * generic/tclCompCmds.c (TclCompileArraySetCmd): Generate better code - when the list of things to set is a literal. - -2013-04-25 Jan Nijtmans - - * 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 - - * 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 - - * generic/tclDecls.h: Implement Tcl_Pkg* functions as - (faster/stack-saving) macros around Tcl_Pkg*Ex functions. - -2013-04-08 Don Porter - - * 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 - - * 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 - * 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 - - * library/auto.tcl: [Bug 2102614]: Add ensemble indexing support to - * tests/autoMkindex.test: [auto_mkindex]. Thanks Brian Griffin. - -2013-03-19 Don Porter - - * generic/tclFCmd.c: [Bug 3597000]: Consistent [file copy] result. - * tests/fileSystem.test: - -2013-03-19 Jan Nijtmans - - * win/tclWinFile.c: [Bug 3608360]: Incompatible behaviour of "file - exists". - -2013-03-18 Donal K. Fellows - - * 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 - - * unix/tcl.m4: Patch by Andrew Shadura, providing better support for - three architectures they have in Debian. - -2013-03-11 Don Porter - - * generic/tclCompile.c: [Bugs 3607246,3607372]: Unbalanced refcounts - * generic/tclLiteral.c: of literals in the global literal table. - -2013-03-06 Don Porter - - * 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 - - * 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 - - * 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 - - * tests/chanio.test (chan-io-28.7): [Bug 3605120]: Stop test from - hanging when run standalone. - -2013-02-26 Jan Nijtmans - - * 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 - - * tests/binary.test (binary-41.*): [Bug 3605721]: Test independence - fixes. Thanks to Rolf Ade for pointing out the problem. - -2013-02-25 Don Porter - - * tests/assocd.test: [Bugs 3605719,3605720]: Test independence. - * tests/basic.test: Thanks Rolf Ade for patches. - -2013-02-23 Jan Nijtmans - - * compat/fake-rfc2553.c: [Bug 3599194]: compat/fake-rfc2553.c is - broken. - -2013-02-22 Don Porter - - * 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 - - * 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 - - * win/tclWinDde.c: [Bug 3605401]: Compiler error with latest mingw-w64 - headers. - -2013-02-19 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 for identifying the problem. - -2013-02-08 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tclUnixCompat.c: [Bug 3601804]: platformCPUID segmentation - fault on Darwin. - -2013-01-23 Donal K. Fellows - - * 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 - - * 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 - - * generic/tclPort.h: [Bug 3598300]: unix: tcl.h does not include - sys/stat.h - -2013-01-17 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/fileevent.n: [Bug 3436609]: Clarify readable fileevent "false - positives" in the case of multibyte encodings/transforms. - -2013-01-13 Jan Nijtmans - - * 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 - - * 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 - - * library/http/http.tcl: [Bug 3599395]: http assumes status line is a - proper Tcl list. - -2013-01-08 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclListObj.c: [Bug 3598580]: Tcl_ListObjReplace may release - deleted elements too early. - -2012-12-22 Alexandre Ferrieux - - * generic/tclUtil.c: [Bug 3598150]: Stop leaking allocated space when - objifying a zero-length DString. Spotted by afredd. - -2012-12-21 Jan Nijtmans - - * 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 - - * generic/tclCompCmdsSZ.c (TclSubstCompile): Improved the sequence of - instructions issued for [subst] when dealing with simple variable - references. - -2012-12-14 Don Porter - - *** 8.6.0 TAGGED FOR RELEASE *** - - * changes: updates for 8.6.0 - -2012-12-13 Don Porter - - * 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 - - * 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 - - * generic/tcl.h: Fix Tcl_DecrRefCount macro such that it doesn't - access its objPtr parameter twice any more. - -2012-12-11 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - 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 - - * 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 - - * generic/tclCompCmds.c (TclCompileDictUnsetCmd): Added compilation of - the [dict unset] command (for scalar var in LVT only). - -2012-10-23 Jan Nijtmans - - * 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 - - * 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 - - 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 - - * 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 - - * generic/tclEvent.c: [Bug 3576509]: tcl::Bgerror crashes with invalid - arguments - -2012-10-06 Jan Nijtmans - - * win/Makefile.in: [Bug 2459774]: tcl/win/Makefile.in not compatible - with msys 0.8. - -2012-10-03 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - *** 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 - - * 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 - - * generic/tclBinary.c: [Bug 3496014]: Unecessary memset() in - Tcl_SetByteArrayObj(). - -2012-08-20 Don Porter - - * generic/tclPathObj.c: [Bug 3559678]: Fix bad filename normalization - when the last component is the empty string. - -2012-08-20 Jan Nijtmans - - * win/tclWinPort.h: Remove wrapper macro for ntohs(): unnecessary, - because it doesn't require an initialized winsock_2 library. See: - - * win/tclWinSock.c: - * generic/tclStubInit.c: - -2012-08-17 Jan Nijtmans - - * win/nmakehlp.c: Add "-V" option, in order to be able to detect - partial version numbers. - -2012-08-15 Jan Nijtmans - - * win/buildall.vc.bat: Only build the threaded builds by default - * win/rules.vc: Some code cleanup - -2010-08-13 Stuart Cassoff - - * unix/tclUnixCompat.c: [Bug 3555454]: Rearrange a bit to quash - 'declared but never defined' compiler warnings. - -2012-08-13 Jan Nijtmans - - * 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 - - * tests/http.test: Fix http-3.29 for machines without IPv6 support. - -2010-08-08 Stuart Cassoff - - * unix/tclUnixCompat.c: Change one '#ifdef' to '#if defined()' for - improved consistency within the file. - -2012-08-08 Jan Nijtmans - - * generic/tclfileName.c: [Bug #1536227]: Cygwin network pathname - * tests/fileName.test: support - -2012-08-07 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/clock.test: [Bug 3549770]: Multiple test failures running - * tests/registry.test: tcltest outside build tree - * tests/winDde.test: - -2012-07-27 Jan Nijtmans - - * generic/tclUniData.c: Support Unicode 6.2 (Add Turkish lira sign) - * generic/regc_locale.c: - -2012-07-25 Alexandre Ferrieux - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclTest.c: Fix several more missing mutex-locks in - TestasyncCmd. - -2012-07-19 Alexandre Ferrieux - - * 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 - - * win/makefile.vc: [Bug 3544932]: Visual studio compiler check fails - -2012-07-16 Donal K. Fellows - - * 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 - - * library/reg/pkgIndex.tcl: Make registry 1.3 package dynamically - loadable when ::tcl::pkgconfig is available. - -2012-07-11 Jan Nijtmans - - * 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 - - * unix/tclUnixNotfy.c: [Bug 3541646]: Don't panic on triggerPipe - overrun. - -2012-07-10 Donal K. Fellows - - * 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 - - * 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 - - * unix/tclUnixPipe.c: [Bug 1189293]: Make "<<" binary safe. - * win/tclWinPipe.c: - -2012-07-03 Donal K. Fellows - - * 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 - - * library/msgcat/msgcat.tcl: Add tn, ro_MO and ru_MO to msgcat. - -2012-06-29 Harald Oehlmann - - * 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 - - * 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 - - * 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 - - * generic/tclIOSock.c: Use EAI_SYSTEM only if it exists. - * unix/tclUnixSock.c: - -2012-06-25 Don Porter - - * 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 - - * generic/tclCmdAH.c (EncodingDirsObjCmd): [Bug 3537605]: Do the right - thing when reporting errors with the number of arguments. - -2012-06-25 Jan Nijtmans - - * generic/tclfileName.c: [Patch 1536227]: Cygwin network pathname - * tests/fileName.test: support. - -2012-06-23 Jan Nijtmans - - * unix/tclUnixNotfy.c: [Bug 3508771]: Cygwin notifier for handling - win32 events. - -2012-06-22 Reinhard Max - - * 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 - - * win/tclWinReg.c: [Bug 3362446]: registry keys command fails - * tests/registry.test: with 8.5/8.6 - -2012-06-11 Don Porter - - * 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 - - * 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 - * 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 - - * 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 - - * 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 - - * unix/tclUnixInit.c: On Cygwin, use win32 API in stead of uname() - to determine the tcl_platform variables. - -2012-05-31 Jan Nijtmans - - * 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 - - * 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 - - * doc/expr.n, doc/mathop.n: [Bug 2931407]: Clarified semantics of - division and remainder operators. - -2012-05-29 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * {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 - - * 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 - - * generic/tclIO.c: Properly close nonblocking channels even when - not flushing them. - -2012-05-03 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * tests/ioCmd.test: [Bug 3522560]: Tame deadlocks in broken refchan - tests. - -2012-04-28 Alexandre Ferrieux - - 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 - - * 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 - - * library/init.tcl (auto_execok): Allow shell builtins to be detected - even if they are upper-cased. - -2012-04-26 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - IMPLEMENTATION OF TIP#396. - - * generic/tclBasic.c (builtInCmds, TclNRYieldToObjCmd): Convert the - formerly-unsupported yieldm and yieldTo commands into [yieldto]. - -2012-04-02 Jan Nijtmans - - * 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 - - * 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 - - * generic/tclCmdMZ.c (StringIsCmd): Faster mem-leak free - implementation of [string is entier]. - -2012-03-27 Donal K. Fellows - - IMPLEMENTATION OF TIP#395. - - * generic/tclCmdMZ.c (StringIsCmd): Implementation of the [string is - entier] check. Code by Jos Decoster. - -2012-03-27 Jan Nijtmans - - * 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 - - 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 ("") so that scripted control over copying is - easier. - ***POTENTIAL INCOMPATIBILITY*** - If you'd previously been using the "" 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 - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinFile.c: [Bug 3388350]: mingw64 compiler warnings - -2012-03-11 Donal K. Fellows - - * doc/*.n, doc/*.3: A number of small spelling and wording fixes. - -2012-03-08 Donal K. Fellows - - * doc/info.n: Various minor fixes (prompted by Andreas Kupries - * doc/socket.n: detecting a spelling mistake). - -2012-03-07 Andreas Kupries - - * 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 - - * win/tclWinPort.h: Compatibility with older Visual Studio versions. - -2012-03-04 Jan Nijtmans - - * generic/tclLoad.c: Patch from the cygwin folks - * unix/tcl.m4: - * unix/configure: (re-generated) - -2012-03-02 Donal K. Fellows - - * 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 - - * generic/tclIOUtil.c: [Bug 3466099]: BOM in Unicode - * generic/tclEncoding.c: - * tests/source.test: - -2012-02-23 Donal K. Fellows - - * 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 - - * generic/tclIOUtil.c: [Bug 2233954]: AIX: compile error - * unix/tclUnixPort.h: - -2012-02-16 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * generic/tclEnsemble.c: [Bug 3485022]: TclCompileEnsemble() avoid - * tests/trace.test: compile when exec traces set. - -2012-02-06 Miguel Sofer - - * 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 - - * generic/tclUniData.c: [FRQ 3464401]: Support Unicode 6.1 - * generic/regc_locale.c: - -2012-02-02 Don Porter - - * 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 - - * doc/AddErrInfo.3: [Bug 3482614]: Documentation nit. - -2012-01-30 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCmdMZ.c: [Bug 3475667]: Prevent buffer read overflow. - Thanks to "sebres" for the report and fix. - -2012-01-17 Donal K. Fellows - - * 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 - - * 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 - - * doc/tclvars.n: [Bug 3466506]: Document more environment variables. - -2012-01-09 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompile.c (TclInitAuxDataTypeTable): Extended to register - the DictUpdateInfo structure as an AuxData type. For use by tbcload, - tclcompiler. - -2011-12-11 Jan Nijtmans - - * generic/regc_locale.c: [Bug 3457031]: Some Unicode 6.0 chars not - * tests/utf.test: in [:print:] class - -2011-12-07 Jan Nijtmans - - * tools/uniParse.tcl: [Bug 3444754]: string tolower \u01c5 is wrong - * generic/tclUniData.c: - * tests/utf.test: - -2011-11-30 Jan Nijtmans - - * 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 - - * 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 - - * library/history.tcl (history): Simplify the dance of variable - management used when chaining to the implementation command. - -2011-11-22 Donal K. Fellows - - * generic/tclExecute.c (TclCompileObj): Simplify and de-indent the - logic so that it is easier to comprehend. - -2011-11-22 Jan Nijtmans - - * win/tclWinPort.h: [Bug 3354324]: Windows: [file mtime] sets wrong - * win/tclWinFile.c: time (VS2005+ only). - * generic/tclTest.c: - -2011-11-20 Joe Mistachkin - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinConsole.c: Refactor common thread handling patterns. - -2011-11-11 Alexandre Ferrieux - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * library/tzdata/America/Sitka: Update to Olson's tzdata2011l - * library/tzdata/Pacific/Fiji: - * library/tzdata/Asia/Hebron: (New) - -2011-10-11 Jan Nijtmans - - * win/tclWinFile.c: [Bug 2935503]: Incorrect mode field returned by - [file stat] command. - -2011-10-09 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * win/tclWinInt.h: Remove tclWinProcs, as it is no longer - * win/tclWin32Dll.c: being used. - -2011-10-03 Venkat Iyer - - * 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 - - * 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 - - * generic/tclOO.h: [RFE 3010352]: make all TclOO API functions - * generic/tclOODecls.h: MODULE_SCOPE - * generic/tclOOIntDecls.h: - -2011-09-27 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * generic/tclCmdIL.c: Revise [info frame] so that it stops creating - cycles in the iPtr->cmdFramePtr stack. - -2011-09-22 Donal K. Fellows - - * 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 - - * 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 - - * unix/tclIO.c: [Bug 3412487]: Now short reads are allowed in - synchronous fcopy, avoid mistaking them as nonblocking ones. - -2011-09-21 Andreas Kupries - - * generic/tclIORTrans.c (ForwardOpToOwnerThread): Fixed the missing - initialization of the 'dsti' field. Reported by Don Porter, on chat. - -2011-09-20 Don Porter - - * 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 - - * 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 - - 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 - - * generic/tclProc.c (ProcWrongNumArgs): [Bugs 3400658,3408830]: - Corrected the handling of procedure error messages (found by TclOO). - -2011-09-16 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinPort.h: [Bug 3407070]: tclPosixStr.c won't build with - EOVERFLOW==E2BIG - -2011-09-11 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tcl.h: [RFE 1711975]: Tcl_MainEx() (like Tk_MainEx()) - * generic/tclDecls.h: - * generic/tclMain.c: - -2011-09-02 Don Porter - - * tests/http.test: Convert [testthread] use to Thread package use. - Eliminates memory leak seen in `make valgrind`. - -2011-09-01 Alexandre Ferrieux - - * 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 - - * 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 - - * 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 - - * unix/tclUnixSock.c (TcpWatchProc): [Bug 3394732]: Put back the check - for server sockets. - -2011-08-29 Don Porter - - * generic/tclIORTrans.c: Leak of ReflectedTransformMap. - -2011-08-27 Don Porter - - * 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 - - * generic/tclIORChan.c: [Bug 3396948]: Leak of ReflectedChannelMap. - -2011-08-19 Don Porter - - * 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 - - * generic/tclTest.c: [Bug 2981154]: async-4.3 segfault. - * tests/async.test: [Bug 1774689]: async-4.3 sometimes fails. - -2011-08-18 Alexandre Ferrieux - - * generic/tclIO.c: [Bug 3096275]: Sync fcopy buffers input. - -2011-08-18 Jan Nijtmans - - * generic/tclUniData.c: [Bug 3393714]: Overflow in toupper delta - * tools/uniParse.tcl: - * tests/utf.test: - -2011-08-17 Alexandre Ferrieux - - * generic/tclIO.c: [Bug 2946474]: Consistently resume backgrounded - * tests/ioCmd.test: flushes+closes when exiting. - -2011-08-17 Alexandre Ferrieux - - * doc/interp.n: Document TIP 378's one-way-ness. - -2011-08-17 Don Porter - - * generic/tclGet.c: [Bug 3393150]: Overlooked free of intreps. - (It matters for bignums!) - -2011-08-16 Don Porter - - * 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 - - * 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 - - * generic/tclBasic.c: [Bug 3390272]: Leak of [info script] value. - -2011-08-15 Jan Nijtmans - - * generic/tclPosixStr.c: [Bug 3388350]: mingw64 compiler warnings - * win/tclWinPort.h: - * win/configure.in: - * win/configure: - -2011-08-14 Jan Nijtmans - - * doc/FindExec.3: [Patch 3124554]: Move WishPanic from Tk to Tcl - * doc/Panic.3 Added Documentation - -2011-08-12 Don Porter - - * generic/tclPathObj.c: [Bug 3389764]: Eliminate possibility that dup - of a "path" value can create reference cycle. - -2011-08-12 Donal K. Fellows - - * generic/tclZlib.c (ZlibTransformOutput): [Bug 3390073]: Return the - correct length of written data for a compressing transform. - -2011-08-10 Alexandre Ferrieux - - * generic/tclTestObj.c: [Bug 3386721]: Allow multiple [load]ing of the - Tcltest package. - -2011-08-09 Alexandre Ferrieux - - * 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 - - * 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 - - * win/tclWinConsole.c: [Bug 3388350]: mingw64 compiler warnings - * win/tclWinDde.c: - * win/tclWinPipe.c: - * win/tclWinSerial.c: - -2011-08-09 Jan Nijtmans - - * 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 - - * 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 - - * generic/tclOOInfo.c (InfoClassCallCmd): [Bug 3387082]: Plug memory - leak in call chain introspection. - -2011-08-06 Kevin B, Kenny - - * generic/tclAssemnbly.c: [Bug 3384840]: Plug another memory leak. - * generic/tclStrToD.c: [Bug 3386975]: Plug another memory leak. - -2011-08-05 Kevin B. Kenny - - * generic/tclStrToD.c: [Bug 3386975]: Plugged a memory leak in - double->string conversion. - -2011-08-05 Don Porter - - *** 8.6b2 TAGGED FOR RELEASE *** - - * changes: Updates for 8.6b2 release. - -2011-08-05 Donal K. Fellows - - * 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 - - * generic/tclVar.c (TclPtrSetVar): Fix valgrind-detected error when - newValuePtr is the interp's result obj. - -2011-08-04 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * changes: Updates for 8.6b2 release. - * tools/tcltk-man2html.tcl: Variable substitution botch. - -2011-08-02 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tcl.m4 (SC_TCL_IPV6): Fix AC_DEFINE invocation for - NEED_FAKE_RFC2553. - * unix/configure: autoconf-2.59 - -2011-07-28 Don Porter - - * 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 - - * 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 - - * win/tclWinPort.h: [Bug 3372130]: Fix hypot math function with MSVC10 - -2011-07-19 Don Porter - - * 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 - - * 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 - - * doc/upvar.n: Undocument long gone limitation of [upvar]. - -2011-07-18 Don Porter - - * 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 - - * 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 - - * generic/tclOOCall.c (TclOORenderCallChain): [Bug 3365156]: Remove - stray refcount bump that caused a memory leak. - -2011-07-12 Don Porter - - * generic/tclUnixSock.c: [Bug 3364777]: Stop segfault caused by - reading from struct after it had been freed. - -2011-07-11 Joe Mistachkin - - * generic/tclExecute.c: [Bug 3339502]: Correct cast for CURR_DEPTH to - silence compiler warning. - -2011-07-08 Donal K. Fellows - - * doc/http.n: [FRQ 3358415]: State what RFC defines HTTP/1.1. - -2011-07-07 Miguel Sofer - - * generic/tclBasic.c: Add missing INT2PTR - -2011-07-03 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * generic/tclLink.c: [Bug 3317466]: Prevent multiple links to a - single Tcl variable when calling Tcl_LinkVar(). - -2011-06-13 Don Porter - - * generic/tclStrToD.c: [Bug 3315098]: Mem leak fix from Gustaf - Neumann. - -2011-06-08 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c: Using the two free data elements in NRCommand to - store objc and objv - useful for debugging. - -2011-06-01 Jan Nijtmans - - * generic/tclUtil.c: Fix for [Bug 3309871]: Valgrind finds: invalid - read in TclMaxListLength(). - -2011-05-31 Don Porter - - * 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 - - * 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 - - * 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 - - * library/tzdata/Africa/Cairo: Update to Olson tzdata2011g - -2011-05-24 Donal K. Fellows - - * library/msgcat/msgcat.tcl (msgcat::mcset, msgcat::mcmset): Remove - some useless code; [dict set] builds dictionary levels for us. - -2011-05-17 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclLoad.c (TclGetLoadedPackages): Convert to use Tcl_Obj API - for result generation. - -2011-05-07 Miguel Sofer - - * generic/tclInt.h: Fix USE_TCLALLOC so that it can be enabled without - * unix/Makefile.in: editing the Makefile. - -2011-05-05 Don Porter - - * generic/tclListObj.c: Stop generating string rep of dict when - converting to list. Tolerate NULL interps more completely. - -2011-05-03 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclConfig.c: Reduce internals access in the implementation - of [::pkgconfig list]. - -2011-04-18 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/string.test: Test for [Bug 3285472]. Not buggy in trunk. - -2011-04-12 Venkat Iyer - - * library/tzdata/Atlantic/Stanley: Update to Olson tzdata2011f - -2011-04-12 Miguel Sofer - - * generic/tclBasic.c: Fix for [Bug 2440625], kbk's patch - -2011-04-11 Miguel Sofer - - * 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 - - * 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 - - * win/tclWinPort.h: Fix for [Bug 3280043]: win2k: unresolved DLL - * win/configure.in: imports. - * win/configure - -2011-04-06 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * library/init.tcl: TIP#131 implementation. - -2011-03-31 Donal K. Fellows - - * generic/tclGetDate.y, generic/tclDate.c (TclClockOldscanObjCmd): - More generation of errorCode information. - -2011-03-28 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * generic/tcl.h (ckfree,etc.): Restored C++ usability to the memory - allocation and free macros. - -2011-03-24 Donal K. Fellows - - * 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 - - * generic/tclObj.c: Exploit HAVE_FAST_TSD for the deletion context in - TclFreeObj() - -2011-03-22 Miguel Sofer - - * generic/tclThreadAlloc.c: Simpler initialization of Cache under - HAVE_FAST_TSD, from mig-alloc-reform. - -2011-03-21 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * generic/tclCompExpr.c (ParseExpr): Generate errorCode information on - failure to parse expressions. - -2011-03-17 Jan Nijtmans - - * generic/tclMain.c: [Patch 3124683]: Reorganize the platform-specific - stuff in (tcl|tk)Main.c. - -2011-03-16 Jan Nijtmans - - * generic/tclCkalloc.c: [Bug 3197864]: Pointer truncation on Win64 - TCL_MEM_DEBUG builds. - -2011-03-16 Don Porter - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: remove TEBCreturn() - -2011-03-12 Donal K. Fellows - - * 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 - - * win/tclWinFile.c: [Bug 3185609]: File normalization corner case - of ... broken with -DUNICODE - -2011-03-11 Donal K. Fellows - - * tests/unixInit.test: Make better use of tcltest2. - -2011-03-10 Donal K. Fellows - - * 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 - - * tests/incr.test: Update more of the test suite to use Tcltest 2. - -2011-03-09 Don Porter - - * 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 - - * tests/dstring.test, tests/init.test, tests/link.test: Update more of - the test suite to use Tcltest 2. - -2011-03-08 Jan Nijtmans - - * 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 - - * 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 - - * generic/tclAssembly.c, tests/assemble.test: Migrate to use a style - more consistent with the rest of Tcl. - -2011-03-06 Don Porter - - * 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 - - * generic/tclParse.c (TclParseBackslash): [Bug 3200987]: Correct - * tests/parse.test: trunction checks in \x and \u substitutions. - -2011-03-05 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/RegExp.3: [Bug 3165108]: Corrected documentation of description - of subexpression info in Tcl_RegExpInfo structure. - -2011-01-25 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCmdIL.c (Tcl_LsortObjCmd): Fix crash when multiple -index - options are used. Simplified memory handling logic. - -2010-12-20 Jan Nijtmans - - * win/tclWin32Dll.c: [Patch 3059922]: fixes for mingw64 - gcc4.5.1 - tdm64-1: completed for all environments. - -2010-12-20 Jan Nijtmans - - * 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 - - * 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 - - * unix/Makefile.in: Remove unwanted/obsolete 'ddd' target. - -2010-12-17 Stuart Cassoff - - * 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 - - * unix/Makefile.in: [Bug 2446711]: Remove 'allpatch' target. - -2010-12-17 Stuart Cassoff - - * unix/Makefile.in: [Bug 2537626]: Use 'rpmbuild', not 'rpm'. - -2010-12-16 Jan Nijtmans - - * 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 - - [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 - - * 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 - - * generic/tcl.h: [Bug 3137454]: Tcl CVS HEAD does not build on GCC 3. - -2010-12-14 Reinhard Max - - * 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 - - * 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 - - * unix/tcl.m4: Better building on OpenBSD. - * unix/configure: (autoconf-2.59) - -2010-12-10 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBinary.c: [Bug 3129448]: Possible over-allocation on - * generic/tclCkalloc.c: 64-bit platforms. - * generic/tclTrace.c: - -2010-12-05 Jan Nijtmans - - * unix/tcl.m4: [Patch 3116490]: Cross-compile support for unix - * unix/configure: (autoconf-2.59) - -2010-12-03 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/chanio.test: Converted many tests to tcltest2 by marking the - setup and cleanup parts as such. - -2010-11-19 Jan Nijtmans - - * win/tclWin32Dll.c: Fix gcc warnings: unused variable 'registration' - * win/tclWinChan.c: - * win/tclWinFCmd.c: - -2010-11-18 Jan Nijtmans - - * 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 - - * doc/file.n: [Bug 3111298]: Typofix. - - * tests/oo.test: [Bug 3111059]: Added testing that neatly trapped this - issue. - -2010-11-18 Miguel Sofer - - * generic/tclNamesp.c: [Bug 3111059]: Fix leak due to bad looping - construct. - -2010-11-17 Jan Nijtmans - - * 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 - - * win/tclAppInit.c:Bring compilation under mingw-w64 a bit closer - * win/cat.c: to reality. See for what's missing: - * win/tcl.m4: - * win/configure: (re-generated) - * win/tclWinPort.h: [Bug 3110161]: Extensions using TCHAR don't - compile on VS2005 SP1 - -2010-11-15 Andreas Kupries - - * 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 - - * changes: Updates for 8.6b2 release. - -2010-11-09 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/Makefile.in: [Patch 3101127]: Installer Improvements. - * unix/install-sh: - -2010-11-04 Donal K. Fellows - - * 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 - - * changes: Updates for 8.6b2 release. (Thanks Andreas Kupries) - -2010-11-03 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * library/tzdata/Asia/Hong_Kong: - * library/tzdata/Pacific/Apia: - * library/tzdata/Pacific/Fiji: Olson's tzdata2010o. - -2010-10-29 Alexandre Ferrieux - - * generic/tclTimer.c: [Bug 2905784]: Stop small [after]s from - wasting CPU while keeping accuracy. - -2010-10-28 Kevin B. Kenny - - [dogeen-assembler-branch] - * generic/tclAssembly.c: - * tests/assembly.test (assemble-31.*): Added jump tables. - -2010-10-28 Don Porter - - * 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 - - * 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 - - * unix/tclUnixSock.c (TcpGetOptionProc): Prevent crash if interp is - * win/tclWinSock.c (TcpGetOptionProc): NULL (a legal situation). - -2010-10-26 Reinhard Max - - * 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 - - [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 - - [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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/info.n: Document [info errorstack] faithfully. - -2010-10-16 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * win/tclWinThrd.h: (removed) because it is just empty en used nowhere - * win/tcl.dsp - -2010-10-12 Jan Nijtmans - - * 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 - - * unix/tclUnixSock.c (CreateClientSocket): [Bug 3084338]: Fix a - memleak and refactor the calls to freeaddrinfo(). - -2010-10-11 Jan Nijtmans - - * 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 - - * generic/tclExecute.c: Fix overallocation of exec stack in TEBC (due - to mixing numwords and numbytes) - -2010-10-08 Jan Nijtmans - - * generic/tclIOSock.c: On Windows, use gai_strerrorA - -2010-10-06 Don Porter - - * 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 - - [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 - - [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 - - * generic/tclExecute.c (TEBCresume): [Bug 3079830]: Added invalidation - of string representations of dictionaries in some cases. - -2010-10-01 Jeff Hobbs - - * 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 - - * 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 - - [dogeen-assembler-branch] - - * tests/assemble.test: - * generic/tclAssemble.h: - * generic/tclAssemble.c: Added listIn, listNotIn, and dictGet. - -2010-09-30 Kevin B. Kenny - - [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 - - [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 - - * unix/configure: Re-generate with autoconf-2.59 - * win/configure: - * generic/tclMain.c: Make compilable with -DUNICODE as well - -2010-09-28 Reinhard Max - - 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 - - [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 - - [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 - - * 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 - - * generic/tclOOMethod.c (ProcedureMethodVarResolver): avoid code - duplication, let the runtime var resolver call the compiled var - resolver. - -2010-09-26 Kevin B. Kenny - - [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 - - [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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tclAppInit.c: Make compilable with -DUNICODE (not activated - * win/tclAppInit.c: yet), many clean-ups in comments. - -2010-09-22 Miguel Sofer - - * 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 - - * 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 - - * 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 - - [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 - - * 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 - - * 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 - - * doc/file.n (file readlink): [Bug 3070580]: Typofix. - -2010-09-18 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/Makefile.in: Revise `make dist` target to tolerate the - case of zero bundled packages. - -2010-09-15 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * win/tclWin32Dll.c: Partly revert yesterday's change, to make it work - on VC++ 6.0 again. - -2010-09-10 Donal K. Fellows - - * 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 - - * 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: should always be - included, and fix conflict in various macro values: Always force the - same values as in VC++. - -2010-09-08 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tcl.m4: Applied patch by Jeff fixing issues with the manifest - handling on Win64. - * win/configure: Regenerated. - -2010-08-30 Miguel Sofer - - * 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 - - * 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 - - * doc/dict.n: [Bug 3046999]: Corrected cross reference to array - manpage to refer to (correct) existing subcommand. - -2010-08-26 Jeff Hobbs - - * 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 - - * 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 - - * library/tzdata/Africa/Cairo: - * library/tzdata/Asia/Gaza: Olson's tzdata2010l. - -2010-08-22 Jan Nijtmans - - * 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 - - * doc/linsert.n: [Bug 3045123]: Make description of what is actually - happening more accurate. - -2010-08-21 Jan Nijtmans - - * 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 - - * doc/Method.3: Fix definition of Tcl_MethodType. - -2010-08-19 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * library/safe.tcl (AliasGlob): [Bug 3004191]: Restore safe [glob] to - working condition. - -2010-08-15 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c (TclNRYieldToObjCmd): - * tests/coroutine.test: Fixed bad copypasta snafu. Thanks to Andy Goth - for finding the bug. - -2010-08-10 Jeff Hobbs - - * generic/tclUtil.c (TclByteArrayMatch): Patterns may not be - null-terminated, so account for that. - -2010-08-09 Don Porter - - * changes: Updates for 8.6b2 release. - -2010-08-04 Jeff Hobbs - - * 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 - - * generic/tclIORChan.c: [Bug 3034840]: Fixed reference counting in - * generic/tclIORTrans.c: InvokeTclMethod and callers. - * tests/ioTrans.test: - -2010-08-03 Andreas Kupries - - * 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 - - * 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 - - * generic/tclVar.c: Correcting bad port of [Bug 3037525] fix - -2010-07-28 Miguel Sofer - - * generic/tclVar.c: [Bug 3037525]: Lose fickle optimisation in - TclDeleteVars (used for runtime-created locals) that caused crash. - -2010-07-29 Jan Nijtmans - - * 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 - - * doc/http.n: Corrected description of location of one of the entries - in the state array. - -2010-07-24 Jan Nijtmans - - * 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 - - * generic/tclBasic.c: Added more errorCode setting. - -2010-07-15 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * generic/tclInt.decls: [Bug 803489]: Tcl_FindNamespace problem in - * generic/tclIntDecls.h: the Stubs table - * generic/tclStubInit.c: - -2010-07-02 Donal K. Fellows - - * 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 - - * 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 - - * doc/mathop.n: [Bug 3023165]: Fix typo that was preventing proper - rendering of the exclusive-or operator. - -2010-06-28 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * generic/tclCmdIL.c (Tcl_LsetObjCmd): [Bug 3019351]: Corrected wrong - args message. - -2010-06-21 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclInt.h: [Patch 3008541]: Order of TIP #348 fields in - Interp structure - -2010-05-28 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclStrToD.c: [Bug 2996549]: Failure in expr.test on Win32 - -2010-05-17 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * generic/tclPkg.c: Unnecessary type casts, see [Patch 2997087] - -2010-05-04 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/coroutine.test: testing coroutine arguments after [yield]: - check that only 0/1 allowed - -2010-04-30 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * compat/dirent2.h: Include "tcl.h", not , 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 - - * win/Makefile.in: Remove unused @MAN2TCLFLAGS@ - * win/tclWinPort.h: Move include from tclInt.h to - * generic/tclInt.h: tclWinPort.h, and eliminate unneeded - * generic/tclEnv.c: , and , 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 include. - * generic/tclExecute.c: Fix gcc warning: comparison between signed and - unsigned. - -2010-04-28 Donal K. Fellows - - * 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 - - * generic/tclExecute.c (TclExecuteByteCode): Rearrange location of an - assignment to shorten the object code. - -2010-04-27 Jan Nijtmans - - * 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 - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c: Add unsupported [yieldm] command. Credit - * generic/tclInt.h: Lars Hellstrom for the basic idea. - -2010-04-24 Miguel Sofer - - * 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 - - * unix/tclUnixPort.h: [Bug 2991415]: tclport.h #included before - limits.h - -2010-04-22 Jan Nijtmans - - * 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 - - * generic/tclTest.c: Use function prototypes from the FS API. - * compat/zlib/*: Upgrade to zlib 1.2.5 - -2010-04-19 Donal K. Fellows - - * generic/tclExecute.c (TclExecuteByteCode): Improve commenting and - reduce indentation for the Invocation Block. - -2010-04-18 Donal K. Fellows - - * doc/unset.n: [Bug 2988940]: Fix typo. - -2010-04-15 Jan Nijtmans - - * win/tclWinPort.h: Move inclusion of 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 - - * doc/try.n: [Bug 2987551]: Fix typo. - -2010-04-14 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * doc/catch.n, doc/info.n, doc/return.n: Formatting. - -2010-04-06 Donal K. Fellows - - * doc/Load.3: Minor corrections of formatting and cross links. - -2010-04-06 Jan Nijtmans - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * unix/tcl.m4: Only test for -visibility=hidden with gcc - (Second remark in [Bug 2976508]) - * unix/configure: regen - -2010-03-29 Don Porter - - * generic/tclStringObj.c: Fix array overrun in test format-1.12 - caught by valgrind testing. - -2010-03-27 Jan Nijtmans - - * generic/tclInt.h: [FRQ 2974744]: share exception codes - * generic/tclResult.c: (ObjType?) - * generic/tclCmdMZ.c: - * generic/tclCompCmdsSZ.c: - -2010-03-26 Jan Nijtmans - - * generic/tclExecute.c: [Bug 2976508]: Tcl HEAD fails on HP-UX - -2010-03-25 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * generic/tclCmdMZ.c: [Bug 2973361]: Revised fix for computing - indices of script arguments to [try]. - -2010-03-23 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompCmdsSZ.c (TclCompileThrowCmd): Added compilation for - the [throw] command. - -2010-03-18 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * win/makefile.vc: [Bug 2967340]: Static build was failing. - * win/.cvsignore: - -2010-03-10 Jan Nijtmans - - * 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 - - * generic/tclIORChan.c: [Bug 2936225]: Thanks to Alexandre Ferrieux - * doc/refchan.n: 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tcl.m4: [FRQ 2959069]: Support for -fvisibility=hidden - * unix/configure (regenerated with autoconf-2.59) - -2010-03-01 Alexandre Ferrieux - - * 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 - - * 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 - - * generic/tclStubInit.c: [Bug 2959713]: Link error with gcc 4.1 - -2010-02-27 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/regexp.test: Add test cases back ported from Jacl regexp work. - -2010-02-21 Jan Nijtmans - - * 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 - - * generic/tclCompCmds.c (TclCompileStringLenCmd): Make [string length] - of a constant string be handled better (i.e., handle backslashes too). - -2010-02-19 Stuart Cassoff - - * tcl.m4: Correct compiler/linker flags for threaded builds on - OpenBSD. - * configure: (regenerated). - -2010-02-19 Donal K. Fellows - - * 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 - - * 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 - - * generic/tclInt.h: Change order of various struct members, - fixing potential binary incompatibility with Tcl 8.5 - -2010-02-16 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/list.test: Add tests for explicit \0 in a string argument to - the list command. - -2010-02-11 Donal K. Fellows - - * 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 - - [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 - - * 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 - - * 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 - - * tools/genStubs.tcl: Remove dependency on 8.5+ idiom "in" in - expressions. - -2010-02-08 Donal K. Fellows - - * 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 - - * 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 - - * generic/tclCompCmds.c (TclCompileErrorCmd): Added compilation of the - [error] command. No new bytecodes. - -2010-02-05 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclVar.c (ArrayUnsetCmd): More corrections. - -2010-02-02 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/proc.n: [Bug 1970629]: Define a bit better what the current - namespace of a procedure is. - -2010-01-22 Jan Nijtmans - - * 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 - - * generic/tclExecute.c (TclExecuteByteCode): Improve error code - generation from some of the tailcall-related bits of TEBC. - -2010-01-21 Miguel Sofer - - * generic/tclCompile.h: [Bug 2910748]: NRE-enable direct eval on BC - * generic/tclExecute.c: spoilage. - * tests/nre.test: - -2010-01-19 Donal K. Fellows - - * doc/dict.n: [Bug 2929546]: Clarify just what [dict with] and [dict - update] are doing with variables. - -2010-01-18 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tcl.m4 (SC_CONFIG_CFLAGS): [Bug 1636685]: Use the configuration - for modern FreeBSD suggested by the FreeBSD porter. - -2010-01-03 Miguel Sofer - - * 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 - - * 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 - - * library/init.tcl (unknown): [Bug 2824981]: Fix infinite recursion of - ::unknown when [set] is undefined. - -2009-12-29 Donal K. Fellows - - * 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 - - * generic/tclBinary.c: [Bug 2922555]: Handle completely invalid input - * tests/binary.test: to the decode methods. - -2009-12-28 Donal K. Fellows - - * 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 - - * doc/namespace.n (SCOPED SCRIPTS): [Bug 2921538]: Updated example to - not be quite so ancient. - -2009-12-25 Jan Nijtmans - - * generic/tclCmdMZ.c: CONST -> const - * generic/tclParse.c - -2009-12-23 Donal K. Fellows - - * library/safe.tcl (AliasSource, AliasExeName): [Bug 2913625]: Stop - information about paths from leaking through [info script] and [info - nameofexecutable]. - -2009-12-23 Jan Nijtmans - - * unix/tcl.m4: Install libtcl8.6.dll in bin directory - * unix/Makefile.in: - * unix/configure: (regenerated) - -2009-12-22 Donal K. Fellows - - * generic/tclCmdIL.c (Tcl_LsortObjCmd): [Bug 2918962]: Stop crash when - -index and -stride are used together. - -2009-12-21 Jan Nijtmans - - * 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 before 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 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/tcltk-man2html.tcl (long-toc, cross-reference): [FRQ 2897296]: - Added cross links to sections within manual pages. - -2009-12-11 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c: Ensure right lifetime of varFrame's (objc,objv) - for coroutines. - - * generic/tclExecute.c: Code regrouping - -2009-12-09 Donal K. Fellows - - * generic/tclBasic.c: Added some of the missing setting of errorcode - values. - -2009-12-08 Miguel Sofer - - * generic/tclExecute.c (TclStackFree): Improved panic msg. - -2009-12-08 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c: [Patch 2910056]: Add ::tcl::unsupported::yieldTo - * generic/tclInt.h: - -2009-12-07 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/Tcl.n: [Bug 2901433]: Improved description of expansion to - mention that it is using list syntax. - -2009-11-27 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclThreadTest.c (NewTestThread): [Bug 2901803]: Fix small - error in function naming which blocked a threaded test build. - -2009-11-19 Jan Nijtmans - - * 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 - - * unix/tclAppInit.c: [Bug 2883850, 2900542]: Repair broken build of - * win/tclAppInit.c: the tcltest executable. - -2009-11-19 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinDde.c: Avoid gcc compiler warning by explicitly casting - DdeCreateStringHandle argument. - -2009-11-12 Andreas Kupries - - * 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 - - * generic/tclClock.c (TclClockInit): Do not create [clock] support - commands in safe interps. - -2009-11-11 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * win/README: [bug 2459744]: Removed outdated Msys + Mingw info. - -2009-11-09 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/object.n (DESCRIPTION): Substantive revision to make it clearer - what the fundamental semantics of an object actually are. - -2009-11-01 Joe Mistachkin - - * 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 - - * doc/Eval.3, doc/Cancel.3: Move TIP#285 routines out of Eval.3 into - their own manpage. - -2009-10-31 Donal K. Fellows - - * generic/tclBasic.c (ExprRoundFunc): [Bug 2889593]: Correctly report - the expected number of arguments when generating an error for round(). - -2009-10-30 Pat Thoyts - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclPathObj.c: [Bug 2884203]: Missing refcount on cached - normalized path caused crashes. - -2009-10-27 Kevin B. Kenny - - * 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 - - * unix/Makefile.in: Remove $(PACKAGE).* and prototype from the - `make distclean` target. Completes 2009-10-20 commit. - -2009-10-24 Kevin B. Kenny - - * 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 - - * 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 . - -2009-10-22 Donal K. Fellows - - * generic/tclOOBasic.c (TclOO_Object_VarName): [Bug 2883857]: Allow - the passing of array element names through this method. - -2009-10-21 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 . - - * 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 - - * 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 - - * 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 - - * 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 - - * library/tzdata/Africa/Cairo: - * library/tzdata/Asia/Gaza: - * library/tzdata/Asia/Karachi: - * library/tzdata/Pacific/Apia: Olson's tzdata2009n. - -2009-09-29 Don Porter - - * 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 - - * 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 - - * tests/error.test (error-15.8.*): Coverage tests illustrating - flaws in the propagation of return options by [try]. - -2009-09-26 Donal K. Fellows - - * 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 - - 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 - - * doc/namespace.n: the description of [namespace unknown] failed - to mention [namespace path]: fixed. Thx emiliano. - -2009-09-21 Mo DeJong - - * 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 - - * generic/tclCompile.c: Correct botch in the conversion of - Tcl_SubstObj(). Thanks to Kevin Kenny for detection and report. - -2009-09-17 Don Porter - - * 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 - - * generic/tclObj.c: Extended ::tcl::unsupported::representation. - -2009-09-11 Don Porter - - * 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 - - * 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 - - * 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 - - * generic/tclParse.c: [Bug 2850901]: Corrected line counting error - * tests/into.test: in multi-command script substitutions. - -2009-09-07 Daniel Steffen - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclStringObj.c: [Bug 2845535]: A few more string - overflow cases in [format]. - -2009-08-25 Andreas Kupries - - * 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 - - * 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 - - * generic/tclFileName.c: Correct regression in [Bug 2837800] fix. - * tests/fileName.test: - -2009-08-20 Don Porter - - * 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 - - * 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 - - * generic/tclCmdAH.c (TclNRForObjCmd, etc.): [Bug 2823276]: Make [for] - and [while] into NRE-safe commands, even when interpreted. - -2009-08-18 Don Porter - - * generic/tclPathObj.c: [Bug 2837800]: Added NULL check to prevent - * tests/fileName.test: crashes during [glob]. - -2009-08-16 Jan Nijtmans - - * unix/dltest/pkge.c: const addition - * unix/tclUnixThrd.c: Use 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 - - 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 - - * 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 - - * tests/coroutine.test: fix testfile cleanup - -2009-08-02 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - -2009-07-23 Joe Mistachkin - - * generic/tclNotify.c: [Bug 2820349]: Ensure that queued events are - freed once processed. - -2009-07-22 Jan Nijtmans - - * 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 - - * 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 bindings in Tk. - -2009-07-21 Kevin B. Kenny - - * library/tzdata/Asia/Dhaka: - * library/tzdata/Indian/Mauritius: Olson's tzdata2009k. - -2009-07-20 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/zlib.test: [Bug 2818131]: Added tests and fixed a typo that - broke [zlib push] for deflate format. - -2009-07-09 Donal K. Fellows - - * compat/mkstemp.c (mkstemp): [Bug 2819227]: Use rand() for random - numbers as it is more portable. - -2009-07-05 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/oo.test (oo-19.1): [Bug 2811598]: Make more resilient. - -2009-06-24 Pat Thoyts - - * tests/http11.test: [Bug 2811492]: Clean up procs after testing. - -2009-06-18 Donal K. Fellows - - * 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 - - * 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 - - * generic/tclStringObj.c: sprintf() -> Tcl_ObjPrintf() conversion. - -2009-06-15 Reinhard Max - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * library/tzdata/Asia/Dhaka: New DST rule for Bangladesh. (Olson's - tzdata2009i.) - -2009-06-08 Donal K. Fellows - - * doc/copy.n: Fix error in example spotted by Venkat Iyer. - -2009-06-02 Don Porter - - * 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 - - * tests/expr.test: [Bug 2798543]: Added many tests demonstrating - the broken cases. - -009-05-30 Kevin B. Kenny - - * library/tzdata/Africa/Cairo: - * library/tzdata/Asia/Amman: Olson's tzdata2009h. - -2009-05-29 Andreas Kupries - - * 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 - - * doc/expr.n: Fixed documentation of the right-associativity of - the ** operator. (spotted by kbk) - -2009-05-14 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c (TclObjInvoke): [Bug 2486550]: Make sure that a - null objProc is not used, use Tcl_NRCallObjProc instead. - -2009-05-01 Jan Nijtmans - - * win/configure.in Fix 64-bit detection for zlib on Win64 - * win/configure (regenerated) - -2009-04-28 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * unix/Makefile.in: [Patch 2769530]: Don't chmod/exec installManPage. - -2009-04-19 Pat Thoyts - - * 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 - - * doc/chan.n, doc/close.n: Tidy up documentation of TIP #332. - -2009-04-14 Kevin B. Kenny - - * library/tzdata/Asia/Karachi: Updated rules for Pakistan Summer - Time (Olson's tzdata2009f) - -2009-04-11 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * doc/StringObj.3: [Bug 2089279]: Corrected example so that it works - on 64-bit machines as well. - -2009-04-10 Pat Thoyts - - * tests/http.test: [Bug 26245326]: Added specific check for problem - * tests/httpd: (return incomplete HTTP response header). - -2009-04-08 Kevin B. Kenny - - * tools/tclZIC.tcl: Always emit files with Unix line termination. - * library/tzdata: Olson's tzdata2009e - -2009-04-09 Don Porter - - * library/http/http.tcl: [Bug 26245326]: Handle incomplete - lines in the "connecting" state. Thanks to Sergei Golovan. - -2009-04-08 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/Alloc.3: [Bug 2556263]: Size argument is "unsigned int". - -2009-03-27 Don Porter - - * 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 - - * 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 - - * doc/coroutine.n: [Bug 2152285]: Added basic documentation for the - coroutine and yield commands. - -2009-03-24 Donal K. Fellows - - * 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 - - * generic/tclBasic.c: [Bug 2502037]: NR-enable the handling of unknown - commands. - -2009-03-21 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * doc/tailcall.n: Added documentation for tailcall command. - -2009-03-18 Don Porter - - * 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 - - * generic/tclCmdMZ.c (TryPostBody): [Bug 2688063]: Extract information - from list before getting rid of last reference to it. - -2009-03-15 Joe Mistachkin - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c (TclNRCoroutineObjCmd): fix Tcl_Obj leak. - Diagnosis and fix thanks to GPS. - -2009-03-09 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompile.c: [Bug 2555129]: const compiler warning (as - error) in tclCompile.c - -2009-02-07 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinSock.c: [Bug 2446662]: Resync Win behavior on RST with - that of unix (EOF). - -2009-01-26 Donal K. Fellows - - * 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 - - * doc/zlib.n: Added a note that 'zlib push' is reversed by 'chan pop'. - -2009-01-22 Jan Nijtmans - - * 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 - - * unix/tcl.m4: Corrected a typo ($(SHLIB_VERSION) should be - ${SHLIB_VERSION}). - * unix/configure: Autoconf 2.59 - -2009-01-21 Andreas Kupries - - * 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 - - * generic/tclStringObj.c: New fix for [Bug 2494093] replaces the - flawed attempt committed 2009-01-09. - -2009-01-19 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCmdMZ.c (Tcl_ThrowObjCmd): Move implementation of [throw] - * library/init.tcl (throw): to C from Tcl. - -2009-01-12 Don Porter - - * 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 - - * 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 - - * generic/tclNamesp.c (NamespaceEnsembleCmd): [Bug 1558654]: Error out - when someone gives wrong # of args to [namespace ensemble create]. - -2009-01-08 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCmdAH.c: Tidy up spacing and code style. - -2009-01-03 Kevin B. Kenny - - * 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 - - * 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 Index: ChangeLog.1999 ================================================================== --- ChangeLog.1999 +++ /dev/null @@ -1,2634 +0,0 @@ -1999-12-22 Jeff Hobbs - - * changes: updated changes file - * tools/tclSplash.bmp: updated to show 8.3 - -1999-12-21 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tcl.m4: added defined for _THREAD_SAFE in --enable-threads - case; added check for pthread_mutex_init in libc; in AIX case, with - --enable-threads ${CC}_r is used; fixed flags when using gcc on SCO - - * generic/tclProc.c: corrected error reporting for default case at the - global level for uplevel command. - - * generic/tclIOSock.c: changed int to size_t type for len in - TclSockMinimumBuffers. - - * generic/tclCkalloc.c: fixed Tcl_DbCkfree to return a value on NULL - input. [Bug 3400] - - * generic/tclStringObj.c: fixed support for passing in negative length - to Tcl_SetUnicodeObj, et al handling routines. [Bug 3380] - - * doc/scan.n: - * tests/scan.test: - * generic/tclScan.c: finished support for inline scan by supporting - XPG identifiers. - - * doc/http.n: - * library/http2.1/http.tcl: added register and unregister commands to - http:: package (better support for tls/SSL), as well as -type argument - to http::geturl. [RFE 2617] - - * generic/tclBasic.c: removed extra decr of numLevels in Tcl_EvalObjEx - that could cause seg fault. (mjansen@wendt.de) - - * generic/tclEvent.c: fixed possible lack of MutexUnlock in - Tcl_DeleteExitHandler. [Bug 3545] - - * unix/tcl.m4: Added better pthreads library check and inclusion of - _THREAD_SAFE in --enable-threads case - Added support for gcc config on SCO - - * doc/glob.n: added note about ..../ glob behavior on Win9* - * doc/tcltest.n: fixed minor example errors. [Bug 3551] - -1999-11-17 Brent Welch - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * {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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/aclocal.m4: Changed AIX-4.[2-9] check to AIX-4.[1-9] [Bug 1909] - -1999-08-20 Jeff Hobbs - - * generic/tclPosixStr.c: fixed typo. [Bug 2592] - - * doc/*: fixed various nroff bugs in man pages. [Bug 2503 2588] - -1999-08-19 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * /: 8.2.0 tagged for final release - -1999-08-12 Scott Stanton - - * 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 - - * win/tclWinSerial.c: Applied patch from Petteri Kettunen to remove - compiler warning. - -1999-08-10 Scott Redman - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinInt.h: Remove function declarations in header that was - moved to tclInt.decls file in previous changes. - -1999-08-02 Scott Redman - - * 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 - - * 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 - - * 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 - - * generic/tclInt.decls: added declaractions necessary for the Tcl test - code to work wth stubs. [Bug 2445] - -1999-07-30 Scott Redman - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/tclSplash.bmp: Updated Windows installer bitmap to ready - Tcl/Tk Version 8.2. - -1999-07-26 Scott Redman - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * README: Small tweaks to clean up typos and wording. - -1999-07-20 Melissa Hirschl - - * 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 - - * library/http2.1/http.tcl: updated -useragent text to say version - 2.1. - -1999-07-16 Scott Redman - - * 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 - - * tools/tcl.wse.in: Fixed naming of target files for Windows. - -1999-07-14 Jerry Peek - - * doc/re_syntax.n: Deleted sentence as suggested by Scott S. - -1999-07-12 Jerry Peek - - * 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 - - * 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 - - * 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 - - * tests/string.test: - * generic/tclCmdMZ.c: Fixed bug in string range bounds checking code. - -1999-07-08 Jennifer Hom - - * 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 - - * 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 - - * doc/fconfigure.n: Clarified default buffering behavior for the - standard channels. [Bug 2335] - -1999-07-06 Scott Redman - - * win/tclWinSerial.c: New implementation of serial port driver from - Rolf Shroedter (Rolf.Schroedter@dlr.de) that allows more than one byte - to be read from the port. Implemented using polling instead of - threads, there is a max. 10ms latency between checking the port for - file events. [Bug 1980 2217] - -1999-07-06 Brent Welch - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/reg.test: - * generic/regexec.c: Fixed bugs in non-greedy quantifiers. - -1999-06-23 Jerry Peek - - * 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 - - * 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 - - * unix/tclUnixThrd.c (TclpThreadCreate): Fixed memory leak where - thread attributes were not being released. [Bug 2254] - -1999-06-17 Scott Stanton - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclUtf.c (Tcl_UtfNcasecmp): Fixed incorrect computation of - relative ordering. [Bug 2135] - -1999-06-01 Scott Stanton - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * generic/tclCmdAH.c (Tcl_ForObjCmd): Fixed crash caused by failure to - reset the result before evaluating the test expression. - -1999-05-14 Bryan Surles - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/makefile.vc: Added encoding directory to install-libraries - target. - -1999-05-03 Scott Stanton - - * 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 - - * Changed version to 8.1.1. - -1999-04-30 Scott Stanton - - * 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 - - * 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 - - * generic/tclLiteral.c (TclHideLiteral): Fixed so hidden literals get - duplicated to avoid accidental sharing in the global object table. - -1999-04-23 Scott Stanton - - * generic/tclStubInit.c: - * tools/genStubs.tcl: Changed to avoid the need for forward - declarations in stub initializers. - -1999-04-23 Scott Stanton - - * 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 - - * 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 - - * 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 - - * 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 - - * Merged 8.1 back into the main trunk - -1999-04-13 Scott Stanton - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 " but allow all - other uses including "encoding system". Added test cases and updated - the man page for Safe Tcl. - -1999-04-05 Scott Stanton - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclFileName.c: - * generic/tclDecls.h: - * generic/tcl.decls: Added CONST to Tcl_JoinPath and - Tcl_TranslateFileName. - -1999-03-29 Scott Redman - - * 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 - - * win/makefile.bc: Removed makefile for Borland compiler, no longer - supported. - -1999-03-26 Scott Redman - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/reg.test: - * generic/regc_color.c: Applied regexp bug fix from Henry Spencer. - -1999-03-19 Scott Redman - - * 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 - - * 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 - - * win/README.binary: - * win/README: - * unix/configure.in: - * generic/tcl.h: - * README: Updated version to 8.1b3. - -1999-03-14 Scott Stanton - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWin32Dll.c: Removed Dll instance from thread-local storage. - -1999-03-08 Scott Stanton - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * Updated patchlevel to 8.1b1 - -1998-12-02 Scott Stanton - - * 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 - - * Merged changes from 8.0.4, especially the new pkg_mkIndex - -1998-12-01 Scott Stanton - - * 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 - - * 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 - - * regexec.c: more performance tuning from Henry Spencer. - -1998-11-17 Scott Stanton - - * 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 - - * tclVar.c (TclGetIndexedScalar): Fixed bug 796, var name was getting - lost before being passed to CallTraces. - -1998-10-21 Scott Stanton - - * added "encoding" command - - * Moved internal regexp declarations from tclInt.h to tclRegexp.h - - * integrated regexp updates from Henry Spencer - -1998-10-15 Scott Stanton - - * 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 - - * 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 - - * makefile.vc: fixed so TCL_LIBRARY is set before running tcltest - - * tclWin32Dll.c: removed TclpFinalize, cleanup of merges DELETED ChangeLog.2000 Index: ChangeLog.2000 ================================================================== --- ChangeLog.2000 +++ /dev/null @@ -1,2539 +0,0 @@ -2000-12-14 Don Porter - - * 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 - - * 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 - - * 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 {!} in expressions. [Patch 102702] - -2000-12-08 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 . 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/.cvsignore: Removed 'configure' from the glob list now that it's - included. - -2000-11-03 Jeff Hobbs - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * win/tclConfig.sh.in (TCL_LIBS): Cleaned up unix-specific autoconf - variables. - -2000-07-11 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/trace.n: minor doc cleanup - -2000-09-06 André Pönitz - - * doc/*.n: added or changed "SEE ALSO:" section - -2000-09-06 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/man.macros: Tweaked tab settings for .SO (Standard Options) - sections, based on suggestion from Peter Spjuth. - -2000-08-24 Mo DeJong - - * 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 - - 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 - - * generic/tclVar.c: Added check for non-arrays for [array statistics] - command (patch from Mark Patton). - -2000-08-19 David Gravereaux - - * generic/tclPlatDecls.h: without a previous '#include ', - 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 - - * win/.cvsignore (added): provides a cleaner build environment with - graphical CVS clients. - -2000-08-15 Eric Melski - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclObj.c: r1.15 accidentally changed a global mutex name - tclObjMutex to ObjMutex. Put the correct name back. - -2000-08-07 Eric Melski - - * 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 - - * win/configure.in: TCL_STUB_LIB_FLAG should not include ${TCL_DBGX} - in win/tclConfig.sh, fix that. - -2000-07-25 David Gravereaux - - * 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 - - * 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 - - * doc/msgcat.n: Added documentation about the selection of the default - locale on Windows. - -2000-07-23 Joe English - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * compat/string.h: Fixed function prototypes for strpbrk and strtok - [Bug: 6020]. - -2000-07-17 David Gravereaux - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/package.n: Corrected information about [package forget] - arguments [Bug: 5418]. - -2000-06-23 Eric Melski - - * 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 - - * 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 - - * doc/RegExp.3: Replaced instances of "Tcl_GetRegExpInfo" with - "Tcl_RegExpGetInfo", the correct name of the function [Bug: 5901]. - -2000-06-13 Eric Melski - - * 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 - - * 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 - - * 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 - - 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 - - * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Corrected caching - of the index ptr to account for offsets != sizeof(char *). [Bug: 5153] - -2000-05-29 Sandeep Tamhankar - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - operating as proxy for David Gravereaux - - * win/tclWinThrd.c (TclpInitLock, TclpMasterLock): Added missing - initialization of joinLock. - -2000-05-09 Eric Melski - - * 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 - - * 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 - - * tests/set-old.test: - * doc/array.n: - * generic/tclVar.c: Added [array statistics] command [RFE: 4557] - -2000-05-06 Andreas Kupries - operating as proxy for David Gravereaux - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - 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 - - * 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 - - * unix/mkLinks: - * doc/AddErrInfo.3: Added information about Tcl_LogCommandInfo - [Bug: 1818]. - -2000-04-24 Eric Melski - - * 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 - - * 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 - - 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 - - * library/package.tcl (tclPkgUnknown): Fixed a typo in the Mac package - search part of tclPkgUnknown. - -2000-04-21 Sandeep Tamhankar - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/dde.n: corrected dde poke docs. [Bug: 4991] - -2000-04-11 Eric Melski - - * win/tclWinPipe.c: Added "CONST" keyword to declaration of char - *native in TclpCreateTempFile, to supress compiler warnings. - -2000-04-10 Brent Welch - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - 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 - - * 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 - - * 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 - - * {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 - - * 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 - - * 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 - - * 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 - - * unix/tclUnixFCmd.c (SetGroupAttribute): - * unix/tclUnixFCmd.c (SetOwnerAttribute): Added (uid_t) and (gid_t) - casts to avoid compiler warnings. - -2000-03-31 Eric Melski - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * mac/tclMacSock.c: Don't panic when you get an error closing an async - socket. This doesn't seem to hurt anything, and we return the error so - the caller can do the right thing. - - New Files: - * mac/MW_TclHeader.h: - * mac/MW_TclTestHeader.h: - * mac/MW_TclTestHeader.pch: - * mac/MW_TclAppleScriptHeader.h: More convenient to use .h prefix - files in the preference panels... - - The above are curtesy of Daniel Steffen (steffen@math.mq.edu.au) - -2000-02-08 Eric Melski - - * 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 - - * 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 - - * tests/package.test: - * library/tclIndex: - * library/package.tcl: Renamed ::package namespace to ::pkg. - -2000-02-03 Eric Melski - - * 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 - - * 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 - - * library/init.tcl: Applied patch from rfe 1734 regarding auto_load - errors not setting error message and errorInfo properly. - -2000-02-01 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/clock.test: Added tests for "next " and - "" - 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 - - * 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 - - * 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 - - * 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 - - * 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 " 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 - - * generic/tclClock.c: Changed switch in Tcl_ClockObjCmd to use - enumerated values instead of constants. (ie, COMMAND_SCAN instead of - 3). DELETED ChangeLog.2001 Index: ChangeLog.2001 ================================================================== --- ChangeLog.2001 +++ /dev/null @@ -1,3629 +0,0 @@ -2001-12-28 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/tcl.wse.in: Fix for [Bug 495120]. tcl.wse.in was stored in cvs - with improper . This resulted in corrupted when checked-out - on translating CVS clients such as windows (CRCRLF) and mac (CRCR). - -2001-12-19 Mo DeJong - - * 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 - - * 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 - - * 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 - - * win/tclWinSerial.c (SerialCheckProc): corrected time calculations to - be unsigned. (schroedter) - -2001-12-18 Mo DeJong - - * 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 - - * 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 - - * Applied [Bug 219311] on behalf of Rolf Schroedter - to prevent fcopy on serial ports - from flooding the event queue. - -2001-12-11 Miguel Sofer - - * doc/CrtInterp.3: - * generic/tclBasic.c: docs and comments corrections. [Bug 493412] - Bug & patch by Don Porter. - -2001-12-14 Donal K. Fellows - - * 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 - - * 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 - - * doc/Preserve.3: doc'd TCL_DYNAMIC use. [Patch 483989] (porter) - -2001-12-12 Andreas Kupries - - * generic/tclIO.c (Tcl_GetsObj): Applied patch for [Bug 491341] as - provided by Don Porter . Fixes the - assumption of having an empty Tcl_Obj to work with. - -2001-12-11 Miguel Sofer - - * 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 - - * unix/tclUnixPipe.c (TclpCreateProcess): Applied Don Porter's patch - fixing [Bug 437489]. - -2001-12-10 Miguel Sofer - - * generic/tclEvent.c: - * tests/event.test: fix background error reporting in the absence of a - bgerror proc [Bug 219142]. - -2001-12-10 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/namespace.test: modified namespace-41.2, added 41.3 - {knownbug} after discussion with Don Porter and Kevin Kenny. - -2001-11-29 Miguel Sofer - - * tests/namespace.test: added namespace-41.2, a simpler test for - [Bug 231259] - -2001-11-29 Donal K. Fellows - - * 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 - - * 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 - - * win/tclWinFCmd.c: Fix a coredump in the filename normalizer code for - Win95/98. - -2001-11-27 David Gravereaux - - * 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 - - * 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 - - * generic/tclIntPlatDecls.h: 'make genstubs' after changes in - 2001-11-23 commit from Daniel Steffen. - -2001-11-24 Mo DeJong - - * 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 - - * 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 - - * 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 - - 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 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 - , 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: missing variable declaration under - TCL_COMPILE_DEBUG. - -2001-11-20 Miguel Sofer - - * 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 - - * 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 - - * win/buildall.vc.bat: Added useful comments. - -2001-11-19 Miguel Sofer - - * tests/compile.test: added a test for bug [Bug 483309] - -2001-11-19 Vince Darley - - * 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 - - * 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 - - * 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 - - * generic/tclCompCmds.c: patch for [Bug 483309] (petasis). - -2001-11-16 Kevin B. Kenny - - * generic/tclListObj.c: removed a C++-style comment that was - inadvertently left in the source code. - -2001-11-16 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/FileSystem.3: - * doc/file.n: - * doc/tcltest.n: converted use of \' to more reasonable format. - -2001-11-10 Mo DeJong - - * 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 - - * 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 - - * 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 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 - - * 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 - - * tests/var.test: - * generic/tclVar.c: Corrected bug in [global] when dealing with - variable names matching :*. [Bug 480176] - -2001-11-08 Mo DeJong - - 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 - - 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * generic/tclIO.c (ReadChars): Fixed [Bug 478856] reported by Stuart - Cassoff . 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 - - * 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 - - * library/init.tcl: made filesystem fallback proc ::tcl::CopyDirectory - more robust to vagaries of non-native filesystems. - -2001-11-02 Vince Darley - - * doc/file.n: - * generic/tclIOUtil.c: updated documentation and comments to clarify - behaviour of 'file copy' wrt soft links. - -2001-10-29 Vince Darley - - * 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 - - * 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 - - * 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 - - * doc/ObjectType.3: Minor documentation fix, reported by David N. - Welton directly to me. - -2001-10-22 Vince Darley - - * 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 - - * 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 - - * generic/tclIOUtil.c: fix to bug in Tcl_FSChdir shown up by recent - tclkit builds. - -2001-10-17 Jeff Hobbs - - * unix/tclUnixPipe.c (PipeInputProc, PipeOutputProc): do immediate - retry when error is returned with errno == EINTR. [Bug 415131] (leger) - -2001-10-16 Jeff Hobbs - - * unix/tclLoadAout.c (TclGuessPackageName): removed unused vars and - fixed warnings. [Bug 446622] (lim) - -2001-10-15 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * generic/tclFCmd.c: fix to memory leak in TclFileDeleteCmd on - certain error conditions. - * doc/FileSystem.3: fix to typo. - -2001-10-12 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * win/tclWinPort.h: #include needed to get moved to - after #include 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 - - * tests/unixInit.test: Corrected restore of ::env(LANG). - -2001-10-09 Jeff Hobbs - - * 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 - - * generic/tclLiteral.c: (TclReleaseLiteral) reverted previous patch - for [Bug 467523] - cure is worse than the illness. - -2001-10-05 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclIOUtil.c: - * doc/FileSystem.3: corrected and clarified documentation for - 'Tcl_FSListVolumes(Proc)'. No code changes. - -2001-09-28 Miguel Sofer - - * doc/FindExec.3: added a comment not to change the working directory - before calling Tcl_GetNameOfExecutable. [Bug 219215] - -2001-09-28 Kevin Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 . - - * 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" . - - * 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 - - * 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 - - * 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 - - * generic/tclVar.c: removed comments referring to unused flag - TCL_PARSE_PART1. - -2001-09-24 Don Porter - - * 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 - - The change below fixes [Bug 464380]. The bug was reported by Ronnie - Brunner . 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: insured that execution stack errors are also - detected at abnormal returns. - -2001-09-19 Donal K. Fellows - - * 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 - - * generic/tclIOCmd.c (Tcl_PutsObjCmd): Rewritten to have saner and - faster argument handling. [Bug 123552], [Patch 402564] (fellows) - -2001-09-18 Don Porter - - * 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 - - * 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 - - * generic/tclExecute.c: corrected small bug in [Patch 456668] - the - varFramePtr was not restored in one possible exit. - -2001-09-17 Miguel Sofer - - * 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 - - * 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 . Thanks to - Christopher Nelson for doing editorial work. - -2001-09-13 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tcl.decls: reserved stub #481 for the implementation of - [TIP 56] - -2001-09-11 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tcl.h: - * generic/tclPlatDecls.h: Reminder from David Cuthbert - that I hadn't finished the Borland compatibility - stuff. [Patch 436116] - -2001-09-09 Mo DeJong - - * 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 - - * win/mkd.bat: - * win/rmd.bat: made these text files, text files again. [Patch 451333] - -2001-09-08 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 . - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/winFCmd.test: made notWin2000 constraint false if not running - on Windows at all. - -2001-09-04 David Gravereaux - - * 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 - - * 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 - - * generic/tclProc.c: - * tests/proc.test: made [proc] check that formal args have simple - names. [Bug 458548] - -2001-09-04 Vince Darley - - 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 - - * generic/tclCompile.c: fixed incorrect operands for INST_LIST [Bug - 458241] (David Cuthbert, dacut@users.sourceforge.net) - -2001-09-03 Jeff Hobbs - - * generic/tclExecute.c (TclExecuteByteCode): fixed missing comma in - debug macro. - -2001-09-03 Donal K. Fellows - - * doc/ExprLongObj.3: Fixed error in documentation of argument type to - Tcl_ExprObj [Bug 457435] - -2001-09-02 David Gravereaux - - * 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 - - * 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 - - * generic/tclIndexObj.c: fixed some casting problems that upset Crays. - [Bug 419528] (andreasen) - -2001-08-30 Don Porter - - * generic/tcl.h: Silence warning from Sun compiler. [Bug 454374] - -2001-08-30 Miguel Sofer - - * 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 - - 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 - - * 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 - - -2001-08-28 Jeff Hobbs - - * generic/tclCompCmds.c (TclPushVarName): noted 'static' defn. - [Bug 453872] - -2001-08-26 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 . - -2001-08-23 Jeff Hobbs - - * 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 - - 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 - - * 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 - - * 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 - - * tests/ioUtil.test (ioUtil-3.*): Corrected errors in tests revealed - by fix of overagressive compiler. [Bug 451200] - -2001-08-21 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/trace.test: Corrected test numbers. [Bug 449794] - -2001-08-12 Mo DeJong - - * 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 - - 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 - - * generic/tclVar.c: - * tests/trace.test: Insure that [array] traces work correctly for - undefined variables. [Bug 449094] - -2001-08-09 Mo DeJong - - * unix/Makefile.in: Delete the unused getcwd.o target. [Bug 440942] - -2001-08-08 Don Porter - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * generic/tclIOUtil.c (Tcl_FSMatchInDirectory): corrected - uninitialized value. - -2001-08-02 Mo DeJong - - * generic/tclPlatDecls.h: - * win/tclWinPort.h: Revert 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 - - * 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 - - 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 - - * 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 - - * doc/pkgMkindex.n: - * library/package.tcl: Corrected documentation and usage message of - [pkg_mkIndex]. - -2001-07-18 Mo DeJong - - * 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 - - * 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 - - * 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 - - * win/tclWinPort.h: Add Cygwin specific defines for environ and - timezone variables. - -2001-07-17 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * README: - * mac/README: - * unix/README: - * win/README: - * win/README.binary: updated READMEs with purls - -2001-07-03 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclNamesp.c: Correction to faulty patch from [Bug 231259] - -2001-06-28 Donal K. Fellows - - * 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 - - * 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 - - * tests/event.test (event-11.5): Removed hard-coded port number which - could fail on some systems. [Bug 436727] - -2001-06-26 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tcl.m4 (SC_CONFIG_CFLAGS): Link to the imm32 library when - building with mingw gcc. - -2001-06-25 Mo DeJong - - * 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 - - * win/configure: Regen. - * win/configure.in: Add resource compiler fix from 8.3.3 to fix - compiling with mingw. - -2001-06-22 Mo DeJong - - * win/configure: Regen. - * win/tcl.m4: Fix silly typo in last checkin. - -2001-06-22 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclUtil.c (Tcl_DStringAppendElement): patch to save an - extra strlen call. [Bug 428572] - -2001-05-30 Donal K. Fellows - - * 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 - - * library/init.tcl (unknown): removed errant " in error message - -2001-05-27 Jeff Hobbs - - * 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 - - * 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 - -2001-05-23 Jeff Hobbs - - * 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 - - * unix/tcl.m4 (SC_PATH_TCLCONFIG): Fix comments, and typo in cached - variable name. - -2001-05-23 Mo DeJong - - * 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 - - * 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 - - * generic/tclExecute.c: removed Tcl_DuplicateObj in INST_DUP - -2001-05-21 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * doc/console.n: Deleted. Put it in the wrong source tree! D'oh! - -2001-05-15 Jeff Hobbs - - * 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 - - * tests/lindex.test: added test for nested braces [Patch 423617] - -2001-05-15 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: insure different rand() seeds in different - threads. [Bug 416643] - -2001-05-03 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tclUnixTime.c: Fixed silly typo in calls to 'gmtime' and - 'localtime' that broke the Linux build. - -2001-04-09 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/Macintosh.3: Removed duplicates from .SH line. [Bug 413983] - -2001-04-05 Donal K. Fellows - - * generic/tclCmdMZ.c (Tcl_StringObjCmd): Fixed so will compile - with K&R compilers. [Patch 413844, Bug 413847] - -2001-04-04 Don Porter - - * generic/tclMain.c: Patch from Kevin Kenny to restore support of - pre-ANSI compilers. [Bug 413846, Patch 413842] - -2001-04-04 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinInt.h (tclWinTCharEncoding): Removed as now a static - variable in win/tclWin32Dll.c instead. - -2001-03-23 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/string.test: Fixed some test numberings and added a test. - [Patch 403229] - -2001-03-06 Donal K. Fellows - - * 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 - - * 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 - - * no changes; fixing up the missing comment in the previous one. - Sorry. - -2001-02-23 msofer - - * /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 - - * 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 - - * 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 - - * win/makefile.vc (install-libraries): Corrected misdirected install - directory for the msgcat 1.2 package. - -2001-01-30 Don Porter - - * 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 - - 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 - - * 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 - - * 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 Index: ChangeLog.2002 ================================================================== --- ChangeLog.2002 +++ /dev/null @@ -1,4741 +0,0 @@ -2002-12-18 David Gravereaux - - * win/makefile.vc: some uses of xcopy swapped to the @$(CPY) macro. - Reported by Joe Mistachkin . - -2002-12-17 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/README: Update msys build env URL. This release #4 build both - tcl and tk without problems. - -2002-11-22 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/Tcl.n: Corrected indentation of the new language. Oops. - -2002-11-10 Kevin Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * library/word.tcl: Changed $tcl_platform to $::tcl_platform to avoid - possible scope trouble. - -2002-10-29 Vince Darley - - * 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 - - * unix/tclLoadDyld.c (TclpFindSymbol): pass all dyld error messages - upstream [Bug 627546]. - -2002-10-28 Andreas Kupries - - * library/dde/pkgIndex.tcl: - * library/reg/pkgIndex.tcl: Changed the hardwired debug suffix (d) to - the correct suffix (g). - -2002-10-28 Don Porter - - * 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 - - * 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 - - * 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 - - *** 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/configure: add workaround for cygwin windres - * win/tcl.m4 (SC_CONFIG_CFLAGS): problem. [Patch 624010] (howell) - -2002-10-15 Jeff Hobbs - - * 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 - - * 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 - - * generic/tclEnv.c (Tcl_PutEnv): correct possible mem leak. [Patch - 623269] (brouwers) - -2002-10-11 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/binary.n: More clarification of [binary scan]'s behaviour. - -2002-10-09 Daniel Steffen - - * generic/tclIntDecls.h: fixed botched regen. - -2002-10-09 Daniel Steffen - - * 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 definitions and - obsolete definitions. - * mac/tclMacChan.c: removed obsolete GetOpenMode() and replaced - associated constants with the analogues (they existing defs - were inconsistent with 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 - - * 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 - - * 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 - - * doc/tcltest.n: fixed typo [Bug 618018]. Thanks to "JJM". - -2002-10-03 Donal K. Fellows - - * 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 - - * 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 - - * doc/socket.n: Mentioned that ports may be specified as serivce names - as well as integers. [Bug 616843] - -2002-09-30 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/README: Add note about building extensions with the same - compiler Tcl was built with. [Tk Bug 592096] - -2002-09-10 Daniel Steffen - - * macosx/Tcl.pbproj/project.pbxproj: disabled building html - documentation during embedded build. - -2002-09-10 Daniel Steffen - - * 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 - - *** 8.4.0 TAGGED FOR RELEASE *** - -2002-09-06 Don Porter - - * 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 - - * tests/tcltest.test: Added nonRoot flag to tests 8.3, 8.4, and 8.12. - -2002-09-05 Don Porter - - * 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 - - * 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 - - * 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 - - * generic/tclInterp.c (AliasCreate): a Tcl_Obj was leaked on error - return from TclPreventAliasLoop. - -2002-09-03 Daniel Steffen - - * macosx/Tcl.pbproj/project.pbxproj: Bumped version number to 8.4.0 - and updated copyright info. - -2002-09-03 Miguel Sofer - - * generic/tclVar.c (Tcl_UpVar2): a Tcl_Obj was being leaked on error - return from TclGetFrame. - -2002-09-03 Don Porter - - * changes: Updated changes for 8.4.0 release. - -2002-09-02 Jeff Hobbs - - * 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 - - * 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 - - *** 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 - - * win/tclWinThrd.c (TclpFinalizeThreadData, TclWinFreeAllocCache): - Applied patch for [Bug 599428], provided by Miguel Sofer - . - -2002-08-28 David Gravereaux - - * 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 - - * 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 - - * 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 - - * generic/tclThreadAlloc.c: small optimisation, reducing the new - allocator's overhead. - -2002-08-23 Miguel Sofer - - * generic/tclObj.c (USE_THREAD_ALLOC): fixed leak [Bug 597936]. Thanks - to Zoran Vasiljevic. - -2002-08-23 Miguel Sofer - - * generic/tclThreadAlloc.c (USE_THREAD_ALLOC): moving objects between - caches as a block, instead of one-by-one. - -2002-08-22 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * unix/tclUnixTest.c (TestfilehandlerCmd): Changed readable/writable - to the more common readable|writable. Fixes [Bug 596034] reported by - Larry Virden . - -2002-08-16 Donal K. Fellows - - * 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 - - * 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 - - * generic/tclCmdMZ.c: fixing UMR in delete traces, [Bug 589863]. - -2002-08-08 David Gravereaux - - * tools/man2help.tcl: Fixed $argv handling bug where if -bitmap wasn't - specified $argc was off by one. - -2002-08-08 Miguel Sofer - - * 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 - - * tests/README: Noted removal of defs.tcl. - -2002-08-08 Jeff Hobbs - - * 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 - - * 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 - - * generic/tclCompile.h: - * generic/tclObj.c: making tclCmdNameType static ([Bug 584567], Don - Porter). - -2002-08-07 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: bugfix (reading freed memory). Testsuite - passed on linux/i386, compile-13.1 hung on linux/alpha. - -2002-08-01 Miguel Sofer - - * generic/tclExecute.c: added a reference count for the complete - execution stack, instead of Tcl_Preserve/Tcl_Release. - -2002-08-01 Mo DeJong - - * 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 - - * win/tclWinPort.h: The windows headers don't provide socklen_t, so we - have to do it. - -2002-07-31 Miguel Sofer - - * 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 - - * generic/tclInterp.c: signed/unsigned comparison warning fixed - (Vince Darley). - -2002-07-31 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/regc_locale.c (cclass): [[:xdigit:]] is only a defined - concept on western characters, so should not allow any unicode digit, - and hence number of ranges in [[:xdigit:]] is fixed. - * tests/reg.test: Added test to detect the bug. - * generic/regc_cvec.c (newcvec): Corrected initial size value in - character vector structure. [Bug 578363] Many thanks to - pvgoran@users.sf.net for tracking this down. - -2002-07-28 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * generic/tclVar.c (TclObjLookupVar): leak fix and improved comments. - -2002-07-26 Jeff Hobbs - - * 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 - - * 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 - - * generic/tclProc.c: fix for [Tk Bug 219218] "error handling with - bgerror in Tk" - -2002-07-24 Miguel Sofer - - * generic/tclExecute.c: restoring full TCL_COMPILE_DEBUG - functionality. - -2002-07-24 Don Porter - - * tests/unixInit.test: relaxed unixInit-3.1 to accept iso8859-15 as a - valid C encoding. [Bug 575336] - -2002-07-24 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/Makefile.in: Combine ranlib tests and avoid printing unless - ranlib is actually run. - -2002-07-23 Mo DeJong - - * 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 - - * 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 - - * 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 - - * tclIOUtil.c: Silence compiler warning. [Bug 584408]. - -2002-07-19 Vince Darley - - * 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 - - * 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 - - * unix/Makefile.in: fix to build on MacOS X [Bug 529801], bug report - and fix from jcw. - -2002-07-19 Donal K. Fellows - - * 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 - - * 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 - - * generic/tclBasic.c (CallCommandTraces): delete traces now receive - the FQ old name of the command. [Bug 582532] (Don Porter) - -2002-07-18 Vince Darley - - * 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 - - * generic/tclVar.c (DupParsedVarName): nasty bug fixed, reported by - Vince Darley. - -2002-07-17 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c (TclExecuteByteCode): Minor fixes to make this - file compile with SunPro CC... - -2002-07-17 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * unix/configure: Regen. - * unix/configure.in: Remove useless subst of TCL_BIN_DIR. - -2002-07-15 Miguel Sofer - - * generic/tclVar.c: inaccurate comment fixed - -2002-07-15 Miguel Sofer - - * 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 - - * 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 - - * tests/unixInit.test: Improved constraints to protect /tmp. [Bug - 581403] - -2002-07-15 Vince Darley - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * changes: added recent changes - -2002-07-05 Reinhard Max - - * 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 - - * 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 - - *** 8.4b1 TAGGED FOR RELEASE *** - -2002-07-04 Donal K. Fellows - - * tests/cmdMZ.test (cmdMZ-1.4): - * tests/cmdAH.test: More fixing of writable-current-dir assumption. - [Bug 575824] - -2002-07-04 Miguel Sofer - - * tests/basic.test: Same issue as below; fixed [Bug 575817] - -2002-07-04 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * doc/tcltest.n: Markup fixes, spellcheck. - -2002-07-02 Don Porter - - * 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 - - * tests/fCmd.test: - * generic/tclCmdAH.c: clearer error msgs for 'file link', as per the - man page. - -2002-07-01 Joe English - - * 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 - - * 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 - - * 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 - - * doc/concat.n: Documented the *real* behaviour of [concat]! - -2002-06-30 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tclUnixTime.c: Make [clock format] respect locale settings. - * tests/clock.test: [Bug 565880]. ***POTENTIAL INCOMPATIBILITY*** - -2002-06-26 Miguel Sofer - - * doc/CrtInterp.3: - * doc/StringObj.3: clarifications by Don Porter, [Bug 493995] and [Bug - 500930]. - -2002-06-24 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompExpr.c: - * generic/tclParseExpr.c: LogSyntaxError() should reset the - interpreter result [Bug 550142 "Tcl_ExprObj -> abort"] - -2002-06-21 Don Porter - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c (TclCompEvalObj): clarified and simplified the - logic for compilation/recompilation. - -2002-06-19 Joe English - - * doc/file.n: Fixed indentation. No substantive changes. - -2002-06-19 Jeff Hobbs - - * 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 - - * generic/tclExecute.c (TEBC): removing unused "for(;;)" loop; - improved comments; re-indentation. - -2002-06-18 Miguel Sofer - - * 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 - - * generic/tclExecute.c (TEBC, INST_DONE): small bug in the panic code - for tcl-stack corruption. - -2002-06-17 David Gravereaux - - 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 - - * 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 - - * win/tclWinPipe.c (BuildCommandLine): Fixed [Bug 554068] ([exec] on - windows did not treat { in filenames well.). Bug reported by Vince - Darley , patch provided by Vince - too. - -2002-06-17 Joe English - - * 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 - - * 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 - - * generic/tclCompile.c (TclCompileTokens): a better algorithm for the - previous bug fix. - -2002-06-16 Miguel Sofer - - * generic/tclCompile.c (TclCompileTokens): - * tests/compile.test: [Bug 569438] in the processing of dollar - variables; report by Georgios Petasis. - -2002-06-16 Miguel Sofer - - * 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 - - * 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 - - * win/rules.vc: The test for compiler optimizations was in error. - Thanks goes to Roy Terry for his assistance - with this. - -2002-06-14 Donal K. Fellows - - * 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 - - * generic/tclExecute.c (TclExecuteByteCode): consolidated code for the - conditional branch instructions. - -2002-06-13 Miguel Sofer - - * generic/tclExecute.c (TclExecuteByteCode): fixed the previous patch; - wouldn't compile with TCL_COMPILE_DEBUG set. - -2002-06-13 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * tclBasic.c (Tcl_DeleteTrace): fixed [Bug 568123] (thanks to Hemang - Lavana) - -2002-06-12 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: optimised algorithm for exception range - lookup; part of [Patch 453709]. - -2002-06-10 Vince Darley - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/README: Update msys+mingw URL. - -2002-06-03 Don Porter - - * 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 - - * doc/namespace.n: added description of [namepace forget] behaviour - for unqualified patterns. [Bug 559268] - -2002-06-03 Miguel Sofer - - * generic/tclExecute.c: reverting an accidental modification in the - last commit. - -2002-06-03 Miguel Sofer - - * doc/Tcl.n: clarify the empty variable name issue ([Bug 549285] - reported by Tom Krehbiel, patch by Don Porter). - -2002-05-31 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - === 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 - - * tests/winPipe.test: Applied patch for [Bug 549617]. Patch and bug - report by Kevin Kenny . - - * 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 - - * 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 - - * 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 - - * doc/CrtObjCmd.3: Added Tcl_GetCommandFromObj, Tcl_GetCommandFullName - [Bugs 547987, 414921] - -2002-05-14 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/file.n: - * tools/man2tcl.c: - * tools/man2help2.tcl: Thanks to Peter Spjuth - , 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 - - * 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 - - * 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 - - -- Changes from Peter Spjuth - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/exec.n: - * doc/tclvars.n: doc updates [Patch 509426] (gravereaux) - -2002-04-24 Daniel Steffen - - * 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 - - * doc/TraceCmd.3: New file that documents Tcl_CommandTraceInfo, - Tcl_TraceCommand and Tcl_UntraceCommand [Bug 414927] - -2002-04-22 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * tests/lindex.test (lindex-3.7): - * generic/tclUtil.c (TclGetIntForIndex): Stopped indexes from hitting - wide ints. [Bug 526717] - -2002-04-18 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tcl.h: no 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 - - * 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 - - * 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 - - * library/tcltest/tcltest.tcl: added getMatchingFiles back (alias to - GetMatchingFiles), which was a public function in tcltest 1.0. - -2002-04-01 Vince Darley - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclVar.c: Refactored CallTraces to collect repeated handling - of its returned value into CallTraces itself. - -2002-03-28 David Gravereaux - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c (Tcl_EvalEx): passing the correct commandSize to - TclEvalObjvInternal. [Bug 219362], fix by David Knoll. - -2002-03-28 Miguel Sofer - - * generic/tclBasic.c (Tcl_EvalEx): - * tests/basic.test: avoid exceptional returns at level 0. [Bug 219181] - -2002-03-27 Don Porter - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c (Tcl_EvalObjv): replaced obscure, incorrect code - as described in [Bug 533907] (Don Porter). - -2002-03-24 Don Porter - - * 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 - - * 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 - - * tests/basic.test (basic-46.1): adding test for [Bug 533758], fixed - earlier today. - -2002-03-22 Jeff Hobbs - - * win/tclWinInt.h: moved undef of TCL_STORAGE_CLASS. [Bug 478579] - -2002-03-22 Miguel Sofer - - * 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 - - * doc/expr.n: Improved documentation for ceil and floor. [Bug 530535] - -2002-03-20 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * library/tcltest/tcltest.tcl: - * library/tcltest/pkgIndex.tcl: Bumped tcltest package to 2.0.2. - -2002-03-11 Mo DeJong - - * 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 - - * 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 - - * 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 - - * win/tclWinFCmd.c (DoCopyFile): correctly set retval to TCL_OK. - -2002-03-07 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - *** 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 - - * 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 - - * library/encoding/iso2022-jp.enc: - * library/encoding/iso2022.enc: - * tools/encoding/iso2022-jp.esc: - * tools/encoding/iso2022.esc: gave $B precedence over $@, - 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 - - * 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 - - * 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 - - * generic/tclExecute.c: Replaced a few direct stack accesses with the - POP_OBJECT() macro [Bug 507181] (Don Porter). - -2002-02-27 Don Porter - - * 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 - - * 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 - - * tests/socket.test (2.7): Accepted and applied patch for [Bug 523470] - provided by Don Porter 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 - - * 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 - - * 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 - - * mac/tclMacSock.c (TcpGetOptionProc): Changed to recognize the option - "-error". Essentially ignores the option, always returning an empty - string. - -2002-02-25 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * compat/strtoul.c, compat/strtol.c, compat/strtod.c: Added UCHAR, - CONST and #includes to clean up GCC output. - -2002-02-23 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - --- 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 - - * 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 - - * 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 - - * generic/tcl.h: Better guessing of LP64/ILP32 architecture, but now - sensitive to presence of (suitable) - -2002-02-20 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * changes: First draft of updated changes for 8.4a4 release. - -2002-02-15 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - +----------------------+ - | 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 - - * generic/tclIOCmd.c (Tcl_GetsObjCmd): Trivial fix for [Bug 517503], a - memory leak reported by Miguel Sofer . The leak - happens if an error occurs for "set var [gets $chan]" and leak one - empty object. - -2002-02-12 David Gravereaux - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tclUnixChan.c (FileOutputProc): Fixed [bug 465765] reported by - Dale Talcott . 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 - - * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): handle quirky about case - earlier to avoid shimmering problem. - -2002-02-01 Andreas Kupries - - * 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 - - * generic/tclTest.c: fix to picky windows compiler problem with the - 'MainLoop' function declaration. - -2002-01-31 Andreas Kupries - - * win/tclWinFCmd.c: TIP 27: Applied patch fixing CONST warnings on - behalf of Don Porter . - -2002-01-30 Don Porter - - * 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 - - * doc/FileSystem.3: added documentation for 3 public functions which - had been overlooked. [Bug 507701] - * unix/mkLinks: make mklinks - -2002-01-29 Jeff Hobbs - - * tests/regexpComp.test: - * generic/tclCompCmds.c (TclCompileRegexpCmd): enhanced to support - -nocase and -- options. - -2002-01-28 Mo DeJong - - * 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 - - * 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 - - * 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 - - * doc/package.n: Documented global namespace context for script - evaluation by [package require]. - -2002-01-27 Daniel Steffen - - * 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 - - 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 - - * 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 - - * generic/tclIOUtil.c (SetFsPathFromAny): Corrected tilde-substitution - of pathnames where > 1 separator follows the ~. [Bug 504950] - -2002-01-24 Jeff Hobbs - - * 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 - - * 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 - . - -2002-01-23 Don Porter - - * 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 - - * generic/tclLoadNone.c: TclpLoadFile() didn't match proto of typedef - Tcl_FSLoadFileProc. OK'd by vincentdarley. [Patch 502488] - -2002-01-21 Andreas Kupries - - * generic/tclIO.c (WriteChars): Fix for [Bug 506297], reported by - Martin Forssen . 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 - - * 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 - - * 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 - - * 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 - - * generic/tclIOCmd.c (Tcl_GetsObjCmd): Fixed [Bug 504642] as reported - by Brian Griffin , 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinSerial.c (SerialSetOptionProc): Applied patch for [Bug - 500348] supplied by Rolf Schroedter . 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 - - * 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 - - * 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 , - Kevin Kenny - - * 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 , - Kevin Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * mac/tclMacTime.c (TclpGetTZName): fix for daylight savings TZName bug - -2002-01-03 Don Porter - - * doc/FileSystem.3: - * generic/tclIOUtil.c: Updated some old uses of "fileName" to - new VFS terminology, "pathPtr". - -2002-01-03 Donal K. Fellows - - * 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 - - * 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 Index: ChangeLog.2003 ================================================================== --- ChangeLog.2003 +++ /dev/null @@ -1,3349 +0,0 @@ -2003-12-25 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBinary.c (DeleteScanNumberCache): fixed crashing bug when - numeric scan-value cache contains NULL value. - -2003-12-17 Vince Darley - - * 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 - - * generic/tclPathObj.c: - * tests/fileSystem.test: fix and tests for [Bug 860402] in new file - normalization code. - -2003-12-17 Zoran Vasiljevic - - * 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 - - * 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 - - * generic/tclThreadAlloc.c (binfo): Made variable file-local. - -2003-12-15 David Gravereaux - - * 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 [Patch 758097]. - -2003-12-14 David Gravereaux - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/configure: - * unix/tcl.m4: updated OpenBSD build configuration based on - [Patch #775246] (cassoff) - -2003-12-09 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * doc/lset.n: fix typo [Bug 852224] - -2003-11-24 Don Porter - - * 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 - - * 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 - - * tests/winFCmd.test (winFCmd-16.10,11): Merged new tests from - core-8-4-branch. - -2003-11-20 Miguel Sofer - - * generic/tclVar.c: fix flag bit collision between LOOKUP_FOR_UPVAR - and TCL_PARSE_PART1 (deprecated) [Bug 835020] - -2003-11-19 Don Porter - - * tests/compile.test (compile-16.22.0): Improved test for the recent - fix for Bug 845412. - -2003-11-19 Donal K. Fellows - - * 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 - - * contrib/djgpp/Makefile: Changes from Victor Wagner - * contrib/djgpp/langinfo.c (new): for better - * contrib/djgpp/langinfo.h (new): DJGPP support. - * unix/tclUnixInit.c: . - * unix/tclUnixChan.c: . - * unix/tclUnixFCmd.c: . - -2003-11-17 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * contrib/djgpp/Makefile: Suggested changes from vitus@45.free.net - (Victor Wagner) - - * unix/tclUnixPort.h: added socklen_t typedef for DJGPP - -2003-11-10 Don Porter - - * 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 - - * 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 - - * generic/tclCmdAH.c: - * tests/fCmd.test: fix to misleading error message in 'file link'. - [Bug 836208] - -2003-11-07 Vince Darley - - * generic/tclIOUtil.c: fix to compiler warning/error with some - compilers. [Bug 835918] - -2003-11-07 Daniel Steffen - - * macosx/Makefile: optimized builds define NDEBUG to turn off - ThreadAlloc range checking. - -2003-11-05 Don Porter - - * 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 - - * macosx/Makefile: added 'test' target. - -2003-11-03 Vince Darley - - * 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 - - * 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 - - * generic/tclExecute.c (NEXT_INST macros): replaced macro variable - "result" by "resultHandling" to avoid confusion. - -2003-10-23 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * tools/tcltk-man2html.tcl: fixed incorrect html generated for - .IP/.TP lists, now use
...
...

...
...
- instead of illegal

...
...

...
...
. - 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 - - * win/tclWinPipe.c (BuildCommandLine): Applied the patch coming with - [Bug 805605] to the code, fixing the incorrect use of ispace noted by - Ronald Dauster . - -2003-10-20 Kevin B. Kenny - - * 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 - - * 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 - - * win/tclAppInit.c (sigHandler): Punt gracefully if exitToken has - already been destroyed. - -2003-10-14 Vince Darley - - * generic/tclCmdMZ.c: - * tests/regexp.test: fix to [Bug 823524] in regsub; added three new - tests. - -2003-10-14 Don Porter - - * 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 - - 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 - - * 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 - - * unix/tclUnixTest.c (TestalarmCmd): don't bother checking return - value of alarm. [Bug #664755] (english) - -2003-10-09 Pat Thoyts - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * macosx/Makefile: fixed redo prebinding bug when DESTDIR="". - * mac/tclMacResource.c: fixed possible NULL dereference (bdesgraupes). - -2003-09-29 Vince Darley - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * trace.test: removed 'knownBug' from a test which doesn't illustrate - a bug, just a bad test. - -2003-09-23 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/catch.n: Updated [catch] docs to cover new TIP 90 features. - -2003-08-29 Don Porter - - * 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 - - * 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 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinSerial.c (SerialErrorStr): Fixed a syntax error created in - the previous code cleanup. - -2003-08-19 Donal K. Fellows - - * win/tclWinSerial.c: Adjusted commenting and spacing usage to follow - the principles of the Style Guide better. - -2003-08-18 Mo DeJong - - * 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 - - * 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 - - TIP #136 IMPLEMENTATION from Simon Geard - * 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 - - * win/tclWinInit.c: recognize amd64 and ia32_on_win64 cpus. - -2003-08-06 Don Porter - - * 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 - - * 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 - - * doc/FileSystem.3: - * doc/Translate.3: better documentation of Tcl_TranslateFileName and - related functions. [Bug 775220] - -2003-07-24 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * test/cmdAH.test: ensure certain tests run in local filesystem. [Bug - 748960] - -2003-07-18 Daniel Steffen - - * macosx/Makefile: added option to allow installing manpages in - addition to default html help. - -2003-07-18 Donal K. Fellows - - * doc/Utf.3: Tightened up documentation of Tcl_UtfNext and Tcl_UtfPrev - to better match the behaviour. [Bug 769895] - -2003-07-18 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/dltest/pkga.c (Pkga_EqObjCmd): Fix typo that was causing a - crash in load.test. - -2003-07-15 Donal K. Fellows - - * doc/array.n: Make sure docs are synched with the 8.4 release. - -2003-07-15 Don Porter - - * 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 - - * win/rules.vc: Added a missing $(OPTDEFINES) which broke the build if - STATS=memdbg was specified. - -2003-07-15 Donal K. Fellows - - * generic/tclCmdIL.c (SortCompare): Cleared up confusing error - message. [Bug 771539] - -2003-07-11 Donal K. Fellows - - * 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 - - * 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 - - * tests/winFCmd.test: fix for five tests under win98 [Bug 767679] - -2003-07-07 Jeff Hobbs - - * doc/array.n: add examples from Welton - -2003-06-23 Vince Darley - - * doc/file.n: clarification of 'file tail' behaviour [Bug 737977] - -2003-07-04 Donal K. Fellows - - * 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 - - * generic/tclTrace.c: fix to Window debug build compilation error. - -2003-06-27 Don Porter - - * 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 - - * tests/init.test: Added tests init-4.6.* to illustrate [Bug 760872] - -2003-06-25 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * generic/tclHash.c (Tcl_HashStats): Prevented occurrence of - division-by-zero problems. [Bug 759749] - -2003-06-24 Mo DeJong - - * unix/tclUnixPort.h: #undef inet_ntoa before #define to avoid - compiler warning under freebsd. [Bug 745844] - -2003-06-23 Pat Thoyts - - * 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 - - * 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 - - * generic/tclNamesp.c (Tcl_Export): removed erroneous comments. [Bug - 756744] - -2003-06-17 Vince Darley - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tclUnixTime.c: Corrected a bug in conversion of non-ASCII - chars in the format string. - -2003-05-19 Daniel Steffen - - * 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 - - * 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 - - * 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 - - * unix/Makefile.in: Removed one excess source file tclDToA.c - -2003-05-16 Daniel Steffen - - * macosx/Tcl.pbproj/project.pbxproj: updated copyright year. - -2003-05-15 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * generic/tclIOUtil.c: ensure cd is thread-safe. - [Bug 710642] (vasiljevic) - -2003-05-13 Donal K. Fellows - - * generic/tclEvent.c (Tcl_Finalize): Removed unused variable to reduce - compiler warnings. [Bug 664745] - -2003-05-13 Joe Mistachkin - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c (Tcl_HideCommand): Fixed error message for - grammar and spelling. - -2003-04-28 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/socket.n: Added a paragraph to remind people to specify their - encodings when using sockets. [Bug 630621] - -2003-04-16 Donal K. Fellows - - * doc/CrtMathFnc.3: Functions also have to deal with wide ints, but - this was not documented. [Bug 709720] - -2003-04-16 Vince Darley - - * generic/tclPathObj.c: removed undesired 'static' for function which - is now shared (previously it was duplicated). - -2003-04-15 Joe English - - * doc/namespace.n: added example section "SCOPED SCRIPTS", supplied by - Kevin Kenny. [Bug 219183] - -2003-04-15 Kevin Kenny - - * 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 - - * generic/tclIOUtil.c: finished check-in from yesterday, removing - duplicate function definition. - -2003-04-14 Don Porter - - * generic/tclClock.c: Corrected compiler warnings. - * generic/tclTest.c: - -2003-04-14 Mo DeJong - - * 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 - - * win/tclWinFile.c: added conditionals to restore compilation on - VC++6, which was broken by recent changes. - -2003-04-14 Vince Darley - - * 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 - - * 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 - - * win/Makefile.in (GENERIC_OBJS): add missing tclPathObj.c - -2003-04-12 Kevin Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/binary.n: Fixed typo in [binary format w] desc. [Bug 718543] - -2003-04-08 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * library/dde/pkgIndex.tcl: bumped version to 1.2.2 in tclWinDde.c, - now adding here too. - -2003-03-22 Kevin Kenny - - * 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 - - * 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 - - * 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 - - * generic/tclCompile.c: - * tests/compile.test: bad command count on TCL_OUT_LINE_COMPILE. - [Bug 705406] (Don Porter) - -2003-03-19 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/format.test: Renumber tests, a bunch of tests all had the same - id. - -2003-03-17 Donal K. Fellows - - * 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 - - * 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 - - * win/tcl.m4 (SC_WITH_TCL): Port version number fix that was made in - tk instead of tcl sources. - -2003-03-13 Mo DeJong - - 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 - - * 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 - - * win/makefile.vc: Added two missing uses of $(DBGX) so that - tclpip8x.dll loads without panicking on Win9x. - -2003-03-09 Kevin Kenny - - * generic/tclTest.c (TestChannelCmd): Removed an unused local variable - that caused compilation problems on some platforms. - -2003-03-08 Don Porter - - * doc/tcltest.n: Added missing "-body" to example. Thanks to Helmut - Giese. [Bug 700011] - -2003-03-07 Mo DeJong - - * 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 - - * 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 - - * 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 - - * tests/io.test: Doh! Undo accidental commenting out of a couple of - tests. - -2003-03-06 Mo DeJong - - * 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 - - * 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 - - * 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 - - * generic/tclCompCmds.c (TclCompileSwitchCmd): - Replaced a non-portable 'bzero' with a portable 'memset'. [Bug 698442] - -2003-03-06 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/rules.vc: updated default tcl version to 8.5. - -2003-03-05 Donal K. Fellows - - * 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 - - * 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 - - *** 8.4.2 TAGGED FOR RELEASE *** - -2003-03-03 Daniel Steffen - - 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 - - * win/Makefile.vc: corrected bug introduced by 'g' for debug builds. - -2003-03-03 Don Porter - - * 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 - - * 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 - - * doc/file.n: subcommand is 'file volumes' not 'file volume' - -2003-02-27 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * generic/tclCmdMZ.c (TraceCommandProc): Fix mem leak when deleting a - command that had trace on it. [Bug 693564] (sofer) - -2003-02-25 Don Porter - - * 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 - - * tests/pid.test: See below [Bug 678412]. - * tests/io.test: Made more robust against spaces in paths [Bug 678400] - -2003-02-25 Miguel Sofer - - * tests/execute.test: cleaning up testobj's at the end, to avoid - leak warning by valgrind. - -2003-02-22 Zoran Vasiljevic - - * generic/tclEvent.c (Tcl_FinalizeThread): Fix [Bug 571002] - -2003-02-21 Donal K. Fellows - - * 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 - - * mac/tclMacChan.c (TclpCutFileChannel, TclpSpliceFileChannel): - Implemented missing cut and splice procs for file channels. - -2003-02-21 Don Porter - - * 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 - - * 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 - - * 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 - - * doc/regsub.n: Typo fix [Bug 688943] - -2003-02-19 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclTest.c: cleanup of new 'simplefs' test code, and better - documentation. - -2003-02-17 Miguel Sofer - - * generic/tclBasic.c (TclRenameCommand): fixing error in previous - commit. - -2003-02-17 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * tests/notify.test: Removed Windows line terminators. [Bug 687913]. - -2003-02-15 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclParse.c (CommandComplete): - * tests/parse.test: fix for [Bug 684744], by Don Porter. - -2003-02-11 Jeff Hobbs - - * 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 - - * 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 - - * doc/append.n: Return value was not documented. [Bug 683188] - -2003-02-10 Vince Darley - - * 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 - - * library/safe.tcl: code cleanup of eval and string comp use. - -2003-02-07 Vince Darley - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/main.test: Constrain tests that do not work on Windows. [Bug - 674387] - -2003-01-28 Vince Darley - - * 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 - - * 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 - - * win/README: Update msys+mingw URL to release 6. This version bundles - gcc 3. - -2003-01-26 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/namespace.n (namespace inscope): Clarified documentation - [Patch 670110] - -2003-01-21 Mo DeJong - - * 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 - - * generic/tclCkalloc.c: change %ud to %u as appropriate. - -2003-01-17 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclClock.c (FormatClock): corrected typo that incorrectly - conditionally defined savedTZEnv and savedTimeZone. - -2003-01-13 Mo DeJong - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompCmds.c (TclCompileReturnCmd): Corrected off-by-one - problem with recent commit. [Bug 633204] - -2003-01-09 Vince Darley - - * 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 - - * generic/tclExecute.c (TclExprFloatError): Use the IS_NAN macro for - greater clarity of code. - -2003-01-07 Don Porter - - * 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 - - * 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 Index: ChangeLog.2004 ================================================================== --- ChangeLog.2004 +++ /dev/null @@ -1,4619 +0,0 @@ -2004-12-29 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclVar.c (TclArrayObjCmd - ARRAY_NAMES): leaking an object - [Bug 1084111] - thanks to Rolf Ade. - -2004-12-12 Miguel Sofer - - * generic/tclObj.c (TclSetCmdNameObj): special handling for fully - qualified command names (as in fix [Patch 456668]). - -2004-12-11 Miguel Sofer - - * generic/tclInt.h: - * generic/tclNamesp.c: converting the static function - GetNamespaceFromObj() to MODULE_SCOPE TclGetNamespaceFromObj(). - -2004-12-10 Donal K. Fellows - - * 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 - - * 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 - - * generic/tclInt.h: Move ensemble API decls here from tclNamesp.c - -2004-12-09 Donal K. Fellows - - * 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 - - * 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 - - *** 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 - - * 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 - - * tests/safe.test: Trim auto_path to improve performance [1080039] - - * tests/msgcat.test: makeFile/removeFile cleanup [1079117] - -2004-12-04 Don Porter - - * 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 - - * changes: updated for 8.5a2 release - -2004-12-02 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/Thread.3: - * doc/Notifier.3: Added changes from the core-8-4-branch - -2004-11-25 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/AddErrInfo.3: Typo corrections (Thanks Daniel South). - * doc/interp.n: - -2004-11-19 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tclUnixChan.c (TtySetOptionProc): fixed crash configuring - -ttycontrol on a channel. [Bug 1067708] - -2004-11-16 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/tclvars.n: Added section to documentation on global variables - that are specific to tclsh and wish. [Patch 1065732] - -2004-11-12 Jeff Hobbs - - * generic/tclEncoding.c (TableFromUtfProc): correct crash condition - when TCL_UTF_MAX == 6. [Bug 1004065] - -2004-11-12 Donal K. Fellows - - * doc/interp.n: Basic documentation of the TIP#221 API. - -2004-11-12 Don Porter - - 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 - - * 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 - - * 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 - - * 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 - before forcing the use of to make things - work on NetBSD 2.0. [Bug 1064882] - - * doc/binary.n, doc/upvar.n: More minor fixes. - -2004-11-12 Daniel Steffen - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/winFile.test: added contraint to winFile-4.0 to prevent it - being run on NT4 [Bug 981829] - -2004-11-05 Donal K. Fellows - - * 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 - - * changes: Updates toward an 8.5a2 release. - -2004-11-03 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c (TclExecuteByteCode): Improved version of the - NaN fix from Miguel Sofer. [Bug 761471] - -2004-11-02 Kevin Kenny - - * 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 - - * win/tclWinFile.c: Simplify TclpUtime to use Tcl_FSGetNativePath, and - add comments. - -2004-11-02 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/format.test (format-19.1): Additional regression test for [Bug - 868489]. - -2004-10-27 Donal K. Fellows - - * doc/*.n: Many small general documentation fixes. - -2004-10-26 David Gravereaux - - * 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 - - * 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 - - * 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 - - * generic/tclInt.h: - * generic/tclVar.c: removed more direct references to the VAR flags, - replaced with access macros. - -2004-10-26 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 for finding - these bugs. - -2004-10-22 Donal K. Fellows - - * generic/tclExecute.c (TclCompEvalObj, Tcl_ExprObj): - * generic/tclProc.c (TclProcCompileProc): Always call object - freeIntRepProc's in the same way. - -2004-10-22 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclResult.c: removed unused variable [Bug 1048588]. Thanks - to Daniel South. - -2004-10-15 Don Porter - - * 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 - - 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 - - * 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 - - 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 - - * generic/tclTest.c (TestsetobjerrorcodeCmd): Simplified. - -2004-10-07 Vince Darley - - * 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 - - * *.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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/subst.test (12.1-2): added tests for [Bug 1036649] - -2004-09-29 Don Porter - - * tests/basic.test (49.*): New tests for TCL_EVAL_GLOBAL. - -2004-09-29 Donal K. Fellows - - * 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 - - * generic/tclBasic.c (TclObjInvoke): fix for bogus gcc warning about - uninitialised variable. - -2004-09-27 Don Porter - - * 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 - - * 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 - - * 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 - - * doc/FileSystem.3: fix to small typo. - -2004-09-26 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/error.test (error-6.2,3): Added more tests to verify - ::errorCode setting by/after a [catch]. - -2004-09-19 Miguel Sofer - - * generic/tclCmdAH.c: removed outdated comment [Bug 1029518]. - -2004-09-18 David Gravereaux - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c (INST_CONCAT1): fix for [Bug 1025834]; avoid - unnecessary string copies. - -2004-09-10 David Gravereaux - - * tests/tcltest.test: tcltest-12.3-4 needed to have - ::tcltest::loadScript set to empty in their -setup - -2004-09-10 Donal K. Fellows - - * 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 - - * generic/tcl.h: Micro formatting fixes. - * generic/tclIOGT.c: Channel version fixed, must be 3, to have - wideseekProc. Thanks to David Graveraux . - -2004-09-11 Don Porter - - * 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 - - * 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 - - * 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 - - * win/tclWinConsole.c: Calls to WriteFile and WriteConsoleA changed to - WriteConsole for simplicity. - -2004-09-09 Don Porter - - * 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 - - * 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 - - * 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 - - * win/makefile.vc: some quoting needed to be removed as it was - breaking with VC7. [Bug 1023150] - -2004-09-07 Kevin B. Kenny - - * 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 - - * 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 - - * unix/tclUnixFCmd.c: Stop NULL interp arguments from triggering a - crash when an error happens. [Bug 1020538] - -2004-09-02 Donal K. Fellows - - * doc/lsearch.n: Clarified meaning of -dictionary. [Bug 759545] - -2004-09-02 Vince Darley - - * win/makefile.vc: clock.tcl needs to be installed. - -2004-09-01 Jeff Hobbs - - * 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 - - * doc/regsub.n, doc/RegConfig.3, doc/Environment.3: - * doc/CrtChannel.3, doc/safe.n: Use correct abbreviations. - -2004-08-31 Donal K. Fellows - - * 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 - - * 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 - - * unix/Makefile.in (install-libraries): portable sh fix. - -2004-08-30 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/string.n: Added clarifying note. - -2004-08-23 Don Porter - - * library/auto.tcl: Updated [tcl_findLibrary] search path to - include any [::pkgconfig get scriptdir,runtime] directory, as - well as the $::auto_path. [RFE 695441] - -2004-08-21 Kevin B. Kenny - - * 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 - - * generic/tclScan.c (Tcl_ScanObjCmd, ValidateFormat): Ensure that the - %ld conversion works correctly on 64-bit platforms. [Bug 1011860] - -2004-08-19 Kevin Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/io.test: Make io-61.1 create file as binary to pass on Win32 - -2004-07-23 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclwinThrd.c: redefined MASTER_LOCK to call TclpMasterLock. - Fixes [Bug 987967] - -2004-07-17 Vince Darley - - * 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 - - * 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 - - * 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 . - - * tests/socket.test: Accepted two new testcases by Stuart Casoff - 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 - - * 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 - - * 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 - - * 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 - - * 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 - . - -2004-07-15 Zoran Vasiljevic - - * 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 - - * generic/tclLiteral.c (TclReleaseLiteral): Removed unused variable - 'codePtr' to silence a message from VC++. - -2004-07-15 Miguel Sofer - - * 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 - - * generic/tclEvent.c (NewThreadProc): Backout of changes to fix the - [Bug 770053]. See SF bugreport for more info. - -2004-07-11 Miguel Sofer - - * generic/tclBasic.c (Tcl_EvalEx): leak fix by dgp, release - objv[objectsUsed] on error. - -2004-07-11 Miguel Sofer - - * generic/tclParse.c (Tcl_SubstObj): leak fix by dgp, release result - on error. - -2004-07-11 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinInit.c (AppendEnvironment): Silenced a compilation warning - about a type mismatch. - -2004-07-07 Miguel Sofer - - * 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 - - * generic/tclCmdMZ.c (TclMergeReturnOptions): Simplified logic and - removed potential memory leak. [Bug 986257]. - -2004-07-07 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/fileSystem.test: Added test for [Bug 970529] - -2004-07-01 Donal K. Fellows - - * 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 - - * tests/fileSystem.test: Minor correction to new fileSystem-9.X tests - so that they clean up temporary directories correctly. - -2004-06-30 Vince Darley - - * 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 - - 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 - - * win/tclWinInit.c: Corrected reference counting flaw in recent - changes. Thanks to Pat Thoyts. [Bug 981893]. - -2004-06-29 Vince Darley - - * win/tclWin32Dll.c: fix to compilation with VC++ 5.2 - -2004-06-29 Donal K. Fellows - - * 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 - - * tests/unixNotfy.test: Modified constraints so that testing with a - threaded tclsh (not tcltest) will not hang. - -2004-06-23 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tcl.m4: autoconf 2.5 fixes in Darwin section. - * unix/configure: autoconf-2.57 - -2004-06-18 Donal K. Fellows - - * unix/tclUnixInit.c (localeTable): Added some more locale to encoding - mapping info from Jim Huang - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompile.c: - * generic/tclExecute.c: handle warning [Bug 969066] - -2004-06-08 Donal K. Fellows - - * 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 - - * doc/lsearch.n: Added correct option to example. [Bug 968219] - -2004-06-05 Kevin B. Kenny - - * 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 - - * generic/tcl.h: Restored #include 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 - - * 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 - - * 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 - - * doc/file.n: fix to documentation of 'file volumes' (Bug 962435) - -2004-06-01 David Gravereaux - - * 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 - - * 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 - - * 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 - - * doc/global.n, doc/interp.n, doc/lrange.n: Fix minor markup errors. - -2004-05-28 Donal K. Fellows - - * doc/*.n: Added examples to many (too many to list) more man pages. - -2004-05-25 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * docs/global.n: added details for qualified variable names [Bug - 959831] - -2004-05-25 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclInterp.c (TclInitLimitSupport): Made limits work on - platforms where sizeof(void*)!=sizeof(int). [Bug 959193] - -2004-05-24 Miguel Sofer - - * doc/set.n: accurate description of name resolution process, - referring to namespace.n for details [Bug 959180] - -2004-05-23 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/append.n, doc/upvar.n: Added example. - -2004-05-18 David Gravereaux - - * win/makefile.vc: now generates a tclConfig.sh from Pat Thoyts [Patch - 909911] - -2004-05-18 Donal K. Fellows - - * 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 - - * generic/tclExecute.c (TclExecuteByteCode): added comments to - classify the variables according to their use in TEBC. - -2004-05-17 Donal K. Fellows - - * 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 - - * win/tclWinFile.c: - * tests/cmdAH.test: fix to (Bug 954263) where 'file executable' was - case-sensitive. - -2004-05-17 Donal K. Fellows - - * doc/OpenFileChnl.3: Documented type of 'offset' argument to Tcl_Seek - was wrong. [Bug 953374] - -2004-05-16 Miguel Sofer - - * generic/tclExecute.c (TclExecuteByteCode): remove one level of - indirection for compiledLocals addressing. - -2004-05-16 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - 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 - - * doc/split.n, doc/join.n: Updated examples and added more. - -2004-05-11 Vince Darley - - * doc/glob.n: documented behaviour of symbolic links with 'glob -types - d' (Bug 951489) - -2004-05-11 Donal K. Fellows - - * doc/scan.n: Updated the examples to be clearer about their relevance - to the scan command. - -2004-05-10 Donal K. Fellows - - * doc/scan.n: Added examples. - -2004-05-10 David Gravereaux - - * 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 - - * generic/tclFileName.c: - * generic/tclIOUtil.c: remove some compiler warnings on MacOS X. - -2004-05-07 Chengye Mao - - * 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 - - * doc/format.n: Added examples. - -2004-05-07 Miguel Sofer - - * doc/unset.n: added upvar.n to the "see also" list - -2004-05-07 Reinhard Max - - * 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 - - * 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 - - * 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 - - * doc/break.n, doc/continue.n, doc/for.n, doc/while.n: More examples. - -2004-05-05 Don Porter - - * 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 - - * doc/CrtObjCmd.3: Remove reference to Tcl_RenameCommand; there is no - such API. [Bug 848440] - -2004-05-05 David Gravereaux - - * 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 - - * 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 - - * 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 - - * generic/tclEvent.c (TclSetLibraryPath): Suppress a warning. - -2004-05-03 Andreas Kupries - - * Applied [Patch 868853], fixing a mem leak in TtySetOptionProc. - Report and Patch provided by Stuart Cassoff . - -2004-05-03 Miguel Sofer - - * generic/tclProc.c (TclCreateProc): comments corrected. - -2004-05-03 Miguel Sofer - - * generic/tclCompile.c (TclCompileScript): setting the compilation - namespace outside of the loop. - -2004-05-03 Miguel Sofer - - * 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 - - * 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 - - * library/init.tcl: Corrected unique prefix matching of - interactive command completion in [unknown]. [Bug 946952] - -2004-05-02 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/puts.n: Added a few examples. - -2004-04-29 Don Porter - - * tests/execute.test (execute-8.2): Avoid crashes when there is - limited system stack space (threads-enabled). - -2004-04-28 Miguel Sofer - - * 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 - - * doc/lsearch.n: Fixed fault in documentation of -index option [943448] - -2004-04-26 Don Porter - - * unix/tclUnixFCmd.c (TclpObjNormalizePath): Corrected improper - positioning of returned checkpoint. [Bug 941108] - -2004-04-26 Donal K. Fellows - - * 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 - - * generic/tcl.h: Removed obsolete declarations and #include's. - * generic/tclInt.h: [Bugs 926459, 926486] - -2004-04-24 David Gravereaux - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/read.n: Added example from David Welton. [Patch 938056] - -2004-04-19 Kevin B. Kenny - - * 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 - - * 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 - - * doc/FileSystem.3: Corrected documentation of Tcl_FSUtime, and the - corresponding filesystem driver Tcl_FSUtimeProc. [Bug 935838] - -2004-04-16 Donal K. Fellows - - * doc/socket.n: Added example from [Patch 936245]. - * doc/gets.n: Added example based on [Patch 935911]. - -2004-04-15 Donal K. Fellows - - * generic/tclClock.c (Tcl_ClockObjCmd): Minor fault in a [clock - clicks] error message. - -2004-04-07 Jeff Hobbs - - * 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 - - 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 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 - - * 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 - - * 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 - - * generic/tclCompile.h: removed redundant #ifdef _TCLINT [Bug 928415], - reported by tauvan. - -2004-04-02 Don Porter - - * tests/tcltest.test: Corrected constraint typos: "nonRoot" -> - "notRoot". Thanks to Steven Abner (tauvan). [Bug 928353] - -2004-04-01 Don Porter - - * generic/tclInt.h: Removed obsolete tclBlockTime* declarations. [Bug - 926454] - -2004-04-01 Vince Darley - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclPathObj.c: Fix to filename bugs recently - * tests/fileName.test: introduced [Bug 918320]. - -2004-03-29 Don Porter - - * 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 - - * 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 - - * doc/array.n: added documentation for trace-realted behaviour of - 'array get' [Bug 449893] - -2004-03-26 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclIntDecls.h: Made HEAD build on Solaris again by applying - fix recommended by Don Porter. - -2004-03-18 Reinhard Max - - * 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 - - 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 - - * 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 - - * 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 - - * unix/configure, unix/tcl.m4: add -Wno-strict-aliasing for GCC to - suppress useless type puning warnings. - -2004-03-16 Donal K. Fellows - - * doc/file.n: *roff formatting fix. [Bug 917171] - -2004-03-15 David Gravereaux - - * 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 - - 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 - - * generic/tclGetDate.y (TclGetDate): Fix so that [clock scan - -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 - - * generic/tclFileName.c: Fix to 'glob -path' near the root - * tests/fileName.test: of the filesystem. [Bug 910525] - -2004-03-08 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/dltest/pkgua.c: Fix minor syntax problems. [Bug 909288] - -2004-03-03 Jeff Hobbs - - *** 8.5a1 TAGGED FOR RELEASE *** - - * changes: updated for 8.5a1 - -2004-03-03 David Gravereaux - - * 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 - - * 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 - - * 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 - - * 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 - - * macosx/Makefile: fixed copyright year in Tcl.framework Info.plist - -2004-02-25 Don Porter - - * 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 - - * 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 - - * 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 - - 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 - - * generic/regc_locale.c (cclass): Buffer was having its size reset - instead of being released => memleak. [Bug 902562] - -2004-02-21 Donal K. Fellows - - * generic/tclLoad.c (Tcl_LoadObjCmd): Fixed memory leak due to an - improper error exit route. - -2004-02-20 David Gravereaux - - * 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 - - * 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 - - * 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 - - * generic/tclCompCmds.c (TclCompileSwitchCmd): Bozo mistake in memory - releasing order when in an error case. [Bug 898910] - -2004-02-16 Jeff Hobbs - - * generic/tclTrace.c (TclTraceExecutionObjCmd) - (TclTraceCommandObjCmd): fix possible mem leak in trace info. - -2004-02-12 Mo DeJong - - * 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 - - * win/nmakehlp.c: better macro grepping logic. - -2004-02-07 David Gravereaux - - * 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 - - * doc/clock.n: Removed reference to non-existent [file ctime]. - -2004-02-05 David Gravereaux - - * 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 - - * generic/tclFileName.c (SkipToChar): Corrected CONST and type-casting - issues that caused compiler warnings. - -2004-02-04 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclPathObj.c: fix to [Bug 883143] in file normalization - -2004-01-29 Vince Darley - - * 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 - - * 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 - - * 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 - - * doc/file.n: clarified documentation of 'file system' [Bug 883825] - * tests/fCmd.test: improved test result in failure case. - -2004-01-22 Vince Darley - - * 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 - - * doc/Panic.3: Mentions of 'panic' and 'panicVA' removed from the - documentation. - -2004-01-21 Vince Darley - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompExpr.c (CompileLandOrLorExpr): cosmetic changes. - -2004-01-12 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 Index: ChangeLog.2005 ================================================================== --- ChangeLog.2005 +++ /dev/null @@ -1,3822 +0,0 @@ -2005-12-30 Kevin B. Kenny - - * generic/tclStubLib.c: Corrected a typo in "missing Stubs table - pointer." - -2005-12-27 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * doc/Tcl.n: Clarify what is going on in variable substitution - following thread on comp.lang.tcl. - -2005-12-18 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tcl.m4, unix/configure: Fix sh quoting error reported in - bash-3.1+ [Bug 1377619] (schafer) - -2005-12-12 Kevin B. Kenny - - * doc/mathfunc.n: Changed two examples from the incorrect 'tcl::math::' - to 'tcl::mathfunc::' [Bug 1378818] - -2005-12-09 Mo DeJong - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclIO.c (TclFinalizeIOSubsystem): preserve statePtr until we - retrieve the next statePtr from it. - -2005-11-18 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/namespace.test: fix comment - -2005-11-14 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/trace.test (trace-8.9): added test to detect leak, see [Bug - 1348775]. - -2005-11-04 Pat Thoyts - - * 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 - - * 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 - - * generic/tclGetDate.y: Added abbreviations for the Korean - * library/clock.tcl: timezone. [Patch 1298737] - * generic/tclDate.c: Regenerated. - - * tools/findBadExternals.tcl: Added this script, which locates external - symbols that do not begin with 'Tcl' or 'tcl' and hence might be in - conflict with other link libraries. Thanks to George Peter Staplin for - the idea and the initial version of the script. [Bug 1263012] - - * unix/Makefile.in: Trimmed a bunch of fat out of the tommath/ - directory in 'make dist'. [RFE 1333318] - - * unix/tcl.m4: Added code to enable [load] on LynxOS. Thanks to - heidibr@users.sf.net for the patch. [Bug 1163896]. Removed the last - vestiges of GNU dld from the Unix build [RFE 1071992]. - - * unix/tclLoadDld.c: Removed. - * unix/configure: Regenerated. - -2005-11-04 Miguel Sofer - - * 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 - - * 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 - - 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 - - * 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 - - * generic/tclNamesp.c: fix for [Bugs 1338280/1337229]. Thanks Don. - * tests/trace.test: fix duplicate test numbers - -2005-10-31 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * tests/foreach.test (foreach-8.1): added test for [Bug 1189274] - -2005-10-22 Miguel Sofer - - * generic/tclExecute.c (INST_INCR_*): fixed [Bug 1334570]. Obj leak - detection and patch by Eric Melbardis. - -2005-10-21 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: Restored some optimizations of the - INST_INCR_SCALAR1_IMM opcode. - -2005-10-14 Zoran Vasiljevic - - * 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 - - * generic/tclExecute.c (TclIncrObj, TclExecuteByteCode): Tidied up a - couple of infelicitous do {...} while(0) constructs. - -2005-10-14 Pat Thoyts - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclPathObj.c (SetFsPathFromAny): TclGetString macro must not - be combined with post-increment arguments. [Bug 1325099] - -2005-10-12 Kevin Kenny - - * generic/tclExecute.c (Tcl_ExecuteByteCode, TclIncrObj): Several - common cases inlined in hopes of gaining a little performance in [incr] - -2005-10-10 Miguel Sofer - - * generic/tclCompCmds.c: New convenience macro CompileTokens(). - -2005-10-10 Don Porter - - * 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 - - * 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 on comp.lang.tcl - -2005-10-10 Miguel Sofer - - * generic/tclExecute.c: Fixing errors in last commit. (Two commits, the - second removes wrong comment). - -2005-10-09 Miguel Sofer - - * 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 - - 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 - - [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 - - * 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 - - [kennykb-numerics-branch] - - * generic/tclExecute.c: Improved performance of INST_RSHIFT and - INST_LSHIFT. - -2005-10-05 Don Porter - - [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 - - * 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 - - * 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 - - [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 - - * 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 - - * 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 - - [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 - - * 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 - - * generic/tclMain.c: Separate encoding conversion of command line - arguments from list formatting. [Bug 1306162]. - -2005-09-30 Don Porter - - [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 - - * 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 - - [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 - - * tests/binary.test (binary-14.18): Added test for [Bug 1116542] though - the bug itself was already fixed by unrelated changes. - -2005-09-26 Kevin Kenny - - [kennykb-numerics-branch] Merge updates from HEAD. - -2005-09-26 Kevin Kenny - - * 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 - - [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 - - [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 - - [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 - - * doc/ParseCmd.3: copy/paste fix [Bug 1292427] - -2005-09-15 Don Porter - - [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 - - * 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 - - * 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 - - * 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 - - [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 - - * 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 - - [kennykb-numerics-branch] Merge updates from HEAD. - -2005-09-09 Kevin Kenny - - * generic/tclStringObj.c: Added two missing casts to silence messages - from MSVC6. - -2005-09-09 Don Porter - - * 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 - - 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 - - * 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 - - * 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 - - * generic/tclObj.c (pendingObjDataKey): Added missing 'static' to stop - symbol from leaking outside the Tcl library. [Bug 1263012] - -2005-09-02 Don Porter - - [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 - - * 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 - - [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 - - * 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 - - [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 - - * 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 - - [kennykb-numerics-branch] Merge updates from HEAD. - - * generic/tclBasic.c: Restored round(.) to the Tcl 8.4 rules. - -2005-08-29 Kevin Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - [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 - - 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 - - * generic/tclStrToD.c (Tcl_DoubleDigits): Fixed the corner cases of - * tests/binary.test (binary-65.*) formatting floating point - numbers with the largest and smallest possible significands, and added - test cases for them. - -2005-08-24 Kevin Kenny - - [kennykb-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 - - [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 - - * unix/configure.in: - * win/configure: Regen. - * win/configure.in: Update minimum autoconf version to 2.59. - -2005-08-23 Kevin Kenny - - [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 - - [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 - - * unix/tclConfig.h.in: autoheader-2.59. - -2005-08-22 Don Porter - - [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 - - [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 - - [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 - - [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 - - * 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 - - * generic/tclEvent.c (Tcl_Finalize): Removed a copy-and-paste accident - that caused a (mostly harmless) double finalize of the load and - filesystem subsystems. - * tests/clock.test: Eliminated the bad test clock-43.1, and split - clock-50.1 into two tests, with a more permissive check on the error - message for an out-of-range value. - -2005-08-17 Kevin Kenny - - [kennykb-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 - - [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 - - [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 - - [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 - - [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 - - [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 - - [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 - - * 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 - - [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 - - * 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 - - [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 - - * 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 - - * generic/tclPathObj.c: fix to [file rootname] bug in optimized code - path reported on comp.lang.tcl. - -2005-08-08 Don Porter - - [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 - - * 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 - - [kennykb-numerics-branch] - * generic/tclObj.c: Rewrote Tcl_GetDoubleFromObj(). - -2005-08-05 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - [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 - - * 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 - - [kennykb-numerics-branch] Updated from HEAD - -2005-07-30 Daniel Steffen - - * unix/tclLoadDyld.c (TclpDlopen, TclpLoadMemory): workarounds for - bugs/changes in behaviour in Mac OS X 10.4 Tiger. - -2005-07-29 Donal K. Fellows - - * 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 - - * win/README: Update link to msys_mingw8.zip. - -2005-07-28 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c (INST_DICT_*): stop 2 compiler warnings for - uninitialised variables. - -2005-07-23 Donal K. Fellows - - * generic/tclExecute.c (TEBC:INST_DICT_INCR_IMM): Fix the incrementor - to work correctly with wide values. - -2005-07-21 Donal K. Fellows - - * 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 - - * 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 - - * generic/tclStrToD.c (RefineResult): Plugged a stupid memory leak in - RefineResult (called from Tcl_StrToD). [Tk Bug 1227781] - -2005-07-15 Kevin B. Kenny - - * 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 - - * 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 - - * unix/tclUnixSock.c: Use a ProcessGlobalValue to store the value - * win/tclWinSock.c: returned by Tcl_GetHostName() ([info - hostname]). Also re-order initialization of the value on Windows to - favor GetComputerName() over gethostname() as a source of the - information. - -2005-07-12 Kevin Kenny - - [kennykb-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 - - * doc/lsearch.n: Clarify documentation of -exact option; wording was - open to misinterpretation by non-English speakers. - -2005-07-11 Donal K. Fellows - - * generic/tclExecute.c: General style cleanup. - -2005-07-08 Mo DeJong - - * 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 - - * generic/tclLink.c: Simplified LinkTraceProc [Bug 1208108]. - -2005-07-05 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * library/auto.tcl: Make file safe to re-[source] without - destroying registered auto_mkindex_parser hooks. - -2005-06-23 Kevin Kenny - - * 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 - - * tools/tcltk-man2html.tcl: fixed useversion glob pattern to accept - multi-digit patchlevels. - -2005-06-22 Don Porter - - * win/tclWinFile.c: Potential buffer overflow. [Bug 1225571] Thanks to - Pat Thoyts for discovery and fix. - -2005-06-22 Kevin Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclFCmd.c: correct fix to file mkdir 2005-06-09 [Bug 1219176] - -2005-06-12 Donal K. Fellows - - * generic/tclCompCmds.c: Factor out some common idioms into named forms - for greater clarity. - -2005-06-10 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - *** 8.5a3 TAGGED FOR RELEASE *** - - * unix/Makefile.in (dist): add libtommath - -2005-06-03 Donal K. Fellows - - * 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 - - * macosx/Makefile: fixed 'embedded' target. - -2005-06-02 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/tclWinThrd.c: Fixed [Bug 1204064] - -2005-05-30 Donal K. Fellows - - 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 - - * 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 - - * generic/tclCmdMZ.c (Tcl_TimeObjCmd): add necessary cast - -2005-05-25 Don Porter - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/mathfunc.n: Changed NAME line to match the name of the page. - -2005-05-11 Kevin Kenny - - [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 - - * 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 - - * 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 - - * 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 - - Merged all changes on kennykb-numerics-branch back into the HEAD. - TIP's 132 and 232 are now Final. - -2005-05-10 Kevin Kenny - - [kennykb-numerics-branch] Merged changes from HEAD. - -2005-05-10 Miguel Sofer - - * generic/tclExecute.c (ExponLong, ExponWide): - * tests/expr.test (expr-23.34/35): fixed special case 'i**0' for i>0 - [Bug 1198892] - -2005-05-09 Kevin B. Kenny - - [kennykb-numerics-branch] - * win/tclWin32Dll.c (TclpCheckStackSpace, TclWinCPUID): Reworked - structured event handling to function even with -fomit-frame-pointers. - -2005-05-08 Kevin B. Kenny - - [kennykb-numerics-branch] - * generic/tclStrToD.c: Made code more portable by finding a workaround - for MSVC's 'volatile' issue that does not require conditional - compilation. - * win/tclWin32Dll.c (TclWinCPUID): Removed structured event handling - from the GCC code since (a) bad code is generated by the instruction - scheduling with -O2, and (b) it's not needed on any reasonably modern - CPU. - -2005-05-07 Kevin B. Kenny - - [kennykb-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 - - * unix/tcl.m4, unix/configure: correct Solaris 10 (5.10) check and add - support for x86_64 Solaris cc builds. - -2005-05-05 Kevin B. Kenny - - [kennykb-numerics-branch] Merged with HEAD. - -2005-05-05 Kevin B. Kenny - - * win/tclWinThrd.c: Corrected a compilation error on the - --enable-threads configuration. - -2005-05-05 Don Porter - - * 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 - - * 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 - - * 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 - - * unix/tclUnixNotfy.c: applied dkf's tkMacOSXNotify.c cleanup changes. - -2005-04-29 Don Porter - - 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 - - * tests/unixInit.test (7.1): Alternative fix for the 2004-11-11 commit. - -2005-04-27 Don Porter - - * 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 - - * generic/tclBinary.c (FormatNumber): Dredge the NaN out of the - internal representation if Tcl_GetDoubleFromObj returns TCL_ERROR on a - NaN. - - * generic/tclObj.c (Tcl_GetDoubleFromObj): Restored silent - overflow/underflow behaviour that the merge of 2004-04-25 messed up. - Thanks to Don Porter for calling attention to this bug. Also removed an - uninitialised memory reference in this function that valgrind caught. - Also changed to return TCL_ERROR on a pure NaN. - - * generic/tclStrToD.c (RefineResult): Added a test for the initial - approximation being HUGE_VAL; this test avoids EDOM being returned from - ldexp on some platforms on input values exceeding the floating point - range. - - * tests/expr.test (expr-29.*, expr-30.*): Added further tests of - overflow/underflow on input conversions. - -2005-04-25 Kevin B. Kenny - - [kennykb-numerics-branch] Merged with HEAD. - - * doc/CrtMathFunc.n: Revised documentation for TIP 232 - -2005-04-25 Daniel Steffen - - * 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 - - * 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 - - * library/init.tcl: Use "ni" and "in" operators. - -2005-04-25 Miguel Sofer - - * generic/tclExecute.c: fix for [Bug 1189274]. - -2005-04-24 Don Porter - - * generic/tclLiteral.c: Silence compiler warnings. - * generic/tclObj.c: [Bug 1188863]. - -2005-04-22 Don Porter - - 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 - - * doc/GetInt.3: Convert argument "string" to "str" to agree with code. - Also clarified a few details on int and double formats. - * generic/tclGet.c: Radical code simplification. Converted - Tcl_GetFoo() routines into wrappers around Tcl_GetFooFromObj(). Reduces - code duplication, and the resulting potential for inconsistency. - - * generic/tclObj.c: Several changes: - - - Re-ordered error detection code so all values with trailing garbage - receive a "not an integer" message instead of an "integer too large" - message. - - Removed inactive code meant to deal with strtoul* routines that fail - to parse leading signs. All of them do, and if any are detected that - do not, the correct fix is replacement with compat/strtoul*.c, not a - lot of special care by the callers. - - Tcl_GetDoubleFromObj now avoids shimmering away a "wideInt" intrep. - - Fixed Tcl_GetBooleanFromObj to agree with its documentation and with - Tcl_GetBoolean, accepting only "0" and "1" and not other numeric - strings. [Bug 1187123] - - Added new private routine TclGetTruthValueFromObj to perform the more - permissive conversion of numeric values to boolean that is needed by - the [expr] machinery. - - * generic/tclInt.h (TclGetTruthValueFromObj): New routine. - * generic/tclExecute.c: Updated callers to call new routine. - * generic/tclBasic.c: Updated callers to call new routine. - * generic/tclCompCmds.c: Updated callers to call new routine. - * generic/tclDictObj.c: Updated callers to call new routine. - * tests/obj.test: Corrected bad tests that actually expected - values like "47" and "0xAC" to be accepted as booleans. - - * generic/tclLiteral.c: Disabled the code that forces some literals - into the "int" Tcl_ObjType during registration. We can re-enable it if - this change causes trouble, but it seems more sensible to let Tcl's - "on-demand" shimmering rule, and not try to pre-guess things. - -2005-04-20 Kevin B. Kenny - - [kennykb-numerics-branch] - * doc/expr.n: - * doc/mathfunc.n (new file): Revised documentation for TIP 232 - -2005-04-20 Don Porter - - * 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 - - * generic/tclFileName.c: Silenced a compiler warning about '/*' within - a comment. - -2005-04-19 Don Porter - - * 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 - - * 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 - - * generic/Var.c (Tcl_ArrayObjCmd - ARRAY_NAMES): fix Tcl_Obj leak. [Bug - 1084111] - -2005-04-16 Zoran Vasiljevic - - * 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 - - * 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 - - * generic/tclExecute.c: missing semicolons caused failure to compile - with TCL_COMPILE_DEBUG. - -2005-04-13 David Gravereaux - - * 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 - 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 - - * 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 - - * 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 - - * 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 - on comp.lang.tcl that the current documentation was not clear. - -2005-04-13 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * tools/tclZIC.tcl: Rewrote to take advantage of more features of Tcl - 8.5 (on which it was dependent anyway). Also added a [package require] - line to formalize the relationship. - -2005-04-11 Kevin Kenny - - [kennykb-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 - - * 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 - - * generic/tclBasic.c (TclObjInvoke): Plug memory leak. [Bug 1180368] - -2005-04-09 Miguel Sofer - - * generic/tclExecute.c: fix possible leak of expansion Tcl_Objs - -2005-04-09 Daniel Steffen - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: small opts in obj handling - -2005-04-02 Miguel Sofer - - * generic/tclVar.c: converted a few function calls to macros. - -2005-04-01 Miguel Sofer - - * 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 - - * generic/tclExecute.c (INST_JUMP_TRUE/FALSE): replaced "test and - branch" with "compute index into table" - -2005-03-30 Donal K. Fellows - - * doc/FileSystem.3: Defined loadHandle argument. [Bug 1172401] - -2005-03-29 Jeff Hobbs - - * win/tcl.m4, win/configure: do not require cygpath in macros to allow - msys alone as an alternative. - -2005-03-24 Don Porter - - * 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 - - * 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 - - * 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 - - * unix/tcl.m4: Updated the OpenBSD configuration and regenerated - * unix/configure: the configure script. - -2005-03-15 Kevin B. Kenny - - [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 - - * generic/tclExecute.c: fixed INST_PUSH1's debugging code (wrong obj - ref passed to TRACE_WITH_OBJ). - -2005-03-14 Miguel Sofer - - * generic/tclCompile.c: fixed INST_RETURN's stack effect in - tclInstructionTable (-1 instead of -2) - -2005-03-10 Miguel Sofer - - * generic/tclCompCmds.c: removed debugging line - -2005-03-10 Don Porter - - * generic/tclTrace.c (TclCheckInterpTraces): Corrected mistaken cast - of ClientData to (TraceCommandInfo *) when not warranted. Thanks to - Yuri Victorovich for the report. [Bug 1153871] - * generic/tcl.h: Moved flag values TCL_TRACE_ENTER_EXEC and - * generic/tclInt.h: TCL_TRACE_LEAVE_EXEC from public interface into - private. Should be used only by internal workings of execution traces. - -2005-03-09 Kevin B. Kenny - - [kennykb-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 - - * win/makefile.vc: clarify necessary defined vars that can come from - MSVC or the Platform SDK. - -2005-03-07 Donal K. Fellows - - * doc/string.n: Minor typo. [Bug 1158247] - -2005-03-07 Miguel Sofer - - * generic/tclExecute.c: new peephole optimisation for INST_PUSH1; fixed - the peephole opt in INST_POP so that it is not used when - TCL_COMPILE_DEBUG is defined. - -2005-03-04 Kevin B. Kenny - - [kennykb-numerics-branch] - - * generic/tclCmdMZ.c: Changed [scan] to treat out-of-range floating - point values as infinities and zeroes. - * generic/tclExecute.c: Changed [expr] to be permissive about - infinities, allowing them to propagate. - * generic/tclGet.c: Changed Tcl_GetDouble to be permissive about - over/underflow. - * generic/tclObj.c: Changed SetDoubleFromAny to be permissive about - over/underflow. - * generic/tclParseExpr.c: Made [expr] permissive about input numbers - out of range. - -2005-03-03 Kevin B. Kenny - - [kennykb-numerics-branch] - - * generic/tclInt.h: - * generic/tclStrToD.c (Tcl_DoubleDigits, TclFormatNaN): - * generic/tclUtil.c (Tcl_PrintDouble): Changed the signature of - TclDoubleDigits so that it accepts a pointer to the signum of the - argument, and returns the signum via that pointer. Added very hacky - code to handle IEEE signed zeroes in Tcl_DoubleDigits. (It can't be - done other than as a hack until C9x; C89 simply doesn't deal with the - concept of -0.0). Added output conversion of tagged NaN values. - * generic/tclBinary.c (FormatNumber): Changed to allow [binary format] - to handle NaN. - * tests/binary.test (binary-60.1): Added a quick-n-dirty test to make - sure that NaN's can be scanned and formatted. - * generic/tclParseExpr.c (GetLexeme, ParseMaxDoubleLength): Modified so - that tagged NaN (e.g., NaN(DEADBEEF)) can be recognized. - -2005-03-02 Kevin B. Kenny - - [kennykb-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 - - * doc/CrtSlave.3: Changed to Tcl_Object to Tcl_Obj in the man page. - -2005-02-24 Don Porter - - * 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 - - * doc/CrtChannel.3 (THREADACTIONPROC): Formatting fix. [Bug 1149605] - -2005-02-17 Jeff Hobbs - - * win/tclWinFCmd.c (TraverseWinTree): use wcslen on wchar, not - Tcl_UniCharLen. - -2005-02-16 Miguel Sofer - - * doc/variable.n: fix for [Bug 1124160], variables are detected by - [info vars] but not by [info locals]. - -2005-02-11 Jeff Hobbs - - * 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 - - * tests/basic.test (basic-26.3): new test - -2005-02-10 Miguel Sofer - - * 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 - - * generic/tclFileName.c: fix for test failures introduced on 2005-01-17 - [Bug 1119092] - -2005-02-10 Donal K. Fellows - - * doc/binary.n: Made the documentation of sign bit masking and [binary - scan] consistent. [Bug 1117017] - -2005-02-08 David N. Welton - - * doc/CrtChannel.3: Typo: return->returns. - -2005-02-06 Kevin B. Kenny - - [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 - - * doc/Thread.3: One-word grammar fix. - -2005-02-05 David N. Welton - - * doc/Thread.3: Fixed sentence describing flags for Tcl_CreateThread. - - * doc/FileSystem.3: Cleaned up typo in Tcl_FSNewNativePath - documentation. - - * generic/tclPathObj.c: Cleaned up typo in comment. - -2005-02-03 Kevin B. Kenny - - [kennykb-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 - - * generic/tclProc.c (TclInitCompiledLocals): Add check for type of the - framePtr->procPtr->bodyPtr passed to TclInitCompiledLocals and panic if - it is not the correct type. If the body of the proc is not of the - compiled byte code type then the code will crash. This was discovered - while tracking down a crash in Itcl, that crash is fixed by Itcl patch - 1115085. - -2005-02-01 Kevin B. Kenny - - [kennykb-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 - - * generic/tclExecute.c (TclCompEvalObj): Removed stray statement left - behind in prior code reorganization. - -2005-01-31 Don Porter - - * unix/configure: autoconf-2.57 - -2005-01-30 Joe English - - * 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 - - * unix/configure, unix/tcl.m4: add solaris 64-bit gcc build support. - [Bug 1021871] - -2005-01-28 Donal K. Fellows - - * tests/expr-old.test (expr-old-37.2): Added test for [Bug 1109484] - -2005-01-27 Jeff Hobbs - - * generic/tclBasic.c (Tcl_ExprBoolean, Tcl_ExprDouble) - (Tcl_ExprLong): Fix to recognize Tcl_WideInt type. [Bug 1109484] - -2005-01-26 Andreas Kupries - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/FileSystem.3: Add missing ARGUMENTS section definitions for - arguments to Tcl_FSLink. [Bug 1106272] - -2005-01-21 Kevin B. Kenny - - [kennykb-numerics-branch] - - * unix/Makefile.in: Updated Makefile to build libtommath on Unix as - well as Windows. [Bug 1106865] - - * generic/tclTestObj.c (TestbignumobjCmd): Silenced a compiler warning - about a mismatched 'const'. - -2005-01-20 Kevin B. Kenny - - [kennykb-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 - - 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/winDde.test: Fixed broken test result. - -2005-01-05 Donal K. Fellows - - * 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 - - * 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 Index: ChangeLog.2007 ================================================================== --- ChangeLog.2007 +++ /dev/null @@ -1,5921 +0,0 @@ -2007-12-31 Donal K. Fellows - - * doc/dict.n: Clarified meaning of dictionary values following - discussion on comp.lang.tcl. - -2007-12-26 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * generic/tclCmdIL.c: Speed patch for lsort. [Patch 1856994] - -2007-12-21 Miguel Sofer - - * generic/tclCmdIL.c (Tcl_LsortObjCmd, Tcl_LsearchObjCmd): Avoid - calling SelectObjFromSublist when there are no sublists. - -2007-12-21 Miguel Sofer - - * 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 - - *** 8.5.0 TAGGED FOR RELEASE *** - - * changes: Updated for 8.5.0 release. - -2007-12-19 Jeff Hobbs - - * 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 - - * changes: Updated for 8.5.0 release. - -2007-12-18 Donal K. Fellows - - * 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 , Tavis Ormandy , - and Tom Lane from the Postgresql crowd for - their help in tracking these problems down. [Bug 1810264] - -2007-12-17 Don Porter - - * changes: Updated for 8.5.0 release. - -2007-12-17 Miguel Sofer - - * 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 - - * generic/tclIOUtil.c (FsAddMountsToGlobResult): fix the tail - conversion of vfs mounts. [Bug 1602539] - - * win/README: updated notes - -2007-12-14 Pat Thoyts - - * tests/winFile.test: Fixed tests for win2k with long machine name - -2007-12-14 Pat Thoyts - - * win/nmakehlp.c: Support compilation with MSVC9 for AMD64. - * win/makefile.vc: - -2007-12-13 Donal K. Fellows - - * doc/trace.n: Clarified documentation of enterstep and leavestep - traces, including adding example. [Bug 614282, 1701540, 1755984] - -2007-12-12 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/namespace.n: Documentation for zero-argument form of - [namespace import] (TIP 261) [Bug 1596416] - -2007-12-06 Jeff Hobbs - - * generic/tclInt.h: add TclGetChannelFromObj decl - (TclMatchIsTrivial): simplify TclMatchIsTrivial to remove ] check. - -2007-12-06 Donal K. Fellows - - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Prevent shimmering crash - when -exact and -integer/-real are mixed. [Bug 1844789] - -2007-12-03 Donal K. Fellows - - * unix/tclUnixChan.c (CreateSocketAddress): Add extra #ifdef-fery to - make code compile on BSD 5. [Bug 1618235, again] - -2007-12-03 Don Porter - - * 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 - - * win/configure, win/tcl.m4 (LIBS_GUI): remove ole32.lib oleaut32.lib - -2007-12-03 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclIO.c: -eofchar must support no eofchar. - -2007-11-27 Miguel Sofer - - * generic/tclBasic.c: remove unneeded call in Tcl_CreateInterp, add - comments. - -2007-11-27 Don Porter - - * 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 - - * 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 - - * generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix bug in [dict - append] compiler which caused strange stack corruption. [Bug 1837392] - -2007-11-23 Andreas Kupries - - * 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 - - * 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 - - * generic/tclCmdMZ.c (String*Cmd, TclInitStringCmd): Rebuilt [string] - * generic/tclCompCmds.c (TclCompileString*Cmd): as an ensemble. - -2007-11-22 Donal K. Fellows - - * generic/tclDictObj.c (Dict*Cmd,TclInitDictCmd): Rebuilt the [dict] - * generic/tclCompCmds.c (TclCompileDict*Cmd): command as an ensemble. - -2007-11-22 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - *** 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 - - * 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 - - * generic/tclExecute.c (TclExecuteByteCode:INST_EXIST_*): Fix read - traces not firing on non-existent array elements. [Bug 1833522] - -2007-11-16 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * macosx/Tcl.xcodeproj/project.pbxproj: add new chanio.test. - * macosx/Tcl.xcode/project.pbxproj: - -2007-11-14 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * generic/tclCompCmds.c (TclCompileRegexpCmd): clean up comments, only - free dstring on OK from TclReToGlob. - (TclCompileSwitchCmd): simplify TclReToGlob usage. - -2007-11-14 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/regcomp.c: Convert optst() from expensive no-op to a - cheap no-op. - -2007-11-13 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 . 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclUtil.c (Tcl_ConcatObj): optimise for some of the - concatenees being empty objs. [Bug 1447328] - -2007-10-28 Donal K. Fellows - - * 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 - - * generic/regc_lex.c (lexescape): Close off one of the problems - mentioned in [Bug 1810264]. - -2007-10-27 Miguel Sofer - - * 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 - - * tools/tcltk-man2html.tcl (make-man-pages, htmlize-text) - (process-text): Make the man->HTML scraper work better. - -2007-10-26 Don Porter - - *** 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompile.c: Fix comments. - * generic/tclExecute.c: - -2007-10-18 David Gravereaux - - * tools/mkdepend.tcl: sort the dep list for a more humanly readable - output. - -2007-10-18 Don Porter - - * 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 - - * tools/mkdepend.tcl: Improved defense from malformed object list - infile. - -2007-10-17 Donal K. Fellows - - * tools/man2html2.tcl: Convert .DS/.DE into HTML tables, not - preformatted text. - -2007-10-17 Kevin B. Kenny - - * 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 - - * win/makefile.vc: removed old dependency cruft that is no longer - needed. - -2007-10-15 Don Porter - - * 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 - - * 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 - - * generic/tclParse.c (Tcl_ParseBraces): fix for possible read after - the end of buffer. [Bug 1813528] (Joe Mistachkin) - -2007-10-14 David Gravereaux - - * tools/mkdepend.tcl (new): Initial stab at generating automatic - * win/makefile.vc: dependencies. - -2007-10-12 Pat Thoyts - - * 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 - - * win/makefile.vc: Fixed my bad spelling mistakes from years back. - Dedependency, duh! Rather funny. - -2007-10-11 Don Porter - - * 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 - - * generic/tclObj.c: remove superfluous #include of tclCompile.h - -2007-10-08 George Peter Staplin - - * 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 - - * 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 - - [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 - - * library/tclIndex: Added 'tcl::tm::path' to the tclIndex. This fixes - [Bug 1806422] reported by Don Porter. - -2007-09-25 Donal K. Fellows - - * 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 - - *** 8.5b1 TAGGED FOR RELEASE *** - - * changes: updates for 8.5b1 release. - -2007-09-19 Don Porter - - * 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 - - * generic/tclStubLib.: Replaced isdigit with internal implementation. - -2007-09-18 Don Porter - - * 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 - - * win/makefile.vc: Add crt flags for tclStubLib now it uses C-library - functions. - -2007-09-17 Joe English - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c (Tcl_CreateObjCommand): Only invalidate along the - namespace path once; that is enough. [Bug 1519940] - -2007-09-14 Daniel Steffen - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclLink.c (Tcl_UpdateLinkedVar): guard against var being - unlinked. [Bug 1740631] (maros) - -2007-09-10 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * generic/tclVar.c (Tcl_SetVar2, TclPtrSetVar): [Bug 1710710] fixed - correctly, reverted fix of 2007-05-01. - -2007-09-08 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompile.c: replaced copy loop that tripped some compilers - with memmove. [Bug 1780870] - -2007-08-23 Don Porter - - * 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 - - * generic/tclExecute.c (TEBC): disable the new shortcut to frequent - INSTs for debug builds. REVERTED (collision with alternative fix) - -2007-08-21 Don Porter - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c (Overflowing, TclIncrObj, TclExecuteByteCode): - Encapsulate Miguel's last change in a more mnemonic macro. - -2007-08-19 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: Provide DECACHE/CACHE protection to the - * tests/trace.test: Tcl_LogCommandInfo() call. [Bug 1773040] - -2007-08-12 Miguel Sofer - - * 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 - - * generic/tclInt.h: remove redundant ops in TclNewStringObj macro. - -2007-08-10 Miguel Sofer - - * generic/tclInt.h: fix the TclSetVarNamespaceVar macro, was causing a - leak. - -2007-08-10 Don Porter - - * 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 - - * 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 - - * generic/tclProc.c (InitLocalCache): reference firstLocalPtr via - procPtr. codePtr->procPtr == NULL exposed by tbcload. - -2007-08-08 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * library/word.tcl: Rewrote for greater efficiency. [Bug 1764318] - -2007-08-01 Pat Thoyts - - * 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 - - * generic/tclVar.c (TclCleanupVar): fix [Bug 1765225], thx Larry - Virden. - -2007-07-31 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * unix/tclUnixChan.c (SET_BITS, CLEAR_BITS): Added macros to make this - file clearer. - -2007-07-24 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * generic/tclCompExpr.c: Removed unused arguments and variables - -2007-07-17 Don Porter - - * 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 - - * 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 - - * generic/tclCompExpr.c: Factored out, corrected, and commented - common code for reporting syntax errors in LEAF elements. - -2007-07-11 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * library/init.tcl (unknown): Corrected inconsistent error message - in interactive [unknown] when empty command is invoked. [Bug 1743676] - -2007-07-05 Miguel Sofer - - * generic/tclNamesp.c (SetNsNameFromAny): - * generic/tclObj.c (SetCmdNameFromAny): Avoid unnecessary - ckfree/ckalloc when the old structs can be reused. - -2007-07-04 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclVar.c (UnsetVarStruct): fix possible segfault. - -2007-06-27 Don Porter - - * 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 - - * generic/tclBasic.c (TclEvalEx): Moved some arrays from the C - stack to the Tcl stack. - -2007-06-26 Miguel Sofer - - * generic/tclVar.c (UnsetVarStruct): more streamlining. - -2007-06-25 Don Porter - - * 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 - - * generic/tclVar.c (UnsetVarStruct): fixing incomplete change, more - streamlining. - -2007-06-24 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tcl.h, generic/tclCompile.h, generic/tclCompile.c: Remove - references in comments to obsolete {expand} notation. [Bug 1740859] - -2007-06-20 Miguel Sofer - - * generic/tclVar.c: streamline namespace vars deletion: only compute - the variable's full name if the variable is traced. - -2007-06-20 Don Porter - - * 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 - - * tools/tcltk-man2html.tcl: revamp of html doc output to use CSS, - standardized headers, subheaders, dictionary sorting of names. - -2007-06-18 Jeff Hobbs - - * tools/tcltk-man2html.tcl: clean up copyright merging and output. - clean up coding constructs. - -2007-06-18 Miguel Sofer - - * 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 - - * generic/tclBasic.c (TclEvalEx,TclEvalObjEx): Moved the CmdFrame off - the C stack and onto the Tcl stack. - -2007-06-17 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * macosx/Tcl.xcodeproj/project.pbxproj: add new Tclsh-Info.plist.in. - -2007-06-08 Donal K. Fellows - - * 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 - - * generic/tclParse.c: fix for uninit read. [Bug 1732414] - -2007-06-06 Daniel Steffen - - * 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 - - * 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 - - * generic/tclInt.h: - * generic/tclExecute.c: Tcl-stack reform, [Patch 1701202] - -2007-06-03 Daniel Steffen - - * unix/Makefile.in: add datarootdir to silence autoconf-2.6x warning. - -2007-05-30 Don Porter - - * 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 - - * unix/tclUnixThrd.c (Tcl_JoinThread): fix for 64-bit handling of - pthread_join exit return code storage. [Bug 1712723] - -2007-05-22 Don Porter - - [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 - - * 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 - - * 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 - - * generic/tcl.decls: workaround 'make checkstubs' failures from - tclStubLib.c MODULE_SCOPE revert. [Bug 1716117] - -2007-05-16 Joe English - - * 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 - - * 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 - - * generic/tclInt.h: Removed TclEvalObjEx and TclGetSrcInfoForPc from - tclInt.h now they are in the internal stubs table. - -2007-05-09 Don Porter - - * generic/tclInt.h: TclFinalizeThreadAlloc() is always defined, so - make sure it is also always declared (with MODULE_SCOPE). - -2007-05-09 Daniel Steffen - - * 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 - - [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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - *** 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/Makefile.in (dist): add platform library package to src dist - -2007-04-24 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompile.c (TclFreeCompileEnv): Tip 280's new field - extCmdMapPtr was not being freed. [Bug 1705778, leak #1] - -2007-04-23 Kevin B. Kenny - - * 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 - - * 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 - - * generic/tclListObj.c (SetListFromAny): avoid discarding internal - reps of objects converted to singleton lists. [Patch 738900] - -2007-04-20 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: fixed checkInterp logic [Bug 1702212] - -2007-04-16 Donal K. Fellows - - * various (including generic/tclTest.c): Complete the purge of K&R - function definitions from manually-written code. - -2007-04-15 Kevin B. Kenny - - * 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 - - * generic/tclExecute.c: removed some code at INST_EXPAND_SKTOP that - duplicates functionality already present at checkForCatch. - -2007-04-12 Miguel Sofer - - * 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 - - * generic/tclCompCmds.c: moved all exceptDepth management to the - macros - the decreasing half was managed by hand. - -2007-04-10 Donal K. Fellows - - * 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 - - * generic/tclCompile (tclInstructionTable): Fixed bugs in description - of dict instructions. - -2007-04-07 Miguel Sofer - - * generic/tclCompile (tclInstructionTable): Fixed bug in description - of INST_START_COMMAND. - - * generic/tclExecute.c (TEBC): Small code reduction. - -2007-04-06 Miguel Sofer - - * 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 - - * generic/tclExecute.c: INST_INVOKE optimisation. [Patch 1693802] - -2007-04-03 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: optimise the lookup of elements of indexed - arrays. - -2007-03-29 Miguel Sofer - - * 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 - - * 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 - - * generic/tclCmdMZ.c (STR_MAP): Replace ckalloc calls with - TclStackAlloc calls. - -2007-03-24 Zoran Vasiljevic - - * 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 - - * generic/tclBasic.c (DeleteInterpProc): pop the root frame pointer - before deleting the global namespace [Bug 1658572] - -2007-03-23 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * generic/tclEnv.c: Some more ckalloc -> ckrealloc replacements. - * generic/tclLink.c: - -2007-03-20 Kevin B. Kenny - - * 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 - - * 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 - - * doc/regsub.n: Corrected example so that it doesn't recommend - potentially unsafe practice. Many thanks to Konstantin Kushnir - for reporting this. - -2007-03-17 Kevin B. Kenny - - * 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 - - * 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 - - * win/Makefile.in: Fully qualify LIBRARY_DIR so that `make test` does - not depend on working dir. - -2007-03-15 Mo DeJong - - * tests/parse.test: Add two backslash newline parse tests. - -2007-03-12 Don Porter - - * 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 - - * generic/tclCmdIL.c (Tcl_LsortObjCmd): Fix problems with declaration - positioning and memory leaks. [Bug 1679072] - -2007-03-11 Donal K. Fellows - - * 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 - - * generic/tclCmdIL (Tcl_LsortObjCmd): changed fix to [Bug 1675116] to - use the cheaper TclListObjCopy() instead of Tcl_DuplicateObj(). - -2007-03-09 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclLink.c (LinkedVar): Added macro to conceal at least some - of the pointer hackery. - -2007-03-02 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/tcltest.n: Typo fix. [Bug 1663539] - -2007-02-20 Pat Thoyts - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/re_syntax.n: Corrected description of 'print' class [Bug - 1614687] and enhanced description of 'graph' class. - -2007-02-12 Kevin B. Kenny - - * 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 - - * win/nmakehlp.c: Properly cleanup after nmakehlp, including the - * win/makefile.vc: vcX0.pch file. - -2007-02-08 Jeff Hobbs - - * 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 - - * 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 - - * generic/tclNamesp.c: Corrected broken implementation of the - * tests/namespace.test: TclMatchIsTrivial optimization on [namespace - children $namespace $pattern]. - -2007-02-04 Daniel Steffen - - * 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 - - * win/rules.vc: Fix platform specific file copy macros for downlevel - Windows. - -2007-01-29 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclIO.c: Added macros to make usage of ChannelBuffers - clearer. - -2007-01-11 Joe English - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclDate.c: Regenerated to recover a lost fix from patthoyts. - [Bug 1618523] - -2006-12-26 Mo DeJong - - * 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 - - * 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 - - * unix/tclUnixThrd.c (Tcl_GetAllocMutex, TclpNewAllocMutex): Add - intermediate variables to shut up unwanted warnings. [Bug 1618838] - -2006-12-19 Daniel Steffen - - * 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 - - * 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 - - * doc/string.n: Fix example. [Bug 1615277] - -2006-12-12 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * library/tcltest/tcltest.tcl: use [info frame] for "-verbose line". - -2006-12-07 Don Porter - - * 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 - - * 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 - - * tests/exec.test: Fixed line endings (caused win32 problems). - -2006-12-06 Don Porter - - * 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 - - * tests/expr.test (expr-47.12): Improved error reporting in hopes of - having more information to pursue [Bug 1609936]. - -2006-12-05 Andreas Kupries - - 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 - - * 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 - - 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 - - * 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 - - * 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 - - * doc/file.n: Clarification of [file pathtype] docs. [Bug 1606454] - -2006-12-01 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c (TclIncrObj): Correct failure to detect - floating-point increment values. Thanks to William Coleda [Bug - 1602991] - -2006-11-26 Donal K. Fellows - - * 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 - - * unix/tcl.m4 (Linux): --enable-64bit support. [Patch 1597389] - * unix/configure: autoconf-2.59 [Bug 1230558] - -2006-11-25 Donal K. Fellows - - 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 - - * 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 - - 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 - - * 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 - - * 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 - - * 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 - - * doc/apply.n, doc/chan.n: Added examples. - -2006-11-15 Don Porter - - 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 - - * 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 - - TIP#261 IMPLEMENTATION - - * generic/tclNamesp.c: [namespace import] with 0 arguments - introspects the list of imported commands. - -2006-11-13 Kevin B. Kenny - - * generic/tclThreadStorage.c (Tcl_InitThreadStorage): - (Tcl_FinalizeThreadStorage): Silence a compiler warning about - presenting a volatile pointer to 'memset'. - -2006-11-13 Don Porter - - * 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 - - * 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 - - * generic/tclInt.h, generic/tclInt.decls: Transfer TclPtrMakeUpvar and - TclObjLookupVar to the internal stubs table. - -2006-11-10 Daniel Steffen - - * 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 - - * 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 - - 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 - - * generic/tclIO.c, generic/tclPkg.c: Style & clarity rewrites. - -2006-11-07 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * macosx/Tcl.xcodeproj/project.pbxproj: check autoconf/autoheader exit - status and stop build if they fail. - -2006-11-02 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/rules.vc: Fix for [Bug 1582769] - options conflict with VC2003. - -2006-10-31 Donal K. Fellows - - * 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 - - * tools/tcltk-man2html.tcl (option-toc): handle any kind of options - defined toc section (needed for ttk docs) - -2006-10-30 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - *** 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 - - * 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 - - * generic/tclInterp.c (ApplyObjCmd): fixed bad error in 2006-10-12 - commit: interp released too early. Spotted by mistachkin. - -2006-10-16 Miguel Sofer - - * tclProc.c (SetLambdaFromAny): - * tests/apply.test (9.1-9.2): plugged intrep leak [Bug 1578454], - found by mjanssen. - -2006-10-16 Andreas Kupries - - * generic/tclBasic.c: Moved TIP#219 cleanup to DeleteInterpProc. - -2006-10-16 Daniel Steffen - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/nmakehlp.c: Replaced all wnsprintf() calls with snprintf(). - wnsprintf was not in my shwlapi header file (VC++6) - -2006-10-11 Don Porter - - * generic/tclPkg.c (Tcl_PackageRequireEx): Corrected crash when - argument version=NULL passed in. - -2006-10-10 Don Porter - - * 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 - - * 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 - - * 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 - - * win/rules.vc: [Bug 1571954] avoid /RTCc flag with MSVC8 - -2006-10-06 Pat Thoyts - - * 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 - - * library/tm.tcl: Fixed bug in TIP #189 implementation, now allowing - '_' in module names. - -2006-10-05 Jeff Hobbs - - * 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 - - * 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 - - * tzdata/: Olson's tzdata2006m. - -2006-10-01 Kevin B. Kenny - - * 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 - - * doc/Eval.3 (TclEvalObjv): added note on refCount management for the - elements of objv. [Bug 730244] - -2006-10-01 Pat Thoyts - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/makefile.vc: Additional compiler flags and amd64 support. - * win/nmakehlp.c: - * win/rules.vc: - -2006-09-26 Don Porter - - * 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 - - * 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 - - * 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 - - * doc/package.n: Fixed nits reported by Daniel Steffen in the TIP#268 - changes. - -2006-09-25 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * generic/tclInt.h: Moved TIP#268's field 'packagePrefer' to the end - of the structure, for better backward compatibility. - -2006-09-22 Andreas Kupries - - 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 - - * 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 - - * generic/tclUtil.c: Dropped ParseInteger() routine. TclParseNumber - covers the task just fine. - -2006-09-19 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/Makefile.in (install-libraries): Fixed typo tcltest 2.3.9 -> - 2.3.0. - -2006-09-11 Daniel Steffen - - * 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 - - * tests/msgcat.test: Bumped version in auxiliary files as well. - * doc/msgcat.n: - -2006-09-11 Kevin B. Kenny - - * 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 - - * library/msgcat/msgcat.tcl: Removed some unneeded [uplevel]s. - -2006-09-10 Don Porter - - * 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 - - * 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 - - * 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 - - * unix/tclUnixCompat.c: Fixed conditions for CopyArray/CopyString, and - CopyHostent. Also fixed bad var names in TclpGetHostByName. - -2006-09-07 Zoran Vasiljevic - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/package.n: correct package example - -2006-08-31 Don Porter - - * 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 - - * generic/tclParseExpr.c: Dropped the old expr parser. - -2006-08-30 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * library/tzdata/America/Havana: Regenerated from Olson's - * library/tzdata/America/Tegucigalpa: tzdata2006k. - * library/tzdata/Asia/Gaza: - -2006-08-28 Don Porter - - * 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 - - * generic/tclClock.c (ClockClicksObjCmd): Fix nested macro breakage - with TCL_MEM_DEBUG enabled. [Bug 1547662] - -2006-08-26 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * win/Makefile.in (gdb): Make this target work so that debugging an - msys build is possible. - -2006-08-21 Daniel Steffen - - * 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 - - * 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 - - * generic/tclCompile.c: Revised the new set of expression - * generic/tclParseExpr.c: parse error messages. - -2006-08-16 Don Porter - - * generic/tclParseExpr.c: Replace PrecedenceOf() function with - prec[] static array. - -2006-08-14 Donal K. Fellows - - * 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 - - * 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 - - 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 - - * generic/tclEncoding.c: Replace buffer copy in for loop with - call to memcpy(). Thanks to afredd. [Patch 1530262] - -2006-08-09 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/AppInit.3: Fix typo [Bug 1496886] - -2006-07-26 Don Porter - - * 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 - - * win/tclWinSock.c: Correct un-initialized Tcl_DString. Thanks to - afredd. [Bug 1518166] - -2006-07-21 Miguel Sofer - - * generic/tclExecute.c: - * tests/execute.test (execute-9.1): dgp's fix for [Bug 1522803]. - -2006-07-20 Daniel Steffen - - * 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 - - * unix/tclUnixPort.h: Added the inclusion of . - 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 - - * generic/tclAsync.c: Made Tcl_AsyncDelete() more tolerant when called - after all thread TSD has been garbage-collected. - -2006-07-05 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tclLoadDl.c (TclpDlopen): Workaround for a compiler bug in Sun - Forte 6. [Bug 1503729] - -2006-06-06 Don Porter - - * 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 - - * 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 - - * generic/tcl.h (Tcl_DecrRefCount): use if/else construct to allow - placement in unbraced outer if/else conditions. (jcw) - -2006-05-27 Daniel Steffen - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclEvent.c (HandleBgErrors): fix leak. [Coverity issue 86] - -2006-05-05 Don Porter - - * 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 - - * 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 - - *** 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 - - * 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 - - * 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 - - * doc/IntObj.3: Minor review fixes, including better documentation of - the behaviour of Tcl_GetBignumAndClearObj. - -2006-04-17 Don Porter - - * doc/IntObj.3: Documentation changes to account for TIP 237 changes. - * doc/Object.3: [Bug 1446971] - -2006-04-12 Donal K. Fellows - - * 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 - - * generic/tclTrace.c: Stop some interference between enter traces - * tests/trace.test: and enterstep traces. [Bug 1458266] - -2006-04-07 Don Porter - - * generic/tclPathObj.c: Yet another revised fix for the [Bug 1379287] - * tests/fileSystem.test: family of path normalization bugs. - -2006-04-06 Jeff Hobbs - - * generic/tclRegexp.c (FinalizeRegexp): full reset data to indicate - readiness for reinitialization. - -2006-04-06 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: remove unused var and silence gcc warning - -2006-03-29 Jeff Hobbs - - * win/Makefile.in: convert _NATIVE paths to use / to avoid ".\" - path-as-escape issue. - -2006-03-29 Don Porter - - * 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 - - * 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 - - * 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 - - * generic/tclIOUtil.c: fix to nativeFilesystemRecord comparisons - (lesser part of [Bug 1064247]) - -2006-03-27 Pat Thoyts - - * win/tclWinTest.c: Fixes for [Bug 1456373] (mingw-gcc issue) - -2006-03-27 Andreas Kupries - - * 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 - - * 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 - - * generic/tclExecute.c: Corrections to INST_EXPON detection of - overflow to use mp_int calculations. - -2006-03-24 Kevin B. Kenny - - * generic/tclExecute.c (TclExecuteByteCode): Added a couple of missing - casts to 'int' that were affecting compilablity on VC6. - -2006-03-24 Don Porter - - * 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 - - * 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 - - * unix/tcl.spec: Cleaned up and completed the spec file. An RPM can - now be built from the tcl source distribution with "rpmbuild -tb - " - -2006-03-22 Reinhard Max - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/fCmd.test: add proper test constraints so the new tests don't - run on Unix. - -2006-03-14 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - -- 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 - - * win/tclWinFile.c: previous patch breaks tests, so removed. - -2006-03-09 Vince Darley - - * 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 - - * generic/tclExecute.c: Complete missing bit of TIP 215 implementation - * tests/incr.test: - -2006-03-07 Joe English - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclIO.c: Made several routines tolerant of - * generic/tclIORChan.c: interp == NULL arguments. [Bug 1380662] - * generic/tclIOUtil.c: - -2006-02-09 Don Porter - - 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 - - * doc/Encoding.3, doc/encoding.n: Updates due to review at request of - Don Porter. Mostly minor changes. - -2006-02-08 Don Porter - - 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 - - * 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 - - 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 - - * doc/dict.n: Fixed silly bug in example. Thanks to Heiner Marxen - for catching this! [Bug 1415725] - -2006-01-26 Donal K. Fellows - - * 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 - - * 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 - - * tests/string.test (string-12.21): Added test for [Bug 1410553] based - on original bug report. - -2006-01-23 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * win/tclWinFile.c: fix to sharing violation [Bug 1366227] - -2006-01-11 Don Porter - - * 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 - - * 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 - - * generic/tclNamesp.c (NamespaceInscopeCmd): [namespace inscope] - * tests/namespace.test: commands were not reported by [info level]. - [Bug 1400572] - -2006-01-09 Donal K. Fellows - - * 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 - - * 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 - - * 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 Index: ChangeLog.2008 ================================================================== --- ChangeLog.2008 +++ /dev/null @@ -1,3796 +0,0 @@ -2008-12-31 Don Porter - - * 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 - - * generic/tclZlib.c (Tcl_ZlibStreamPut): Plug a memory leak. - -2008-12-27 Donal K. Fellows - - * 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 - - * 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 - - * win/Makefile.in: Fix build of zlib objects with msvc - * win/tcl.m4: - * win/configure: autoconf-2.59 - -2008-12-23 Donal K. Fellows - - * win/Makefile.in: Handle file extensions correctly. [Bug 2459725] - -2008-12-22 Pat Thoyts - - *** 8.6b1 TAGGED FOR RELEASE *** - - * win/makefile.vc: Ensure pkgs directories are suitable and quote the - paths. [Bug 2458395] - -2008-12-22 Joe Mistachkin - - * tools/man2help2.tcl: Added support for "\(mi" nroff macro. [Bug - 2330040] - -2008-12-22 Pat Thoyts - - * win/makefile.vc: Support the pkgs tree in the NMAKE builds. - -2008-12-21 Daniel Steffen - - * 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 - - * doc/TclZlib.3: Fix minor typo. [Bug 2455165] - -2008-12-20 Kevin B. Kenny - - * 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 - - * 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 - - * changes: Updates for 8.6b1 release. - -2008-12-20 Daniel Steffen - - * 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 - - * 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 - - * generic/tclInt.decls: CONSTify TclGetLoadedPackages second param - * generic/tclLoad.c - * generic/tclIntDecls.h (regenerated) - -2008-12-19 Kevin Kenny - - * 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 - - * win/makefile.vc: Added build of compat/zlib - -2008-12-18 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * generic/tcl.decls: VOID -> void - * generic/tclInt.decls: - * compat/dlfcn.h: - * generic/tclDecls.h: (regenerated) - * generic/tclIntDecls.h: - -2008-12-18 Alexandre Ferrieux - - 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 - - * doc/SetChanErr.3: General improvements in nroff rendering and some - corrections to language issues. - -2008-12-17 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * generic/tcl.h, generic/tclZlib.c: Removed undocumented flag. - -2008-12-16 Jan Nijtmans - - * 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 - - 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 - - * 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 - - * 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 - - * generic/tclBinary.c: Redefine non-strict decoding to ignore only - * doc/binary.n: whitespace. [Bug 2380293] - * tests/binary.test: - -2008-12-15 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - TIP #322 IMPLEMENTATION - - * doc/NRE.3 (new file): Added documentation of the published API for - Non-Recursive Evaluation (NRE). - -2008-12-11 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/zlib.test: Start of test suite for zlib command. - -2008-12-11 Jan Nijtmans - - * 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 - - 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 - - * library/tzdata/*: Update from Olson's tzdata2008i. - -2008-12-10 Alexandre Ferrieux - - 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 - - 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 - - * 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 - - 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 - - * 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 - - * 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 - - 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 - - * 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 - - * win/tclWinPipe.c (TclpOpenTemporaryFile): Avoid an infinite loop due - to GetTempFileName/CreateFile interaction. [Bug 2380318] - -2008-12-03 Don Porter - - * 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 - - 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 - - * 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 - - * generic/tclParse.c: Coding standards fixups. - -2008-12-01 Donal K. Fellows - - * 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 - - * 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 - - 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 - - * 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 - - * generic/tclIndexObj.c: Eliminate warning: unused variable - * generic/tclTest.c: A few more (harmless) Tcl_SetResult - eliminations. - -2008-11-26 Kevin B. Kenny - - * 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 - -2008-11-25 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * tools/tcltk-man2html.tcl: Improvements to tackle tricky aspects of - cross references and new entities to map. [Bug 2330040] - -2008-11-19 Jan Nijtmans - - * generic/tclThreadTest.c: Convert Tcl_SetResult(......, TCL_DYNAMIC) - to Tcl_SetResult(......, TCL_VOLATILE), in preparation for TIP #340 - -2008-11-17 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/registry.test: Use HKCU to avoid requiring admin access for - registry testing on Vista/Server2008 - -2008-11-11 Jan Nijtmans - - * 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 - - * doc/platform_shell.n: Fixed [Bug 2255235], reported by Ulrich - * library/platform/pkgIndex.tcl: Ring . - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclOO.h (TCLOO_VERSION): Bump version of TclOO. - -2008-10-31 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCmdAH.c (ForNextCallback): handle TCL_CONTINUE in the for - body. [Bug 2186888] - -2008-10-22 Jan Nijtmans - - * 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 - - * generic/tclProc.c: Reset -level and -code values to defaults - after they are used. [Bug 2152286] - -2008-10-19 Donal K. Fellows - - * 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 - - * generic/tclOO.decls: CONST -> const. - * generic/tclOODecls.h: (regenerated) - * generic/tclOOIntDecls.h: (regenerated) - -2008-10-17 Andreas Kupries - - * generic/tclIORTrans.c (DeleteReflectedTransformMap): Removed debug - output in C++ comment. - -2008-10-17 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * doc/binary.n: Formatting fix. - -2008-10-14 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - *** 8.6a3 TAGGED FOR RELEASE *** - - * changes: Updates for 8.6a3 release. - -2008-10-10 Donal K. Fellows - - * generic/tclOODefineCmds.c (TclOODefineUnexportObjCmd) - (TclOODefineExportObjCmd): Corrected export/unexport record synthesis. - [Bug 2155658] - -2008-10-08 Jan Nijtmans - - * unix/tclUnixChan.c: Fix minor compiler warning. - * unix/tcl.m4: Fix for [Bug 2073255] - * unix/configure: Regenerated - -2008-10-08 Miguel Sofer - - * 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 - - * 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 - - * doc/binary.n: Added better documentation of the [binary encode] and - [binary decode] subcommands. - -2008-10-07 Miguel Sofer - - 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 - - * doc/chan.n, doc/transchan.n: Documented the channel transformation - API of TIP #230. - -2008-10-06 Pat Thoyts - - * tests/winFCmd.test: Fixed some erroneous tests on Vista+. - * generic/tclFCmd.c: Fix constness for msvc of last commit - -2008-10-06 Joe Mistachkin - - * tools/man2tcl.c: Added missing line from patch by Harald Oehlmann. - [Bug 1934200] - -2008-10-05 Jan Nijtmans - - * 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 - - * 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< - - * 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 - - * generic/tclIndexObj.c (TclInitPrefixCmd): Make the [tcl::prefix] - into an exported command. [Bug 2144595] - -2008-10-04 Donal K. Fellows - - * generic/tclCmdIL.c (InfoFrameCmd): Improved hygiene of result - * generic/tclRegexp.c (TclRegAbout): handling. - -2008-10-04 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - 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 - - * 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 - - 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 - - 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 - - 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 - - * generic/tclBasic.c: Fix the numLevels computations on - * generic/tclInt.h: coroutine yield/resume - * tests/unsupported.test: - -2008-09-27 Donal K. Fellows - - * 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 - - 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 - - * generic/tclOO.h (TCLOO_VERSION): Bump the version. - -2008-09-25 Don Porter - - 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 - - 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 - - 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 - - * 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 - - * 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 - - 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 - - * doc/chan.n: Clean up paragraph order. - -2008-09-18 Miguel Sofer - - * 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 - - * 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 - - * library/init.tcl: Export min and max commands from the mathfunc - namespace. [Bug 2116053] - -2008-09-16 Joe Mistachkin - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/append.test, appendComp.test, cmdAH.test: Use the powers of - tcltest2 to make these files simpler. - -2008-09-07 Miguel Sofer - - * 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 - - * doc/namespace.n: Fix [Bug 2098441] - -2008-09-04 Miguel Sofer - - * 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 - - * 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 - - * tests/socket.test: Rewrote so as to use tcltest2 better. - -2008-09-01 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c: - * generic/tclExecute.c: Set special errocodes: COROUTINE_BUSY, - COROUTINE_CANT_YIELD, COROUTINE_ILLEGAL_YIELD. - -2008-08-22 Don Porter - - *** 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 - - * generic/tclBasic.c: Previous fix, now done right. - * generic/tclCmdIL.c: - * generic/tclInt.h: - * tests/unsupported.test: - -2008-08-21 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * generic/tclProc.c (Tcl_DisassembleObjCmd): Added ability to - disassemble TclOO methods. The code to do this is very ugly. - -2008-08-21 Pat Thoyts - - * generic/tclOOMethod.c: Added casts to make MSVC happy - * generic/tclBasic.c: - -2008-08-20 Donal K. Fellows - - * 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 - - * generic/tclTest.c (TestconcatobjCmd): Fix use of internal-only - TclInvalidateStringRep macro. [Bug 2057479] - -2008-08-17 Miguel Sofer - - * 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 - - * generic/tclExecute.c: Better cmdFrame management - -2008-08-14 Don Porter - - * tests/fileName.test: Revise new tests for portability to case - insensitive filesystems. - -2008-08-14 Daniel Steffen - - * 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 - - * tests/nre.test: Added test for large {*}-expansion effects - -2008-08-13 Don Porter - - * 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 - - * generic/tclOOInfo.c (InfoObjectDefnCmd, InfoObjectMixinsCmd): - Fix # args displayed. [Bug 2048676] - -2008-08-08 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * library/http/http.tcl: CRC field from zlib data should be treated as - unsigned for 64bit support. [Bug 2046846] - -2008-08-10 Miguel Sofer - - * 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 - - * generic/tclBasic.c: Slight cleanup - * generic/tclCompile.h: - * generic/tclExecute.c: - -2008-08-09 Daniel Steffen - - * 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 - - * changes: Updates for 8.6a2 release. - -2008-08-08 Kevin Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * unix/tclUnixChan.c: Streamline async connect logic [Patch 1994512] - -2008-08-05 Miguel Sofer - - * generic/tclExecute.c: Fix for [Bug 2038069] by dgp. - * tests/execute.test: - -2008-08-04 Miguel Sofer - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclOOMethod.c (PushMethodCallFrame): Remove hack that should - have gone when this code was merged into Tcl. - -2008-07-27 Jan Nijtmans - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclBasic.c (GetCommandSource): Added comment with - explanation and warning for waintainers. - -2008-07-22 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * generic/*.c: Fix [2021443] inconsistant "wrong # args" messages - * win/tclWinReg.c - * win/tclWinTest.c - * tests/*.test - -2008-07-21 Alexandre Ferrieux - - 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 - - * generic/tclFCmd.c: Inodes on windows are unreliable. [Bug 2015723] - * tests/winFCmd.test: test rename with inode collision - -2008-07-21 Miguel Sofer - - * 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 - - * tests/fileName.test: Repaired the failing test fileName-15.7 from - dkf's commit earlier today. - -2008-07-20 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclOOBasic.c (TclOO_Object_Eval, FinalizeEval): NRE-enable - the oo::object.eval method. - -2008-07-18 Miguel Sofer - - * 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 - - * 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 - - * win/tclWinThrd.c: Test for TLS_OUT_OF_INDEXES to make certain that - thread key creation is successful. - -2008-07-16 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * 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 - - * generic/tclCmdIL.c (InfoFrameCmd): Fixed unsafe idiom of setting - the interp result found by Don Porter. - -2008-07-07 Donal K. Fellows - - * doc/regexp.n, doc/regsub.n: Correct examples. [Bug 1982642] - -2008-07-06 Donal K. Fellows - - * doc/lindex.n: Improve examples. - -2008-07-03 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * doc/ObjectType.3: Clean up typedef formatting. - -2008-06-30 Don Porter - - * doc/ObjectType.3: Updated documentation of the Tcl_ObjType - struct to match expectations of Tcl 8.5. [Bug 1917650] - -2008-06-30 Alexandre Ferrieux - - * 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 - - * 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 - - * generic/tclPathObj.c: Plug memory leak in [Bug 1999176] fix. Thanks - to Rolf Ade for detecting. - -2008-06-29 Donal K. Fellows - - * 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 - - * 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 - - * 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 - - *** 8.6a1 TAGGED FOR RELEASE *** - - * changes: Updates for 8.6a1 release. - - * generic/tclOO.h: Bump to TclOO 0.5. - -2008-06-25 Andreas Kupries - - * 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 - - * win/rules.vc: Fix versions of dde and registry dlls - * win/makefile.vc: Fix problem building with staticpkg option - -2008-06-24 Don Porter - - * 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 - - * doc/fileevent.n: Fix examples and comment on eof use. [Bug 1995063] - -2008-06-23 Don Porter - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclClock.c (ClockConvertlocaltoutcObjCmd): Removed left - over debug output. - -2008-06-17 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - 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 - - * 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 - - * generic/tclEncoding.c(UtfToUtfProc): Avoid unwanted sign extension - when converting incomplete UTF-8 sequences. See [Bug 1908443] for - details. - -2008-06-10 Andreas Kupries - - * 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 - - * generic/tclIORTrans.c (ReflectInput): Fixed a bug triggered by Pat - Thoyts . 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 - - * generic/tclOOCall.c (TclOOGetSortedMethodList): Plug memory leak - that occurred when all methods were hidden. [Bug 1987817] - -2008-06-08 Miguel Sofer - - * 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 - - 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 - - * generic/tclBinary.c: TIP #317 implementation - * tests/binary.test: - -2008-06-02 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tests/io.test (io-53.9): Need to close chan before removing file. - -2008-05-26 Donal K. Fellows - - * win/makefile.bc: Remove deprecated winhelp target. - * win/Makefile.in, win/makefile.vc: It didn't work correctly anyway. - -2008-05-23 Andreas Kupries - - * win/tclWinChan.c (FileWideSeekProc): Accepted a patch by Alexandre - Ferrieux 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 - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclCompile.c: Fix crash with tcl_traceExec. Found and fixed - by Alexander Pasadyn. [Bug 1964803] - -2008-05-15 Pat Thoyts - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * */*.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 - - * 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 - - * 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 - - * 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 - - * doc/Ensemble.3: Fix a typo: s/defiend/defined/ - Thanks to hat0 for spotting this. - -2008-04-16 Daniel Steffen - - * 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 - - * generic/tclIO.c (CopyData): Applied another patch by Alexandre - * io.test (io-53.8a): Ferrieux , - * 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 - - * unix/Makefile.in: Adjust tclDTrace.h dependencies for removal - of tclStubLib.o from TCL_OBJS. [Bug 1942795] - -2008-04-14 Kevin B. Kenny - - * 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 - - * 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 - - * 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 - - * 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 - , with modifications from me to - separate overflow from true negative value. Extended testsuite. [Bug - 1557855] - -2008-04-09 Daniel Steffen - - * 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 - - * generic/tclExecute.c: Added comments to the alignment macros used in - GrowEvaluationStack() and friends. - -2008-04-08 Daniel Steffen - - * 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 - - * 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 - for the patch. [Bug 1350564] - -2008-04-07 Reinhard Max - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - for report and patch. - -2008-04-02 Daniel Steffen - - * 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 - - * generic/tclIO.c (CopyData): Applied patch for fcopy problem [Bug - 780533], with many thanks to Alexandre Ferrieux - 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 - - * 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 - - * 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 - - * 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 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 - - *** 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 - - * 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 - - * 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 - - * unix/tcl.m4 (SunOS-5.1x): Fix 64bit support for Sun cc. [Bug - 1921166] - - * unix/configure: autoconf-2.59 - -2008-03-26 Don Porter - - * changes: Updated for 8.5.2 release. - -2008-03-24 Pat Thoyts - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * generic/tclExecute.c: Patch from Miguel Sofer to correct the - alignment of memory allocated by GrowEvaluationStack(). [Bug 1914503] - -2008-03-18 Andreas Kupries - - * 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 - - * 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 - - * 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 - - * generic/tclTest.c: Ignore the return value of write() when we are - * unix/tclUnixPipe.c: about to exit anyways. - -2008-03-13 Daniel Steffen - - * 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 - - * 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 - - * 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 - - * doc/info.n: Replaced {expand} with {*}. - -2008-03-12 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * win/configure.in: Add AC_HEADER_STDC to support msys/win64. - -2008-03-06 Donal K. Fellows - - * doc/namespace.n: Minor tidying up. [Bug 1909019] - -2008-03-04 Don Porter - - * tests/execute.test (6.3,4): Added tests for [Bug 1899164]. - -2008-03-03 Reinhard Max - - * unix/tclUnixChan.c: Fix mark and space parity on Linux, which uses - CMSPAR instead of PAREXT. - -2008-03-02 Miguel Sofer - - * 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 - - * 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 - - * unix/tclPort.h, unix/tclCompat.h, unix/tclUnixChan.h: Reduce scope - of and #includes. [Patch 1903339] - -2008-02-28 Joe English - - * 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 - - * 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 - - * library/http/http.tcl: [Bug 705956] - fix inverted logic when - cleaning up socket error in geturl. - -2008-02-27 Kevin B. Kenny - - * 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 - - * 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 - - * generic/tclIORChan.c (enum MethodName), - * generic/tclCompExpr.c (enum Marks): More stray trailing ","s - -2008-02-26 Joe English - - * 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 - - * generic/tclCompile.h: Remove stray trailing "," from enum - InstOperandType definition (C99ism). - -2008-02-26 Jeff Hobbs - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - *** 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 - - * generic/tclExecute.c (INST_CONCAT1): Fix optimisation for in-place - concatenation (was going over String type) - -2008-02-02 Daniel Steffen - - * unix/configure.in (Darwin): Correct Info.plist year substitution - in non-framework builds. - - * unix/configure: autoconf-2.59 - -2008-01-30 Miguel Sofer - - * generic/tclInterp.c (Tcl_GetAlias): Fix for [Bug 1882373], thanks go - to an00na. - -2008-01-30 Donal K. Fellows - - * 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 - - * 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 - - * changes: Updated for 8.5.1 release. - -2008-01-23 Don Porter - - * 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 - - * 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 - - * 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 - - * unix/README: Minor typo fixes [Bug 1853072] - - * generic/tclIO.c (TclGetsObjBinary): Operate on topmost channel. - [Bug 1869405] (Ficicchia) - -2008-01-17 Don Porter - - * generic/tclCompExpr.c: Revision to preserve parsed intreps of - numeric and boolean literals when compiling expressions with (optimize - == 1). - -2008-01-15 Miguel Sofer - - * 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 - - * 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 - - * win/tclWinSerial.c (SerialCloseProc, TclWinOpenSerialChannel): Use - critical section for read & write side. [Bug 1353846] (newman) - -2008-01-11 Miguel Sofer - - * 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 - - * 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 - - * doc/vwait.n: Add a missing be to fix a typo. - -2008-01-04 Jeff Hobbs - - * 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 - - * 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 - - * 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" *** - ****************************************************************** Index: README.md ================================================================== --- README.md +++ README.md @@ -1,13 +1,26 @@ # README: Tcl -This is the **Tcl 9.0a2** source distribution. +This is the **Tcl 9.0a4** 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) +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) +
+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) +
+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) @@ -27,25 +40,25 @@ Tcl can also be used for a variety of web-related tasks and for creating powerful command languages for applications. Tcl is maintained, enhanced, and distributed freely by the Tcl community. Source code development and tracking of bug reports and feature requests -takes place at [core.tcl-lang.org](https://core.tcl-lang.org/). +take place at [core.tcl-lang.org](https://core.tcl-lang.org/). Tcl/Tk release and mailing list services are [hosted by SourceForge](https://sourceforge.net/projects/tcl/) with the Tcl Developer Xchange hosted at [www.tcl-lang.org](https://www.tcl-lang.org). -Tcl is a freely available open source package. You can do virtually +Tcl is a freely available open-source package. You can do virtually anything you like with it, such as modifying it, redistributing it, and selling it either in whole or in part. See the file `license.terms` for complete information. ## 2. Documentation -Extensive documentation is available at our website. +Extensive documentation is available on our website. The home page for this release, including new features, is -[here](https://www.tcl.tk/software/tcltk/9.0.html). +[here](https://www.tcl-lang.org/software/tcltk/9.0.html). Detailed release notes can be found at the [file distributions page](https://sourceforge.net/projects/tcl/files/Tcl/) by clicking on the relevant version. Information about Tcl itself can be found at the [Developer @@ -86,20 +99,20 @@ 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). ## 4. Development tools -ActiveState produces a high quality set of commercial quality development +ActiveState produces a high-quality set of commercial quality development tools that is available to accelerate your Tcl application development. Tcl Dev Kit builds on the earlier TclPro toolset and provides a debugger, -static code checker, single-file wrapping utility, bytecode compiler and +static code checker, single-file wrapping utility, bytecode compiler, and more. More information can be found at - http://www.ActiveState.com/Tcl + https://www.activestate.com/products/tcl/ ## 5. Tcl newsgroup -There is a USENET news group, "`comp.lang.tcl`", intended for the exchange of +There is a USENET newsgroup, "`comp.lang.tcl`", intended for the exchange of information about Tcl, Tk, and related applications. The newsgroup is a great place to ask general information questions. For bug reports, please see the "Support and bug fixes" section below. ## 6. Tcl'ers Wiki Index: changes ================================================================== --- changes +++ changes @@ -2484,11 +2484,11 @@ 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 + tcl_safeCreateInterp -- creates a slave and initializes the policy mechanism. tcl_safeInitInterp -- initializes an existing slave with the policy mechanism. tcl_safeDeleteInterp -- deletes a slave and deinitializes the policy mechanism. @@ -3026,11 +3026,11 @@ 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) +of the command to be deleted as a result of unaliasing 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) @@ -4165,11 +4165,11 @@ 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. + preinit script. - Adding the Tcl_SetdefaultEncodingDir and Tcl_GetDefaultEncodingDir routines. - Modifying the TclpInitLibrary routines to append the default encoding dir. (surles) @@ -4648,11 +4648,11 @@ 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 --- +--- Released 8.2.1, October 04, 1999 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 @@ -4678,11 +4678,11 @@ 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 --- +--- Released 8.2.2, November 04, 1999 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. @@ -4703,11 +4703,11 @@ 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 --- +--- Released 8.2.3, December 16, 1999 1999-09-14 (feature enhancement) added -start switch to regexp and regsub. 1999-09-15 (feature enhancement) add 'array unset' command. @@ -4760,11 +4760,11 @@ 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 --- +--- Released 8.3b1, December 22, 1999 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 @@ -4786,11 +4786,11 @@ 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 --- +--- Released 8.3b2, January 13, 2000 2000-01-14 (feature enhancement) clock format %Q added, clock scan updated 2000-01-20 (bug fix) corrected complex array elem compiling (Spjuth) @@ -4825,11 +4825,11 @@ 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 --- +--- Released 8.3.0, February 10, 2000 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) @@ -4868,11 +4868,11 @@ 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 --- +--- Released 8.3.1, April 26, 2000 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; @@ -4918,11 +4918,11 @@ 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 --- +--- Released 8.4a1, June 6, 2000 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 @@ -4957,11 +4957,11 @@ 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 --- +--- Released 8.3.2, August 9, 2000 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) @@ -4974,11 +4974,11 @@ 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-06 (cross-platform feature) Set ^Z (\x1A) 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, @@ -5016,11 +5016,11 @@ 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 --- +--- Released 8.4a2, November 3, 2000 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) @@ -5074,11 +5074,11 @@ 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 --- +--- Released 8.3.3, April 6, 2001 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) @@ -5148,11 +5148,11 @@ * 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 --- +--- Released 8.4a3, August 6, 2001 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) @@ -5254,11 +5254,11 @@ *** 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 --- +--- Released 8.3.4, October 19, 2001 2001-08-21 (bug fix)[219184] overagressive compilation of [catch] (sofer) 2001-08-22 (new feature)[227482] [dde request -binary] (hobbs) => dde 1.2 @@ -5280,12 +5280,10 @@ 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) @@ -5366,12 +5364,10 @@ => 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) @@ -5392,11 +5388,11 @@ 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. +commands. See 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) @@ -5433,11 +5429,11 @@ 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 --- +--- Released 8.4a4, March 5, 2002 2002-03-06 (new feature)[TIP 80] expanded [lsearch] options (wilkason, fellows) 2002-03-07 (new feature)[TIP 87] [interp recursionlimit] (trier) @@ -5543,11 +5539,11 @@ 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 --- +--- Released 8.4b1, July 5, 2002 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) @@ -5581,11 +5577,11 @@ 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 --- +--- Released 8.4b2, August 9, 2002 2002-08-20 (new feature) --enable-memdebug configure option (kupries) 2002-08-23 (bug fix)[597936] mem leak with USE_THREAD_ALLOC (sofer,zoran) @@ -5596,11 +5592,11 @@ 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 --- +--- Released 8.4.0, September 10, 2002 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 @@ -5659,11 +5655,11 @@ 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 --- +--- Released 8.4.1, October 22, 2002 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 @@ -5752,11 +5748,11 @@ 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 --- +--- Released 8.4.2, March 3, 2003 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 @@ -5834,11 +5830,11 @@ 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 --- +--- Released 8.4.3, May 20, 2003 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. @@ -5875,11 +5871,11 @@ 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 --- +--- Released 8.4.4, July 22, 2003 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. @@ -5921,11 +5917,11 @@ 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 --- +--- Released 8.4.5, November 20, 2003 2003-12-02 (bug fix)[851747] object sharing fix in [binary scan] 2003-12-09 (platform support)[852369] update errno usage for recent glibc @@ -5958,11 +5954,11 @@ 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 --- +--- Released 8.4.6, March 1, 2004 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: @@ -6044,11 +6040,11 @@ => 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 --- +--- Released 8.5a1, March 3, 2004 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) @@ -6068,11 +6064,11 @@ 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. +Changed source code files should work with older Tcl as well. *** 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 @@ -6344,11 +6340,11 @@ 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 --- +--- Released 8.5a2, December 7, 2004 2004-12-13 (bug fix)[1083082] encoding memory leaks (ade,porter) 2004-12-13 (bug fix)[1082349] restored C++ extension support (porter) @@ -6488,11 +6484,11 @@ 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 --- +--- Released 8.5a3, June 4, 2005 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) @@ -6739,11 +6735,11 @@ (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 --- +--- Released 8.5a4, April 27, 2006 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) @@ -6835,11 +6831,11 @@ 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 --- +--- Released 8.5a5, October 20, 2006 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 @@ -6917,11 +6913,11 @@ 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 --- +--- Released 8.5a6, April 25, 2007 2007-04-30 (bug fix)[1705778] many valgrind-detected leaks corrected 2007-05-01 (bug fix)[1710709] leak in [string map] (porter) @@ -6975,11 +6971,11 @@ 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-16 (performance)[1564517] precompile 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) @@ -7020,11 +7016,11 @@ 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 --- +--- Released 8.5b1, September 26, 2007 2007-10-02 (bug fix)[1806422] proper [tcl::tm::path] autoload (porter) 2007-10-02 (bug fix) Improve Tcl_DecrRefCount() robustness (staplin) @@ -7032,11 +7028,11 @@ 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 --- +--- Released 8.5b2, October 26, 2007 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) @@ -7068,11 +7064,11 @@ 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 --- +--- Released 8.5b3, November 19, 2007 2007-11-20 (enhancement) string rep of dict has stable order (fellows) 2007-11-21 (enhancement) compiled ensemble support (fellows) @@ -7102,11 +7098,11 @@ 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 --- +--- Released 8.5.0, December 20, 2007 2007-12-23 (bug fix)[1857126] restore backref support to regexps (hobbs) 2007-12-26 (enhancement)[1856994] [lsort] performance (sofer) @@ -7124,11 +7120,11 @@ 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 --- +--- Released 8.5.1, February 5, 2008 2008-02-06 (enhancement) [clock format] performance (kenny) 2008-02-12 (bug fix)[1891827] compiled [switch -nocase] error (fellows) @@ -7185,11 +7181,11 @@ 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 --- +--- Released 8.5.2, March 28, 2008 2008-03-30 (bug fix)[1783544] more robust TclIsNaN() (kenny,teterin) 2008-04-01 (interface)[1819422] tclStubsPtr no longer in libtcl (porter) *** POTENTIAL INCOMPATIBILITY *** @@ -7240,11 +7236,11 @@ 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 --- +--- Released 8.6a1, June 25, 2008 2008-06-29 (bug fix)[2004480] plug memory leaks (ade,porter,steffen) 2008-07-01 (enhancement)[1905562] embed recursion limit in RE engine (fellows) @@ -7293,11 +7289,11 @@ (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 --- +--- Released 8.6a2, August 25, 2008 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) @@ -7374,11 +7370,11 @@ 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 --- +--- Released 8.6a3, October 10, 2008 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) @@ -7444,11 +7440,11 @@ 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 --- +--- Released 8.6b1, December 19, 2008 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) @@ -7952,11 +7948,11 @@ 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 --- +--- Released 8.6b2, August 8, 2011 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) @@ -8113,11 +8109,11 @@ 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 --- +--- Released 8.6b3, September 18, 2012 2012-09-20 (enhancement) full Unicode support (nijtmans) => dde 1.4.0 2012-09-20 (enhancement) update bundled zlib to 1.2.7 (nijtmans) @@ -8160,11 +8156,11 @@ 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 --- +--- Released 8.6.0, December 20, 2012 2012-12-22 (bug fix)[3598150] DString to Tcl_Obj memleak (afredd) 2012-12-27 (bug fix)[3598580] Tcl_ListObjReplace() refcount fix (nijtmans) @@ -8249,11 +8245,11 @@ 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-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) @@ -8683,11 +8679,11 @@ 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) +2016-07-09 [ae61a6] [file] handling of Win hard-coded 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) @@ -8841,11 +8837,11 @@ 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 +--- Released 8.7a1, September 8, 2017 --- https://core.tcl-lang.org/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) @@ -8940,11 +8936,11 @@ 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/ - +- Released 8.6.9, November 16, 2018 - details at https://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) @@ -8988,11 +8984,14 @@ 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/ - +2019-11-18 (bug)[13657a] application/json us text, not binary (noe,nijtmans) +=> http 2.9.1 + +- Released 8.6.10, Nov 21, 2019 - details at https://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: @@ -9097,10 +9096,13 @@ 2019-04-14 [TIP 504] [string insert] 2019-04-16 [TIP 342] [dict getwithdefault] +2019-04-23 (bug)[67a5ea] make [chan postevent] asynchronous + *** POTENTIAL INCOMPATIBILITY *** + 2019-05-25 [TIP 431] [file tempdir] 2019-05-25 [TIP 383] [coroinject], [coroprobe] 2019-05-31 [TIP 544] Tcl_GetIntForIndex() @@ -9117,11 +9119,11 @@ 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 - +- Released 8.7a3, Nov 21, 2019 --- https://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: @@ -9137,6 +9139,324 @@ 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 - +- Released 9.0a1, Nov 25, 2019 --- https://core.tcl-lang.org/tcl/ for details - + +2019-12-03 (bug)[3cd9be] Corner case in surrogate handling (nijtmans) + +2019-12-09 (new) Add tcltest::(Setup|Eval|Cleanup|)Test (coulter,sebres) +=> tcltest 2.5.2 + +2019-12-12 (new) Add 3 libtommath functions to stub table (nijtmans) + +2019-12-23 (bug)[ce3b9f] compilation errors with clang, windows msys2 (nijtmans) + +2019-12-27 (bug)[1de6b0] [expr 1e2147483648] => 0.0 (kbk) + +2020-01-04 (bug)[912886] tis-620 encoding fails to load (coulter) + +2020-01-13 (bug)[0b9332] Win: support system encoding init to utf-8 (jedlička) + +2020-01-17 (bug)[8cd2fe] [unload] corrupted list of loaded packages (berc) + +2020-01-17 (bug)[5d989f] segfault in lsort for large list length (sebres) + +2020-01-30 (bug) Reset WSAGetLastError()/errno in channel close (nijtmans) + +2020-02-17 (bug) Win: avoid create of legacy error-vars on init phase (sebres) + +2020-02-25 (bug) release refs when setting class's superclasses fails (dkf) + +2020-02-26 (bug) C++ compiler compatibility for registry and dde (nijtmans) +=> registry 1.3.5 +=> dde 1.4.3 + +2020-03-05 (new) Update to Unicode-13 (nijtmans) + +2020-03-16 (bug)[8f89e2] Win: env var encoding, env-2.5 (sebres, nijtmans) + +2020-03-27 (bug)[767e07] Tcl_Get(Range|UniChar) validate index inputs (nijtmans) + +2020-03-28 (bug)[8edfce] [binary encode base64] & multi-byte wrapchars (dgp) + +2020-03-28 (bug)[ffeb20] [binary decode base64] ignore invalid chars (dgp) +See RFC 2045 + *** POTENTIAL INCOMPATIBILITY *** + +2020-03-31 (bug)[b8e82d] some -maxlen values break uuencode round trip (dgp) + *** POTENTIAL INCOMPATIBILITY *** + +2020-04-01 (bug)[f58371] Fileevent run in proper thread (bron,sebres) + +2020-04-13 (bug)[afa4b2] TclNeedSpace bug; tests util-8.5 .. util-8.11 (dgp) + +2020-04-13 (bug)[085913] Tcl_DStringAppendElement # quoting precision (dgp) + *** POTENTIAL INCOMPATIBILITY *** + +2020-04-13 (bug)[a7f685] test util-5.52 (dgp) + +2020-04-13 (bug)[c61818] Tcl_UtfPrev regression (dgp) + +2020-04-15 (bug)[8af92d] zlib transform issue, bad inflate (sebres) + +2020-04-16 (bug)[5e6346] Tcl_UtfPrev handling of overlong sequences (dgp) + +2020-04-27 (bug)[45ca23] [string tolower] inconsistency (dgp) + +2020-04-30 (bug)[da2352] init [info hostname] with DNS, not NetBIOS (nadkarni) + +2020-05-11 (bug)[d402ff] Win32 potential crash when using main() (werner) + +2020-05-13 (bug)[81242a] revised documentation for Tcl_UtfAtIndex() (nijtmans) + *** POTENTIAL INCOMPATIBILITY *** + +2020-05-13 (bug)[ed2980] Tcl_UtfToUniChar reads > TCL_UTF_MAX bytes (nijtmans) + *** POTENTIAL INCOMPATIBILITY *** + +2020-06-02 (bug) prevent segfault in parser (sebres) + +2020-06-21 (bug)[f81bec] http POST a binary file (alakendu,nash) +=> http 2.9.2 + +2020-06-23 (bug)[41c985] auto_path nonsense in Safe Base (nash) + +2020-06-24 (bug)[f70ce1] zlib multi-stream inflate acts only on first (sebres) + +2020-07-09 (bug)[a1bd37] [clock scan] new ISO format (clock-34.(19-24)) (sebres) + *** POTENTIAL INCOMPATIBILITY *** + +2020-07-10 (bug)[501974] [clock scan] +time zone (clock-34.(53-68)) (sebres) + *** POTENTIAL INCOMPATIBILITY *** + +2020-07-15 (bug)[3c6e47] compiled [lappend] performance, avoid copy (sebres) + +2020-07-16 (bug)[5bbd04] Fix index underflow (schwab) + +2020-07-27 (bug)[cb0373] http::geturl -keepalive fixes (nash) +=> http 2.9.3 + +2020-08-10 (bug)[29e884] cmd resolution cycle (namespace-57.0) (coulter,sebres) + +2020-08-12 (bug)[e87000] Tcl_BadChannelOption tolerate NULL (werner,nijtmans) + +2020-08-31 (TIP #581) disfavor Master/Slave terminology (nijtmans) +=> opt 0.4.8 + +2020-09-11 (bug)[3bc0f4] UBSan complains about body.chars[] usage (nijtmans) + +2020-09-17 (bug)[835c93] Support TIP 525 exit code for -singleproc 1 (nijtmans) +=> tcltest 2.5.3 + +2020-09-25 (new) force -eofchar \x1A when evaluating library scripts (nijtmans) + *** POTENTIAL INCOMPATIBILITY *** + +2020-09-29 (bug)[0063cb] http::geturl -headers must be dict (oehlmann,nijtmans) + +2020-10-19 (bug)[cb4582] Update install-sh script (stu,nijtmans) + +2020-10-22 (bug)[c97593] Usage of gnu_printf in latest mingw-w64 (nijtmans) + +2020-10-26 (new)[48898a] improve error message consistency (stu) + *** POTENTIAL INCOMPATIBILITY *** + +2020-11-06 (new) revised case of module names (nijtmans) + *** POTENTIAL INCOMPATIBILITY *** + +2020-12-10 (bug)[ed5be7] Win: recognize "comx:" as serial port (oehlmann) + +2020-12-11 (new) support for msys2, Big Sur (nijtmans) +=> platform 1.0.15 + +2020-12-23 tzdata updated to Olson's tzdata2020e (jima) + +- Released 8.6.11, Dec 31, 2020 - details at https://core.tcl-lang.org/tcl/ - + +Changes to 8.7a5 include all changes to the 8.6 line through 8.6.11, +plus the following, which focuses on the high-level feature changes +in this changeset (new minor version) rather than bug fixes: + +2019-12-13 [TIP 538] Externalize libtommath + +2020-01-20 [TIP 542] Support for switchable Full Unicode support + +2020-01-21 [TIP 543] Eliminate `TCL_INTERP_DESTROYED` flag value + +2020-01-24 [TIP 559] Eliminate public routine `Tcl_FreeResult + +2020-01-31 (new) Implement 64-bit seek on Zip channels. (nijtmans) + +2020-02-28 [TIP 557] C++ support for Tcl + +2020-02-28 [TIP 562] Deprecate channel types 1-4 + +2020-03-11 (bug)[234d6c] Segfault in [set l {}; lpop l] (sebres) + +2020-03-12 (bug) Crash in tests binary-79.[12] (porter) + +2020-03-13 [TIP 569] Eliminate Comments That Serve Lint + +2020-04-06 (bug)[dd010c] [string trim*] on astral characters (porter,nijtmans) + +2020-05-30 [TIP 551] Permit underscore in numerical literals in source code + +2020-07-03 [TIP 578] Death to TCL_DBGX + +2020-08-11 (bug)[e87000] Win32 crash in [fconfigure stdout] (werner,nijtmans) + +2020-09-06 (bug)[c1a376] deletion trace on imported ensemble (coulter) + +2020-09-13 [TIP 585] Promote the INDEX_TEMP_TABLE flag of Tcl_GetIndexFromObj*() to the public interface + +2020-09-15 (bug)[b5777d] crash in [string index abcd 0-0x10000000000000000] + +2020-09-19 [b9ecf3] revised stork mgmt [uplevel [list $cmd ...]] (coulter) + +2020-10-23 [TIP 587] Default utf-8 for source command + +2020-10-27 (bug)[11229b] test string-31.26.* (porter) + +2020-11-08 [TIP 582] Comments in Expressions + +2020-11-16 [TIP 586] C String Parsing Support for binary scan + +2020-12-07 [TIP 590] Recommend lowercase Package Names + +2021-01-06 Bump to tcltest 2.5.4 + +2021-01-15 [TIP 481] `Tcl_GetStringFromObj()` with `size_t` length parameter + +2021-01-15 [TIP 592] End support: Windows XP, Server 2003, Vista, Server 2008 + +2021-01-25 tzdata updated to Olson's tzdata2021a (nijtmans) + +2021-01-29 (bug)[113be1] zipfs on mac + +2021-03-15 [TIP 575] Switchable Tcl_UtfCharComplete()/Tcl_UtfNext()/Tcl_UtfPrev() + +2021-03-19 (new)[0221b9] Drop TCL_WINDOW_EVENTS from Tcl's [update idletasks] + +2021-03-30 (new)[4b4830] [chan truncate] for reflected channels + +2021-04-30 [TIP 597] "string is unicode" and better utf-8/utf-16/cesu-8 encodings + +2021-04-09 [TIP 598] export TclWinConvertError + +2021-05-15 (bug)[463b7a] segfault from Tcl_Unload (coulter) + +2021-05-15 (bug)[fb2a41] tclZipfs.c free all memory (coulter) + +2021-05-18 (bug)[688fcc,28027d] namespace teardown reform (coulter) + +- Released 8.7a5, Jun 18, 2021 --- https://core.tcl-lang.org/tcl/ for details - + +Changes to 9.0a3 include all changes to the 8.7 line through 8.7a5, +plus the following, which focuses on the high-level feature changes +in this changeset (new major version) rather than bug fixes: + +Many of the TIPs in Tcl 8.7 mentioned above are extended further in 9.0 + +2020-02-28 [TIP 497] Full support for Unicode planes 1-16 + +2020-08-21 (bug)[43b434] improper calls to stat64() + +2021-04-08 [TIP 595] Unicode-aware loadable library handling. + +2021-04-30 [TIP 596] Stubs support for embedding Tcl in apps + +Many internal changes to broaden support for sizes beyond 32-bits. + +- Released 9.0a3, Jun 23, 2021 --- https://core.tcl-lang.org/tcl/ for details - + +2021-02-02 (new) support for MacOS Big Sur updates (nijtmans) +=> platform 1.0.17 + +2021-02-15 (bug)[d43f96] [string trim*] broken for Emoji (werner) + +2021-02-16 (bug)[22324b] [string reverse] broken for Emoji (werner) + +2021-02-19 (bug)[1dab71,7c64aa] BRE broken by uninitialized value use (lane) + +2021-03-09 (bug)[8419c5] Unix tty channels tolerate EINTR (nijtmans) + *** POTENTIAL INCOMPATIBILITY *** + +2021-03-10 (bug)[4c591f] [string compare] EIAS violation (nijtmans) + +2021-04-08 (new) dde package installation compatible with Tcl 9 (nijtmans) +=> dde 1.4.4 + +2021-04-14 (bug)[266494] [concat foo [list #]] EIAS violation (porter) + +2021-05-03 (bug)[24b918] Save IO buffers from modern optimizers (rupprecht) + +2021-05-06 (new) support for POSIX error EILSEQ (nijtmans) + +2021-05-17 (bug)[688fcc] segfault during traced delete of alias (coulter) + +2021-06-22 (bug)[bad6cc] More secure build tool. CVE-2021-35331 (nijtmans) + +2021-07-17 (bug)[592a25] Win: segfault in Tcl_PutEnv() (danckaert,nijtmans) + +2021-09-02 (bug)[ccc448] segfault in ensemble rewrite machinery (coulter) + +2021-09-14 (new) Update to Unicode-14 (nijtmans) + +2021-10-08 (bug)[a8579d] failed proc argument spec processing (russell,coulter) + +2021-10-27 (new) support for MacOS Monterey (nijtmans) +=> platform 1.0.18 + +2021-10-27 tzdata updated to Olson's tzdata2021e (nijtmans) + +- Released 8.6.12, Nov 5, 2021 - details at https://core.tcl-lang.org/tcl/ - + +2021-12-08 (update) tcltest package to version 2.5.4 + +2022-01-13 (bug)[26f132] Crash when sizeof(int) < sizeof(void *) (Plan 9 port) + +2022-01-19 (TIP 623)[e9a271] Tcl_GetRange index args < 0 (petasis,nijtmans) + +2022-03-08 (bug) test string-5.22 (porter) + +2022-03-11 (bug)[8a7ec8] fat binary compile on Mac M1 (davis, nijtmans) + +2022-04-04 (bug)[e5ed1b] numeric IPv6 in URLs (nijtmans) +=> http 2.9.6 + +2022-04-26 (bug)[27520c] test error-9.6 (goth,sebres) + +2022-05-04 (bug)[8eb64b] http package tolerant again invalid reply header + +2022-05-11 (bug)[6898f9] http package failed detection of shiftjis charset + +2022-05-25 (bug)[76ad7a] tests string-6.13[23] (mistachkin, nijtmans) + +2022-06-20 (bug)[55bf73] Avoid connection reuse after response code 101. +=> http 2.9.8 + +2022-07-22 (bug)[713653] FP rounding exposed by x86 musl (rubicon,sebres) + +2022-07-22 More portable notation of microseconds in verbose output (sebres) +=> tcltest 2.5.5 + +2022-07-27 (bug)[b3977d] Process CR-LF split across packets (nadkarni,sebres) + +2022-07-29 (bug)[4eb3a1] crash due to undetected bytecode invalidity (nadkarni) + +2022-08-23 (new)[371080] Portability to CHERI-enabled Morello processor (jrtc27) + +2022-09-06 (bug)[55a02f] Fallback init env(HOME) from USERPROFILE (nadkarni) + +2022-09-13 (bug)[1073da] crash writing invalid utf-8 (nijtmans) + +2022-09-14 (new) Update to Unicode-15 (nijtmans) + +2022-10-14 tzdata updated to Olson's tzdata2022e (nijtmans) + +Update bundled zlib to 1.2.13 + +Update bundled libtommath + +Many code fixes to avoid overflow or undefined behavior. Thanks chrstphrchvz. + +- Released 8.6.13, Nov 22, 2022 - details at https://core.tcl-lang.org/tcl/ - DELETED compat/dirent.h Index: compat/dirent.h ================================================================== --- compat/dirent.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * dirent.h -- - * - * This file is a replacement for in systems that - * support the old BSD-style 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 - -#define dirent direct - -#endif /* _DIRENT */ DELETED compat/dirent2.h Index: compat/dirent2.h ================================================================== --- compat/dirent2.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 Index: compat/memcmp.c ================================================================== --- compat/memcmp.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 Index: compat/opendir.c ================================================================== --- compat/opendir.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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 Index: compat/stdint.h ================================================================== --- compat/stdint.h +++ /dev/null @@ -1,919 +0,0 @@ -/* 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 -#include -#include - -/* - * 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 -#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 -#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 -# 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 -#include -#include - -#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 Index: compat/stdlib.h ================================================================== --- compat/stdlib.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 Index: compat/strstr.c ================================================================== --- compat/strstr.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 Index: compat/strtol.c ================================================================== --- compat/strtol.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 Index: compat/strtoul.c ================================================================== --- compat/strtoul.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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; -} Index: compat/waitpid.c ================================================================== --- compat/waitpid.c +++ compat/waitpid.c @@ -154,11 +154,15 @@ if (waitPtr->pid == result) { waitPtr->status = status; goto waitAgain; } } - waitPtr = (WaitInfo *) Tcl_Alloc(sizeof(WaitInfo)); + waitPtr = (WaitInfo *) Tcl_AttemptAlloc(sizeof(WaitInfo)); + if (!waitPtr) { + errno = ENOMEM; + return -1; + } waitPtr->pid = result; waitPtr->status = status; waitPtr->nextPtr = deadList; deadList = waitPtr; Index: compat/zlib/CMakeLists.txt ================================================================== --- compat/zlib/CMakeLists.txt +++ compat/zlib/CMakeLists.txt @@ -1,14 +1,11 @@ -cmake_minimum_required(VERSION 2.4.4) +cmake_minimum_required(VERSION 2.4.4...3.15.0) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) project(zlib C) -set(VERSION "1.2.11") - -option(ASM686 "Enable building i686 assembly implementation") -option(AMD64 "Enable building amd64 assembly implementation") +set(VERSION "1.3") 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") @@ -127,43 +124,10 @@ 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}) @@ -181,12 +145,12 @@ -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) endif(MINGW) -add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +add_library(zlibstatic STATIC ${ZLIB_SRCS} ${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 Index: compat/zlib/ChangeLog ================================================================== --- compat/zlib/ChangeLog +++ compat/zlib/ChangeLog @@ -1,8 +1,101 @@ ChangeLog file for zlib +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) @@ -94,11 +187,11 @@ - Don't specify --version-script on Apple platforms in CMakeLists.txt - Fix casting error in contrib/testzlib/testzlib.c - Fix types in contrib/minizip to match result of get_crc_table() - Simplify contrib/vstudio/vc10 with 'd' suffix - Add TOP support to win32/Makefile.msc -- Suport i686 and amd64 assembler builds in CMakeLists.txt +- Support i686 and amd64 assembler builds in CMakeLists.txt - Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h - Add vc11 and vc12 build files to contrib/vstudio - Add gzvprintf() as an undocumented function in zlib - Fix configure for Sun shell - Remove runtime check in configure for four-byte integer type @@ -294,18 +387,18 @@ - Clarify the use of Z_FINISH with deflateBound() amount of space - Set binary for output file in puff.c - Use u4 type for crc_table to avoid conversion warnings - Apply casts in zlib.h to avoid conversion warnings - Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] -- Improve inflateSync() documentation to note indeterminancy +- Improve inflateSync() documentation to note indeterminacy - Add deflatePending() function to return the amount of pending output - Correct the spelling of "specification" in FAQ [Randers-Pehrson] - Add a check in configure for stdarg.h, use for gzprintf() - Check that pointers fit in ints when gzprint() compiled old style - Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] - Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] -- Add debug records in assmebler code [Londer] +- Add debug records in assembler code [Londer] - Update RFC references to use http://tools.ietf.org/html/... [Li] - Add --archs option, use of libtool to configure for Mac OS X [Borstel] Changes in 1.2.5 (19 Apr 2010) - Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] @@ -509,11 +602,11 @@ - Replace use of errno in gz* with functions, support WinCE [Alves] - Provide alternative to perror() in minigzip.c for WinCE [Alves] - Don't use _vsnprintf on later versions of MSVC [Lowman] - Add CMake build script and input file [Lowman] - Update contrib/minizip to 1.1 [Svensson, Vollant] -- Moved nintendods directory from contrib to . +- Moved nintendods directory from contrib to root - Replace gzio.c with a new set of routines with the same functionality - Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above - Update contrib/minizip to 1.1b - Change gzeof() to return 0 on error instead of -1 to agree with zlib.h @@ -683,11 +776,11 @@ - Update make_vms.com [Zinser] - Initialize state->write in inflateReset() since copied in inflate_fast() - Be more strict on incomplete code sets in inflate_table() and increase ENOUGH and MAXD -- this repairs a possible security vulnerability for invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for - discovering the vulnerability and providing test cases. + discovering the vulnerability and providing test cases - Add ia64 support to configure for HP-UX [Smith] - Add error return to gzread() for format or i/o error [Levin] - Use malloc.h for OS/2 [Necasek] Changes in 1.2.2.3 (27 May 2005) @@ -719,11 +812,11 @@ - Improve WinCE errno handling and comments [Chang] - Remove comment about no gzip header processing in FAQ - Add Z_FIXED strategy option to deflateInit2() to force fixed trees - Add updated make_vms.com [Coghlan], update README - Create a new "examples" directory, move gzappend.c there, add zpipe.c, - fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. + fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html - Add FAQ entry and comments in deflate.c on uninitialized memory access - Add Solaris 9 make options in configure [Gilbert] - Allow strerror() usage in gzio.c for STDC - Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] - Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] @@ -790,11 +883,11 @@ - Update email address in README - Several FAQ updates - Fix a big fat bug in inftrees.c that prevented decoding valid dynamic blocks with only literals and no distance codes -- Thanks to "Hot Emu" for the bug report and sample file -- Add a note to puff.c on no distance codes case. +- Add a note to puff.c on no distance codes case Changes in 1.2.1 (17 November 2003) - Remove a tab in contrib/gzappend/gzappend.c - Update some interfaces in contrib for new zlib functions - Update zlib version number in some contrib entries @@ -968,11 +1061,11 @@ - Refine detection of Turbo C need for dummy returns - Refine ZLIB_DLL compilation - Include additional header file on VMS for off_t typedef - Try to use _vsnprintf where it supplants vsprintf [Vollant] - Add some casts in inffast.c -- Enchance comments in zlib.h on what happens if gzprintf() tries to +- Enhance comments in zlib.h on what happens if gzprintf() tries to write more than 4095 bytes before compression - Remove unused state from inflateBackEnd() - Remove exit(0) from minigzip.c, example.c - Get rid of all those darn tabs - Add "check" target to Makefile.in that does the same thing as "test" @@ -1034,18 +1127,18 @@ - Add contrib/inflate86/ for x86 faster inflate - Add contrib/blast/ for PKWare Data Compression Library decompression - Add contrib/puff/ simple inflate for deflate format description Changes in 1.1.4 (11 March 2002) -- ZFREE was repeated on same allocation on some error conditions. +- ZFREE was repeated on same allocation on some error conditions This creates a security problem described in http://www.zlib.org/advisory-2002-03-11.txt - Returned incorrect error (Z_MEM_ERROR) on some invalid data - Avoid accesses before window for invalid distances with inflate window - less than 32K. + less than 32K - force windowBits > 8 to avoid a bug in the encoder for a window size - of 256 bytes. (A complete fix will be available in 1.1.5). + of 256 bytes. (A complete fix will be available in 1.1.5) Changes in 1.1.3 (9 July 1998) - fix "an inflate input buffer bug that shows up on rare but persistent occasions" (Mark) - fix gzread and gztell for concatenated .gz files (Didier Le Botlan) @@ -1115,11 +1208,11 @@ Changes in 1.1.1 (27 Feb 98) - fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) - remove block truncation heuristic which had very marginal effect for zlib (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the compression ratio on some files. This also allows inlining _tr_tally for - matches in deflate_slow. + matches in deflate_slow - added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) Changes in 1.1.0 (24 Feb 98) - do not return STREAM_END prematurely in inflate (John Bowler) - revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) @@ -1146,11 +1239,11 @@ . Simplify Z_FINISH check in inflate() - Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 - in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) - in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with - the declaration of FAR (Gilles VOllant) + the declaration of FAR (Gilles Vollant) - install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) - read_buf buf parameter of type Bytef* instead of charf* - zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) - do not redeclare unlink in minigzip.c for WIN32 (John Bowler) - fix check for presence of directories in "make install" (Ian Willis) @@ -1160,11 +1253,11 @@ - fix gzgetc and gzputc for big endian systems (Markus Oberhumer) - added compress2() to allow setting the compression level - include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) - use constant arrays for the static trees in trees.c instead of computing them at run time (thanks to Ken Raeburn for this suggestion). To create - trees.h, compile with GEN_TREES_H and run "make test". + trees.h, compile with GEN_TREES_H and run "make test" - check return code of example in "make test" and display result - pass minigzip command line options to file_compress - simplifying code of inflateSync to avoid gcc 2.8 bug - support CC="gcc -Wall" in configure -s (QingLong) @@ -1199,16 +1292,16 @@ Changes in 1.0.6 (19 Jan 1998) - add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) - Fix a deflate bug occurring only with compression level 0 (thanks to - Andy Buckler for finding this one). -- In minigzip, pass transparently also the first byte for .Z files. + Andy Buckler for finding this one) +- In minigzip, pass transparently also the first byte for .Z files - return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() - check Z_FINISH in inflate (thanks to Marc Schluper) - Implement deflateCopy (thanks to Adam Costello) -- make static libraries by default in configure, add --shared option. +- make static libraries by default in configure, add --shared option - move MSDOS or Windows specific files to directory msdos - suppress the notion of partial flush to simplify the interface (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) - suppress history buffer provided by application to simplify the interface (this feature was not implemented anyway in 1.0.4) @@ -1216,29 +1309,29 @@ 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 - 386 asm code replacing longest_match(). + 386 asm code replacing longest_match() contrib/iostream/ by Kevin Ruland A C++ I/O streams interface to the zlib gz* functions contrib/iostream2/ by Tyge Løvset Another C++ I/O streams interface contrib/untgz/ by "Pedro A. Aranda Guti\irrez" A very simple tar.gz file extractor using zlib contrib/visual-basic.txt by Carlos Rios - How to use compress(), uncompress() and the gz* functions from VB. + How to use compress(), uncompress() and the gz* functions from VB - pass params -f (filtered data), -h (huffman only), -1 to -9 (compression level) in minigzip (thanks to Tom Lane) - use const for rommable constants in deflate - added test for gzseek and gztell in example.c - add undocumented function inflateSyncPoint() (hack for Paul Mackerras) - add undocumented function zError to convert error code to string (for Tim Smithers) -- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. -- Use default memcpy for Symantec MSDOS compiler. +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code +- Use default memcpy for Symantec MSDOS compiler - Add EXPORT keyword for check_func (needed for Windows DLL) - add current directory to LD_LIBRARY_PATH for "make test" - create also a link for libz.so.1 - added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) - use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) @@ -1247,21 +1340,21 @@ - add advice in zlib.h for best usage of deflateSetDictionary - work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) - allow compilation with ANSI keywords only enabled for TurboC in large model - avoid "versionString"[0] (Borland bug) - add NEED_DUMMY_RETURN for Borland -- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch) - allow compilation with CC - defined STDC for OS/2 (David Charlap) - limit external names to 8 chars for MVS (Thomas Lund) - in minigzip.c, use static buffers only for 16-bit systems - fix suffix check for "minigzip -d foo.gz" - do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) - use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) - added makelcc.bat for lcc-win32 (Tom St Denis) - in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) -- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion - check for unistd.h in configure (for off_t) - remove useless check parameter in inflate_blocks_free - avoid useless assignment of s->check to itself in inflate_blocks_new - do not flush twice in gzclose (thanks to Ken Raeburn) - rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h @@ -1278,11 +1371,11 @@ - Update web address in README Changes in 1.0.4 (24 Jul 96) - In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF bit, so the decompressor could decompress all the correct data but went - on to attempt decompressing extra garbage data. This affected minigzip too. + on to attempt decompressing extra garbage data. This affected minigzip too - zlibVersion and gzerror return const char* (needed for DLL) - port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) - use z_error only for DEBUG (avoid problem with DLLs) Changes in 1.0.3 (2 Jul 96) @@ -1308,11 +1401,11 @@ Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] - fix array overlay in deflate.c which sometimes caused bad compressed data - fix inflate bug with empty stored block - fix MSDOS medium model which was broken in 0.99 -- fix deflateParams() which could generate bad compressed data. +- fix deflateParams() which could generate bad compressed data - Bytef is define'd instead of typedef'ed (work around Borland bug) - added an INDEX file - new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) - speed up adler32 for modern machines without auto-increment @@ -1329,11 +1422,11 @@ Changes in 0.99 (27 Jan 96) - allow preset dictionary shared between compressor and decompressor - allow compression level 0 (no compression) - add deflateParams in zlib.h: allow dynamic change of compression level - and compression strategy. + and compression strategy - test large buffers and deflateParams in example.c - add optional "configure" to build zlib as a shared library - suppress Makefile.qnx, use configure instead - fixed deflate for 64-bit systems (detected on Cray) - fixed inflate_blocks for 64-bit systems (detected on Alpha) @@ -1368,51 +1461,51 @@ - fixed typo in zconf.h (_GNUC__ => __GNUC__) - check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) - fix typo in Make_vms.com (f$trnlnm -> f$getsyi) - in fcalloc, normalize pointer if size > 65520 bytes - don't use special fcalloc for 32 bit Borland C++ -- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc. - use Z_BINARY instead of BINARY - document that gzclose after gzdopen will close the file -- allow "a" as mode in gzopen. +- allow "a" as mode in gzopen - fix error checking in gzread - allow skipping .gz extra-field on pipes - added reference to Perl interface in README - put the crc table in FAR data (I dislike more and more the medium model :) - added get_crc_table -- added a dimension to all arrays (Borland C can't count). +- added a dimension to all arrays (Borland C can't count) - workaround Borland C bug in declaration of inflate_codes_new & inflate_fast - guard against multiple inclusion of *.h (for precompiled header on Mac) -- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- Watcom C pretends to be Microsoft C small model even in 32 bit mode - don't use unsized arrays to avoid silly warnings by Visual C++: warning C4746: 'inflate_mask' : unsized array treated as '__far' - (what's wrong with far data in far model?). + (what's wrong with far data in far model?) - define enum out of inflate_blocks_state to allow compilation with C++ Changes in 0.95 (16 Aug 95) - fix MSDOS small and medium model (now easier to adapt to any compiler) - inlined send_bits - fix the final (:-) bug for deflate with flush (output was correct but - not completely flushed in rare occasions). + not completely flushed in rare occasions) - default window size is same for compression and decompression - (it's now sufficient to set MAX_WBITS in zconf.h). + (it's now sufficient to set MAX_WBITS in zconf.h) - voidp -> voidpf and voidnp -> voidp (for consistency with other - typedefs and because voidnp was not near in large model). + typedefs and because voidnp was not near in large model) Changes in 0.94 (13 Aug 95) - support MSDOS medium model - fix deflate with flush (could sometimes generate bad output) - fix deflateReset (zlib header was incorrectly suppressed) - added support for VMS - allow a compression level in gzopen() - gzflush now calls fflush -- For deflate with flush, flush even if no more input is provided. +- For deflate with flush, flush even if no more input is provided - rename libgz.a as libz.a - avoid complex expression in infcodes.c triggering Turbo C bug - work around a problem with gcc on Alpha (in INSERT_STRING) - don't use inline functions (problem with some gcc versions) -- allow renaming of Byte, uInt, etc... with #define. +- allow renaming of Byte, uInt, etc... with #define - avoid warning about (unused) pointer before start of array in deflate.c - avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c - avoid reserved word 'new' in trees.c Changes in 0.93 (25 June 95) @@ -1427,11 +1520,11 @@ - don't assume that char is signed (problem on SGI) - Clear bit buffer when starting a stored block - no memcpy on Pyramid - suppressed inftest.c - optimized fill_window, put longest_match inline for gcc -- optimized inflate on stored blocks. +- optimized inflate on stored blocks - untabify all sources to simplify patches Changes in 0.91 (2 May 95) - Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h - Document the memory requirements in zconf.h @@ -1445,71 +1538,71 @@ - don't assume that zalloc clears the allocated memory (the TurboC bug was Mark's bug after all :) - let again gzread copy uncompressed data unchanged (was working in 0.71) - deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented - added a test of inflateSync in example.c -- moved MAX_WBITS to zconf.h because users might want to change that. +- moved MAX_WBITS to zconf.h because users might want to change that - document explicitly that zalloc(64K) on MSDOS must return a normalized pointer (zero offset) - added Makefiles for Microsoft C, Turbo C, Borland C++ - faster crc32() Changes in 0.8 (29 April 95) - added fast inflate (inffast.c) - deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this - is incompatible with previous versions of zlib which returned Z_OK. + is incompatible with previous versions of zlib which returned Z_OK - work around a TurboC compiler bug (bad code for b << 0, see infutil.h) (actually that was not a compiler bug, see 0.81 above) - gzread no longer reads one extra byte in certain cases - In gzio destroy(), don't reference a freed structure - avoid many warnings for MSDOS - avoid the ERROR symbol which is used by MS Windows Changes in 0.71 (14 April 95) - Fixed more MSDOS compilation problems :( There is still a bug with - TurboC large model. + TurboC large model Changes in 0.7 (14 April 95) -- Added full inflate support. +- Added full inflate support - Simplified the crc32() interface. The pre- and post-conditioning (one's complement) is now done inside crc32(). WARNING: this is - incompatible with previous versions; see zlib.h for the new usage. + incompatible with previous versions; see zlib.h for the new usage Changes in 0.61 (12 April 95) -- workaround for a bug in TurboC. example and minigzip now work on MSDOS. +- workaround for a bug in TurboC. example and minigzip now work on MSDOS Changes in 0.6 (11 April 95) - added minigzip.c - added gzdopen to reopen a file descriptor as gzFile -- added transparent reading of non-gziped files in gzread. +- added transparent reading of non-gziped files in gzread - fixed bug in gzread (don't read crc as data) -- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose) - don't allocate big arrays in the stack (for MSDOS) - fix some MSDOS compilation problems Changes in 0.5: - do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but - not yet Z_FULL_FLUSH. + not yet Z_FULL_FLUSH - support decompression but only in a single step (forced Z_FINISH) -- added opaque object for zalloc and zfree. +- added opaque object for zalloc and zfree - added deflateReset and inflateReset -- added a variable zlib_version for consistency checking. -- renamed the 'filter' parameter of deflateInit2 as 'strategy'. - Added Z_FILTERED and Z_HUFFMAN_ONLY constants. +- added a variable zlib_version for consistency checking +- renamed the 'filter' parameter of deflateInit2 as 'strategy' + Added Z_FILTERED and Z_HUFFMAN_ONLY constants Changes in 0.4: -- avoid "zip" everywhere, use zlib instead of ziplib. +- avoid "zip" everywhere, use zlib instead of ziplib - suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush - if compression method == 8. + if compression method == 8 - added adler32 and crc32 - renamed deflateOptions as deflateInit2, call one or the other but not both -- added the method parameter for deflateInit2. +- added the method parameter for deflateInit2 - added inflateInit2 -- simplied considerably deflateInit and inflateInit by not supporting +- simplified considerably deflateInit and inflateInit by not supporting user-provided history buffer. This is supported only in deflateInit2 - and inflateInit2. + and inflateInit2 Changes in 0.3: - prefix all macro names with Z_ -- use Z_FINISH instead of deflateEnd to finish compression. +- use Z_FINISH instead of deflateEnd to finish compression - added Z_HUFFMAN_ONLY - added gzerror() Index: compat/zlib/FAQ ================================================================== --- compat/zlib/FAQ +++ compat/zlib/FAQ @@ -2,11 +2,11 @@ Frequently Asked Questions about zlib If your question is not there, please check the zlib home page http://zlib.net/ which may have more recent information. -The lastest zlib FAQ is at http://zlib.net/zlib_faq.html +The latest zlib FAQ is at http://zlib.net/zlib_faq.html 1. Is zlib Y2K-compliant? Yes. zlib doesn't handle dates. Index: compat/zlib/Makefile.in ================================================================== --- compat/zlib/Makefile.in +++ compat/zlib/Makefile.in @@ -5,14 +5,10 @@ # 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 @@ -24,17 +20,17 @@ #CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ # -Wstrict-prototypes -Wmissing-prototypes SFLAGS=-O LDFLAGS= -TEST_LDFLAGS=-L. libz.a +TEST_LDFLAGS=$(LDFLAGS) -L. libz.a LDSHARED=$(CC) CPP=$(CC) -E STATICLIB=libz.a SHAREDLIB=libz.so -SHAREDLIBV=libz.so.1.2.11 +SHAREDLIBV=libz.so.1.3 SHAREDLIBM=libz.so.1 LIBS=$(STATICLIB) $(SHAREDLIBV) AR=ar ARFLAGS=rc @@ -85,48 +81,48 @@ test: all teststatic testshared teststatic: static @TMPST=tmpst_$$; \ - if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \ + if echo hello world | ${QEMU_RUN} ./minigzip | ${QEMU_RUN} ./minigzip -d && ${QEMU_RUN} ./example $$TMPST ; then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; false; \ - fi; \ - rm -f $$TMPST + fi + @rm -f tmpst_$$ testshared: shared @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ TMPSH=tmpsh_$$; \ - if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \ + if echo hello world | ${QEMU_RUN} ./minigzipsh | ${QEMU_RUN} ./minigzipsh -d && ${QEMU_RUN} ./examplesh $$TMPSH; then \ echo ' *** zlib shared test OK ***'; \ else \ echo ' *** zlib shared test FAILED ***'; false; \ - fi; \ - rm -f $$TMPSH + fi + @rm -f tmpsh_$$ test64: all64 @TMP64=tmp64_$$; \ - if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \ + if echo hello world | ${QEMU_RUN} ./minigzip64 | ${QEMU_RUN} ./minigzip64 -d && ${QEMU_RUN} ./example64 $$TMP64; then \ echo ' *** zlib 64-bit test OK ***'; \ else \ echo ' *** zlib 64-bit test FAILED ***'; false; \ - fi; \ - rm -f $$TMP64 + fi + @rm -f tmp64_$$ infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/infcover.c infcover: infcover.o libz.a $(CC) $(CFLAGS) -o $@ infcover.o libz.a cover: infcover rm -f *.gcda - ./infcover + ${QEMU_RUN} ./infcover gcov inf*.c libz.a: $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 @@ -290,14 +286,14 @@ minigzip$(EXE): minigzip.o $(STATICLIB) $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) examplesh$(EXE): example.o $(SHAREDLIBV) - $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV) minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) - $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV) example64$(EXE): example64.o $(STATICLIB) $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) minigzip64$(EXE): minigzip64.o $(STATICLIB) @@ -361,12 +357,18 @@ rm $$TEMPFILE zconf: $(SRCDIR)zconf.h.in cp -p $(SRCDIR)zconf.h.in zconf.h +minizip-test: static + cd contrib/minizip && { CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; } + +minizip-clean: + cd contrib/minizip && { $(MAKE) clean ; cd ../.. ; } + mostlyclean: clean -clean: +clean: minizip-clean rm -f *.o *.lo *~ \ example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ example64$(EXE) minigzip64$(EXE) \ infcover \ libz.* foo.gz so_locations \ @@ -374,19 +376,17 @@ rm -rf objs rm -f *.gcda *.gcno *.gcov rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov maintainer-clean: distclean -distclean: clean zconf zconf.h.cmakein docs +distclean: clean zconf zconf.h.cmakein rm -f Makefile zlib.pc configure.log -@rm -f .DS_Store @if [ -f Makefile.in ]; then \ printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \ printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \ touch -r $(SRCDIR)Makefile.in Makefile ; fi - @if [ ! -f zconf.h.in ]; then rm -f zconf.h zconf.h.cmakein ; fi - @if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf ; fi tags: etags $(SRCDIR)*.[ch] adler32.o zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h Index: compat/zlib/README ================================================================== --- compat/zlib/README +++ compat/zlib/README @@ -1,8 +1,8 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.11 is a general purpose data compression library. All the code is +zlib 1.3 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). @@ -27,22 +27,21 @@ PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at -http://marknelson.us/1997/01/01/zlib-engine/ . +https://marknelson.us/posts/1997/01/01/zlib-engine.html . -The changes made in version 1.2.11 are documented in the file ChangeLog. +The changes made in version 1.3 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . -zlib is available in Java using the java.util.zip package, documented at -http://java.sun.com/developer/technicalArticles/Programming/compression/ . +zlib is available in Java using the java.util.zip package. Follow the API +Documentation link at: https://docs.oracle.com/search/?q=java.util.zip . -A Perl interface to zlib written by Paul Marquess is available -at CPAN (Comprehensive Perl Archive Network) sites, including -http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . +A Perl interface to zlib and bzip2 written by Paul Marquess +can be found at https://github.com/pmqs/IO-Compress . A Python interface to zlib written by A.M. Kuchling is available in Python 1.5 and later versions, see http://docs.python.org/library/zlib.html . @@ -62,11 +61,11 @@ compiler flag). The compiler bug has been reported to SGI. - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works when compiled with cc. -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is +- On Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1 is necessary to get gzprintf working correctly. This is done by configure. - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with other compilers. Use "make test" to check your compiler. @@ -82,11 +81,11 @@ people who reported problems and suggested various improvements in zlib; they are too numerous to cite here. Copyright notice: - (C) 1995-2017 Jean-loup Gailly and Mark Adler + (C) 1995-2023 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. @@ -106,10 +105,13 @@ jloup@gzip.org madler@alumni.caltech.edu If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. +Gailly and Mark Adler; it does not include third-party code. We make all +contributions to and distributions of this project solely in our personal +capacity, and are not conveying any rights to any intellectual property of +any third parties. If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read the FAQ for more information on the distribution of modified source versions. Index: compat/zlib/adler32.c ================================================================== --- compat/zlib/adler32.c +++ compat/zlib/adler32.c @@ -5,12 +5,10 @@ /* @(#) $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;} @@ -58,15 +56,11 @@ # 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; -{ +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; @@ -129,24 +123,16 @@ /* return recombined sums */ return adler | (sum2 << 16); } /* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ +uLong ZEXPORT adler32(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; -{ +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 */ @@ -167,20 +153,12 @@ if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } /* ========================================================================= */ -uLong ZEXPORT adler32_combine(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off_t len2; -{ +uLong ZEXPORT adler32_combine(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; -{ +uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) { return adler32_combine_(adler1, adler2, len2); } Index: compat/zlib/compress.c ================================================================== --- compat/zlib/compress.c +++ compat/zlib/compress.c @@ -17,17 +17,12 @@ 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; -{ +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; @@ -63,24 +58,18 @@ return err == Z_STREAM_END ? Z_OK : err; } /* =========================================================================== */ -int ZEXPORT compress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ +int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen) { return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } /* =========================================================================== If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ -uLong ZEXPORT compressBound (sourceLen) - uLong sourceLen; -{ +uLong ZEXPORT compressBound(uLong sourceLen) { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; } Index: compat/zlib/configure ================================================================== --- compat/zlib/configure +++ compat/zlib/configure @@ -30,21 +30,22 @@ SRCDIR="$SRCDIR/" fi # set command prefix for cross-compilation if [ -n "${CHOST}" ]; then - uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`" + uname=${CHOST} + mname=${CHOST} CROSS_PREFIX="${CHOST}-" +else + mname=`(uname -a || echo unknown) 2>/dev/null` fi # destination name for static library STATICLIB=libz.a # extract zlib version numbers from zlib.h VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h` -VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}zlib.h` -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"} @@ -85,10 +86,12 @@ 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)' @@ -96,11 +99,11 @@ leave() { if test "$*" != "0"; then echo "** $0 aborting." | tee -a configure.log fi - rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version + rm -rf $test.[co] $test $test$shared_ext $test.gcno $test.dSYM ./--version echo -------------------- >> configure.log echo >> configure.log echo >> configure.log exit $1 } @@ -135,10 +138,13 @@ --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 @@ -163,14 +169,21 @@ cat > $test.c </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 @@ -192,64 +205,77 @@ CFLAGS="${CFLAGS} -m64" SFLAGS="${SFLAGS} -m64" fi if test "$warn" -eq 1; then if test "$zconst" -eq 1; then - CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST" + CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -DZLIB_CONST" else - CFLAGS="${CFLAGS} -Wall -Wextra -pedantic" + CFLAGS="${CFLAGS} -Wall -Wextra" fi fi + if test $address -eq 1; then + CFLAGS="${CFLAGS} -g -fsanitize=address -fno-omit-frame-pointer" + fi + if test $memory -eq 1; then + CFLAGS="${CFLAGS} -g -fsanitize=memory -fno-omit-frame-pointer" + fi if test $debug -eq 1; then CFLAGS="${CFLAGS} -DZLIB_DEBUG" SFLAGS="${SFLAGS} -DZLIB_DEBUG" fi if test -z "$uname"; then uname=`(uname -s || echo unknown) 2>/dev/null` fi case "$uname" in - Linux* | linux* | GNU | GNU/* | solaris*) + Linux* | linux* | *-linux* | GNU | GNU/* | solaris*) + case "$mname" in + *sparc*) + LDFLAGS="${LDFLAGS} -Wl,--no-warn-rwx-segments" ;; + esac LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} ;; *BSD | *bsd* | DragonFly) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} LDCONFIG="ldconfig -m" ;; - CYGWIN* | Cygwin* | cygwin* | OS/2*) + CYGWIN* | Cygwin* | cygwin* | *-cygwin* | OS/2*) EXE='.exe' ;; - MINGW* | mingw*) -# temporary bypass + MINGW* | mingw* | *-mingw*) rm -f $test.[co] $test $test$shared_ext - echo "Please use win32/Makefile.gcc instead." | tee -a configure.log - leave 1 + 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 - # (alain.bonnefoy@icbt.com) - LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; + QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 + # (alain.bonnefoy@icbt.com) + LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; HP-UX*) - LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='libz.so' ;; - *) - shared_ext='.sl' - SHAREDLIB='libz.sl' ;; - esac ;; - Darwin* | darwin*) - shared_ext='.dylib' - SHAREDLIB=libz$shared_ext - SHAREDLIBV=libz.$VER$shared_ext - SHAREDLIBM=libz.$VER1$shared_ext - LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} - if libtool -V 2>&1 | grep Apple > /dev/null; then - AR="libtool" - else - AR="/usr/bin/libtool" - fi - ARFLAGS="-o" ;; - *) LDSHARED=${LDSHARED-"$cc -shared"} ;; + LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} + case `(uname -m || echo unknown) 2>/dev/null` in + ia64) + shared_ext='.so' + SHAREDLIB='libz.so' ;; + *) + shared_ext='.sl' + SHAREDLIB='libz.sl' ;; + esac ;; + AIX*) + LDFLAGS="${LDFLAGS} -Wl,-brtl" ;; + Darwin* | darwin* | *-darwin*) + shared_ext='.dylib' + SHAREDLIB=libz$shared_ext + SHAREDLIBV=libz.$VER$shared_ext + SHAREDLIBM=libz.$VER1$shared_ext + LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"} + 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 @@ -365,12 +391,15 @@ echo - using any output from compiler to indicate an error >> configure.log else try() { show $* - ( $* ) >> configure.log 2>&1 + got=`( $* ) 2>&1` ret=$? + if test "$got" != ""; then + printf "%s\n" "$got" >> configure.log + fi if test $ret -ne 0; then echo "(exit code "$ret")" >> configure.log fi return $ret } @@ -379,12 +408,15 @@ tryboth() { show $* got=`( $* ) 2>&1` ret=$? - printf %s "$got" >> configure.log + 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" = "" } @@ -431,24 +463,10 @@ 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 < @@ -455,21 +473,15 @@ #include 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 < $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 <> configure.log # check for large file support, and if none, check for fseeko() @@ -847,21 +855,20 @@ echo SHAREDLIBM = $SHAREDLIBM >> configure.log echo SHAREDLIBV = $SHAREDLIBV >> configure.log echo STATICLIB = $STATICLIB >> configure.log echo TEST = $TEST >> configure.log echo VER = $VER >> configure.log -echo Z_U4 = $Z_U4 >> configure.log echo SRCDIR = $SRCDIR >> configure.log echo exec_prefix = $exec_prefix >> configure.log echo includedir = $includedir >> configure.log echo libdir = $libdir >> configure.log echo mandir = $mandir >> configure.log echo prefix = $prefix >> configure.log echo sharedlibdir = $sharedlibdir >> configure.log echo uname = $uname >> configure.log -# udpate Makefile with the configure results +# update Makefile with the configure results sed < ${SRCDIR}Makefile.in " /^CC *=/s#=.*#=$CC# /^CFLAGS *=/s#=.*#=$CFLAGS# /^SFLAGS *=/s#=.*#=$SFLAGS# /^LDFLAGS *=/s#=.*#=$LDFLAGS# Index: compat/zlib/contrib/README.contrib ================================================================== --- compat/zlib/contrib/README.contrib +++ compat/zlib/contrib/README.contrib @@ -1,23 +1,15 @@ -All files under this contrib directory are UNSUPPORTED. There were +All files under this contrib directory are UNSUPPORTED. They were provided by users of zlib and were not tested by the authors of zlib. Use at your own risk. Please contact the authors of the contributions for help about these, not the zlib authors. Thanks. ada/ by Dmitriy Anisimkov Support for Ada See http://zlib-ada.sourceforge.net/ -amd64/ by Mikhail Teterin - asm code for AMD64 - See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393 - -asm686/ by Brian Raiter - 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 Decompressor for output of PKWare Data Compression Library (DCL) delphi/ by Cosmin Truta Support for Delphi and C++ Builder @@ -30,13 +22,10 @@ assembler to replace longest_match() and inflate_fast() infback9/ by Mark Adler Unsupported diffs to infback to decode the deflate64 format -inflate86/ by Chris Anderson - Tuned x86 gcc asm code to replace inflate_fast() - iostream/ by Kevin Ruland A C++ I/O streams interface to the zlib gz* functions iostream2/ by Tyge Løvset Another C++ I/O streams interface @@ -43,20 +32,10 @@ iostream3/ by Ludwig Schwardt and Kevin Ruland Yet another C++ I/O streams interface -masmx64/ by Gilles Vollant - 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 - 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 Mini zip and unzip based on zlib Includes Zip64 support by Mathias Svensson See http://www.winimage.com/zLibDll/minizip.html Index: compat/zlib/contrib/ada/readme.txt ================================================================== --- compat/zlib/contrib/ada/readme.txt +++ compat/zlib/contrib/ada/readme.txt @@ -6,12 +6,12 @@ It provides Ada-style access to the ZLib C library. Here are the main changes since ZLib.Ada 1.2: -- Attension: ZLib.Read generic routine have a initialization requirement - for Read_Last parameter now. It is a bit incompartible with previous version, +- Attention: ZLib.Read generic routine have a initialization requirement + for Read_Last parameter now. It is a bit incompatible with previous version, but extends functionality, we could use new parameters Allow_Read_Some and Flush now. - Added Is_Open routines to ZLib and ZLib.Streams packages. Index: compat/zlib/contrib/ada/test.adb ================================================================== --- compat/zlib/contrib/ada/test.adb +++ compat/zlib/contrib/ada/test.adb @@ -63,16 +63,16 @@ Filter : ZLib.Filter_Type; Time_Stamp : Ada.Calendar.Time; procedure Generate_File; - -- Generate file of spetsified size with some random data. + -- Generate file of specified size with some random data. -- The random data is repeatable, for the good compression. procedure Compare_Streams (Left, Right : in out Root_Stream_Type'Class); - -- The procedure compearing data in 2 streams. + -- The procedure comparing data in 2 streams. -- It is for compare data before and after compression/decompression. procedure Compare_Files (Left, Right : String); -- Compare files. Based on the Compare_Streams. Index: compat/zlib/contrib/ada/zlib-streams.ads ================================================================== --- compat/zlib/contrib/ada/zlib-streams.ads +++ compat/zlib/contrib/ada/zlib-streams.ads @@ -60,11 +60,11 @@ Header : in Header_Type := Default; Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset := Default_Buffer_Size; Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset := Default_Buffer_Size); - -- Create the Comression/Decompression stream. + -- Create the Compression/Decompression stream. -- If mode is In_Stream then Write operation is disabled. -- If mode is Out_Stream then Read operation is disabled. -- If Back_Compressed is true then -- Data written to the Stream is compressing to the Back stream Index: compat/zlib/contrib/ada/zlib.adb ================================================================== --- compat/zlib/contrib/ada/zlib.adb +++ compat/zlib/contrib/ada/zlib.adb @@ -202,11 +202,11 @@ if Is_Open (Filter) then raise Status_Error; end if; -- We allow ZLib to make header only in case of default header type. - -- Otherwise we would either do header by ourselfs, or do not do + -- Otherwise we would either do header by ourselves, or do not do -- header at all. if Header = None or else Header = GZip then Win_Bits := -Win_Bits; end if; Index: compat/zlib/contrib/ada/zlib.ads ================================================================== --- compat/zlib/contrib/ada/zlib.ads +++ compat/zlib/contrib/ada/zlib.ads @@ -112,11 +112,11 @@ ------------------------------------ -- Compression strategy constants -- ------------------------------------ - -- RLE stategy could be used only in version 1.2.0 and later. + -- RLE strategy could be used only in version 1.2.0 and later. Filtered : constant Strategy_Type; Huffman_Only : constant Strategy_Type; RLE : constant Strategy_Type; Default_Strategy : constant Strategy_Type; DELETED compat/zlib/contrib/amd64/amd64-match.S Index: compat/zlib/contrib/amd64/amd64-match.S ================================================================== --- compat/zlib/contrib/amd64/amd64-match.S +++ /dev/null @@ -1,452 +0,0 @@ -/* - * 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 -#include -#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 Index: compat/zlib/contrib/asm686/README.686 ================================================================== --- compat/zlib/contrib/asm686/README.686 +++ /dev/null @@ -1,51 +0,0 @@ -This is a patched version of zlib, modified to use -Pentium-Pro-optimized assembly code in the deflation algorithm. The -files changed/added by this patch are: - -README.686 -match.S - -The speedup that this patch provides varies, depending on whether the -compiler used to build the original version of zlib falls afoul of the -PPro's speed traps. My own tests show a speedup of around 10-20% at -the default compression level, and 20-30% using -9, against a version -compiled using gcc 2.7.2.3. Your mileage may vary. - -Note that this code has been tailored for the PPro/PII in particular, -and will not perform particuarly well on a Pentium. - -If you are using an assembler other than GNU as, you will have to -translate match.S to use your assembler's syntax. (Have fun.) - -Brian Raiter -breadbox@muppetlabs.com -April, 1998 - - -Added for zlib 1.1.3: - -The patches come from -http://www.muppetlabs.com/~breadbox/software/assembly.html - -To compile zlib with this asm file, copy match.S to the zlib directory -then do: - -CFLAGS="-O3 -DASMV" ./configure -make OBJA=match.o - - -Update: - -I've been ignoring these assembly routines for years, believing that -gcc's generated code had caught up with it sometime around gcc 2.95 -and the major rearchitecting of the Pentium 4. However, I recently -learned that, despite what I believed, this code still has some life -in it. On the Pentium 4 and AMD64 chips, it continues to run about 8% -faster than the code produced by gcc 4.1. - -In acknowledgement of its continuing usefulness, I've altered the -license to match that of the rest of zlib. Share and Enjoy! - -Brian Raiter -breadbox@muppetlabs.com -April, 2007 Index: compat/zlib/contrib/blast/blast.h ================================================================== --- compat/zlib/contrib/blast/blast.h +++ compat/zlib/contrib/blast/blast.h @@ -55,11 +55,11 @@ * available bytes there. If infun() returns zero, then blast() returns with * an input error. (blast() only asks for input if it needs it.) inhow is for * use by the application to pass an input descriptor to infun(), if desired. * * If left and in are not NULL and *left is not zero when blast() is called, - * then the *left bytes are *in are consumed for input before infun() is used. + * then the *left bytes at *in are consumed for input before infun() is used. * * The output function is invoked: err = outfun(how, buf, len), where the bytes * to be written are buf[0..len-1]. If err is not zero, then blast() returns * with an output error. outfun() is always called with len <= 4096. outhow * is for use by the application to pass an output descriptor to outfun(), if Index: compat/zlib/contrib/delphi/ZLib.pas ================================================================== --- compat/zlib/contrib/delphi/ZLib.pas +++ compat/zlib/contrib/delphi/ZLib.pas @@ -150,11 +150,11 @@ BufSize = number of bytes in OutBuf } procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; const OutBuf: Pointer; BufSize: Integer); const - zlib_version = '1.2.11'; + zlib_version = '1.3.0'; type EZlibError = class(Exception); ECompressionError = class(EZlibError); EDecompressionError = class(EZlibError); Index: compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs ================================================================== --- compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs +++ compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs @@ -1,7 +1,7 @@ // -// Copyright Henrik Ravn 2004 +// © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -59,11 +59,11 @@ /// Where in data to start updating /// The number of bytes from data to use /// The sum of offset and count is larger than the length of data /// data is a null reference /// Offset or count is negative. - /// All the other Update methods are implmeneted in terms of this one. + /// All the other Update methods are implemented in terms of this one. /// This is therefore the only method a derived class has to implement public abstract void Update(byte[] data, int offset, int count); /// /// Updates the current checksum with an array of bytes. Index: compat/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs ================================================================== --- compat/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs +++ compat/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs @@ -1,7 +1,7 @@ // -// Copyright Henrik Ravn 2004 +// © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Index: compat/zlib/contrib/dotzlib/DotZLib/CodecBase.cs ================================================================== --- compat/zlib/contrib/dotzlib/DotZLib/CodecBase.cs +++ compat/zlib/contrib/dotzlib/DotZLib/CodecBase.cs @@ -1,7 +1,7 @@ // -// Copyright Henrik Ravn 2004 +// © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -137,11 +137,11 @@ /// Performs any codec specific cleanup /// /// This must be implemented by a derived class protected abstract void CleanUp(); - // performs the release of the handles and calls the dereived CleanUp() + // performs the release of the handles and calls the derived CleanUp() private void CleanUp(bool isDisposing) { if (!_isDisposed) { CleanUp(); @@ -158,11 +158,11 @@ #endregion #region Helper methods /// - /// Copies a number of bytes to the internal codec buffer - ready for proccesing + /// Copies a number of bytes to the internal codec buffer - ready for processing /// /// The byte array that contains the data to copy /// The index of the first byte to copy /// The number of bytes to copy from data protected void copyInput(byte[] data, int startIndex, int count) Index: compat/zlib/contrib/dotzlib/DotZLib/Deflater.cs ================================================================== --- compat/zlib/contrib/dotzlib/DotZLib/Deflater.cs +++ compat/zlib/contrib/dotzlib/DotZLib/Deflater.cs @@ -1,7 +1,7 @@ // -// Copyright Henrik Ravn 2004 +// © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Index: compat/zlib/contrib/dotzlib/DotZLib/DotZLib.cs ================================================================== --- compat/zlib/contrib/dotzlib/DotZLib/DotZLib.cs +++ compat/zlib/contrib/dotzlib/DotZLib/DotZLib.cs @@ -1,7 +1,7 @@ // -// Copyright Henrik Ravn 2004 +// © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Index: compat/zlib/contrib/dotzlib/DotZLib/GZipStream.cs ================================================================== --- compat/zlib/contrib/dotzlib/DotZLib/GZipStream.cs +++ compat/zlib/contrib/dotzlib/DotZLib/GZipStream.cs @@ -1,7 +1,7 @@ // -// Copyright Henrik Ravn 2004 +// © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -244,11 +244,11 @@ { throw new NotSupportedException(); } /// - /// Not suppported. + /// Not supported. /// /// /// /// /// Always thrown @@ -266,11 +266,11 @@ { // left empty on purpose } /// - /// Gets/sets the current position in the GZipStream. Not suppported. + /// Gets/sets the current position in the GZipStream. Not supported. /// /// In this implementation this property is not supported /// Always thrown public override long Position { @@ -283,11 +283,11 @@ throw new NotSupportedException(); } } /// - /// Gets the size of the stream. Not suppported. + /// Gets the size of the stream. Not supported. /// /// In this implementation this property is not supported /// Always thrown public override long Length { Index: compat/zlib/contrib/dotzlib/DotZLib/Inflater.cs ================================================================== --- compat/zlib/contrib/dotzlib/DotZLib/Inflater.cs +++ compat/zlib/contrib/dotzlib/DotZLib/Inflater.cs @@ -1,7 +1,7 @@ // -// Copyright Henrik Ravn 2004 +// © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Index: compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs ================================================================== --- compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs +++ compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs @@ -154,11 +154,11 @@ #region Info tests [Test] public void Info_Version() { Info info = new Info(); - Assert.AreEqual("1.2.11", Info.Version); + Assert.AreEqual("1.3.0", Info.Version); Assert.AreEqual(32, info.SizeOfUInt); Assert.AreEqual(32, info.SizeOfULong); Assert.AreEqual(32, info.SizeOfPointer); Assert.AreEqual(32, info.SizeOfOffset); } Index: compat/zlib/contrib/dotzlib/readme.txt ================================================================== --- compat/zlib/contrib/dotzlib/readme.txt +++ compat/zlib/contrib/dotzlib/readme.txt @@ -34,11 +34,11 @@ 2. Using NAnt: Open a command prompt with access to the build environment and run nant in the same directory as the DotZLib.build file. You can define 2 properties on the nant command-line to control the build: debug={true|false} to toggle between release/debug builds (default=true). - nunit={true|false} to include or esclude unit tests (default=true). + nunit={true|false} to include or exclude unit tests (default=true). Also the target clean will remove binaries. Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on whether you are building the release or debug version of the library. Index: compat/zlib/contrib/infback9/infback9.c ================================================================== --- compat/zlib/contrib/infback9/infback9.c +++ compat/zlib/contrib/infback9/infback9.c @@ -14,16 +14,12 @@ 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; -{ +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; @@ -49,12 +45,11 @@ decoding. */ #ifdef MAKEFIXED #include -void makefixed9(void) -{ +void makefixed9(void) { unsigned sym, bits, low, size; code *next, *lenfix, *distfix; struct inflate_state state; code fixed[544]; @@ -212,17 +207,12 @@ 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; -{ +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 */ @@ -601,15 +591,13 @@ strm->next_in = next; strm->avail_in = have; return ret; } -int ZEXPORT inflateBack9End(strm) -z_stream FAR *strm; -{ +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; } Index: compat/zlib/contrib/infback9/infback9.h ================================================================== --- compat/zlib/contrib/infback9/infback9.h +++ compat/zlib/contrib/infback9/infback9.h @@ -18,18 +18,18 @@ #ifdef __cplusplus extern "C" { #endif -ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -ZEXTERN int ZEXPORT inflateBack9End OF((z_stream FAR *strm)); -ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm, - unsigned char FAR *window, - const char *version, - int stream_size)); +ZEXTERN int ZEXPORT inflateBack9(z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); +ZEXTERN int ZEXPORT inflateBack9End(z_stream FAR *strm); +ZEXTERN int ZEXPORT inflateBack9Init_(z_stream FAR *strm, + unsigned char FAR *window, + const char *version, + int stream_size); #define inflateBack9Init(strm, window) \ inflateBack9Init_((strm), (window), \ ZLIB_VERSION, sizeof(z_stream)) #ifdef __cplusplus Index: compat/zlib/contrib/infback9/inftree9.c ================================================================== --- compat/zlib/contrib/infback9/inftree9.c +++ compat/zlib/contrib/infback9/inftree9.c @@ -1,17 +1,17 @@ /* inftree9.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2017 Mark Adler + * Copyright (C) 1995-2023 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftree9.h" #define MAXBITS 15 const char inflate9_copyright[] = - " inflate9 1.2.11 Copyright 1995-2017 Mark Adler "; + " inflate9 1.3 Copyright 1995-2023 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. @@ -27,18 +27,13 @@ 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; -{ +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 */ @@ -62,11 +57,11 @@ 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, - 133, 133, 133, 133, 144, 77, 202}; + 133, 133, 133, 133, 144, 198, 203}; 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 */ Index: compat/zlib/contrib/infback9/inftree9.h ================================================================== --- compat/zlib/contrib/infback9/inftree9.h +++ compat/zlib/contrib/infback9/inftree9.h @@ -36,11 +36,11 @@ */ /* Maximum size of the dynamic table. The maximum number of code structures is 1446, which is the sum of 852 for literal/length codes and 594 for distance codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that + examples/enough.c found in the zlib distribution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 32 6 15" for distance codes returns 594. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in infback9.c. If the root table size is changed, @@ -54,8 +54,8 @@ CODES, LENS, DISTS } codetype; -extern int inflate_table9 OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); +extern int inflate_table9(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work); DELETED compat/zlib/contrib/inflate86/inffast.S Index: compat/zlib/contrib/inflate86/inffast.S ================================================================== --- compat/zlib/contrib/inflate86/inffast.S +++ /dev/null @@ -1,1368 +0,0 @@ -/* - * 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 - * 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 DELETED compat/zlib/contrib/masmx64/bld_ml64.bat Index: compat/zlib/contrib/masmx64/bld_ml64.bat ================================================================== --- compat/zlib/contrib/masmx64/bld_ml64.bat +++ /dev/null @@ -1,2 +0,0 @@ -ml64.exe /Flinffasx64 /c /Zi inffasx64.asm -ml64.exe /Flgvmat64 /c /Zi gvmat64.asm DELETED compat/zlib/contrib/masmx64/gvmat64.asm Index: compat/zlib/contrib/masmx64/gvmat64.asm ================================================================== --- compat/zlib/contrib/masmx64/gvmat64.asm +++ /dev/null @@ -1,553 +0,0 @@ -;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 Index: compat/zlib/contrib/masmx64/inffas8664.c ================================================================== --- compat/zlib/contrib/masmx64/inffas8664.c +++ /dev/null @@ -1,186 +0,0 @@ -/* 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 - * 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 -#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 Index: compat/zlib/contrib/masmx64/inffasx64.asm ================================================================== --- compat/zlib/contrib/masmx64/inffasx64.asm +++ /dev/null @@ -1,396 +0,0 @@ -; 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 Index: compat/zlib/contrib/masmx64/readme.txt ================================================================== --- compat/zlib/contrib/masmx64/readme.txt +++ /dev/null @@ -1,31 +0,0 @@ -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 Index: compat/zlib/contrib/masmx86/bld_ml32.bat ================================================================== --- compat/zlib/contrib/masmx86/bld_ml32.bat +++ /dev/null @@ -1,2 +0,0 @@ -ml /coff /Zi /c /Flmatch686.lst match686.asm -ml /coff /Zi /c /Flinffas32.lst inffas32.asm DELETED compat/zlib/contrib/masmx86/inffas32.asm Index: compat/zlib/contrib/masmx86/inffas32.asm ================================================================== --- compat/zlib/contrib/masmx86/inffas32.asm +++ /dev/null @@ -1,1080 +0,0 @@ -;/* 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 -; * 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 Index: compat/zlib/contrib/masmx86/match686.asm ================================================================== --- compat/zlib/contrib/masmx86/match686.asm +++ /dev/null @@ -1,479 +0,0 @@ -; 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 -;;; 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 Index: compat/zlib/contrib/masmx86/readme.txt ================================================================== --- compat/zlib/contrib/masmx86/readme.txt +++ /dev/null @@ -1,27 +0,0 @@ - -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" - Index: compat/zlib/contrib/minizip/Makefile ================================================================== --- compat/zlib/contrib/minizip/Makefile +++ compat/zlib/contrib/minizip/Makefile @@ -1,7 +1,7 @@ CC=cc -CFLAGS=-O -I../.. +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: @@ -14,12 +14,16 @@ minizip: $(ZIP_OBJS) $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) test: miniunz minizip - ./minizip test readme.txt + @rm -f test.* + @echo hello hello hello > test.txt + ./minizip test test.txt ./miniunz -l test.zip - mv readme.txt readme.old + @mv test.txt test.old ./miniunz test.zip + @cmp test.txt test.old + @rm -f test.* clean: - /bin/rm -f *.o *~ minizip miniunz + /bin/rm -f *.o *~ minizip miniunz test.* Index: compat/zlib/contrib/minizip/MiniZip64_Changes.txt ================================================================== --- compat/zlib/contrib/minizip/MiniZip64_Changes.txt +++ compat/zlib/contrib/minizip/MiniZip64_Changes.txt @@ -1,6 +1,6 @@ -MiniZip 1.1 was derrived from MiniZip at version 1.01f +MiniZip 1.1 was derived from MiniZip at version 1.01f Change in 1.0 (Okt 2009) - **TODO - Add history** Index: compat/zlib/contrib/minizip/configure.ac ================================================================== --- compat/zlib/contrib/minizip/configure.ac +++ compat/zlib/contrib/minizip/configure.ac @@ -1,9 +1,9 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_INIT([minizip], [1.2.11], [bugzilla.redhat.com]) +AC_INIT([minizip], [1.3.0], [bugzilla.redhat.com]) AC_CONFIG_SRCDIR([minizip.c]) AM_INIT_AUTOMAKE([foreign]) LT_INIT AC_MSG_CHECKING([whether to build example programs]) Index: compat/zlib/contrib/minizip/crypt.h ================================================================== --- compat/zlib/contrib/minizip/crypt.h +++ compat/zlib/contrib/minizip/crypt.h @@ -30,26 +30,24 @@ #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) /*********************************************************************** * Return the next byte in the pseudo-random sequence */ -static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) -{ +static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) { unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an * unpredictable manner on 16-bit systems; not a problem * with any known compiler so far, though */ - (void)pcrc_32_tab; + (void)pcrc_32_tab; temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); } /*********************************************************************** * Update the encryption keys with the next byte of plain text */ -static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) -{ +static int update_keys(unsigned long* pkeys, const z_crc_t* pcrc_32_tab, int c) { (*(pkeys+0)) = CRC32((*(pkeys+0)), c); (*(pkeys+1)) += (*(pkeys+0)) & 0xff; (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; { int keyshift = (int)((*(pkeys+1)) >> 24); @@ -61,12 +59,11 @@ /*********************************************************************** * Initialize the encryption keys and the random header according to * the given password. */ -static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) -{ +static void init_keys(const char* passwd, unsigned long* pkeys, const z_crc_t* pcrc_32_tab) { *(pkeys+0) = 305419896L; *(pkeys+1) = 591751049L; *(pkeys+2) = 878082192L; while (*passwd != '\0') { update_keys(pkeys,pcrc_32_tab,(int)*passwd); @@ -76,28 +73,27 @@ #define zdecode(pkeys,pcrc_32_tab,c) \ (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) #define zencode(pkeys,pcrc_32_tab,c,t) \ - (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), (Byte)t^(c)) #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED #define RAND_HEAD_LEN 12 /* "last resort" source for second part of crypt seed pattern */ # ifndef ZCR_SEED2 -# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ # endif -static int crypthead(const char* passwd, /* password string */ - unsigned char* buf, /* where to write header */ - int bufSize, - unsigned long* pkeys, - const z_crc_t* pcrc_32_tab, - unsigned long crcForCrypting) -{ - int n; /* index in random header */ +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 */ Index: compat/zlib/contrib/minizip/ioapi.c ================================================================== --- compat/zlib/contrib/minizip/ioapi.c +++ compat/zlib/contrib/minizip/ioapi.c @@ -16,11 +16,11 @@ #if defined(_WIN32) #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) _ftelli64(stream) #define FSEEKO_FUNC(stream, offset, origin) _fseeki64(stream, offset, origin) -#elif defined(__APPLE__) || defined(IOAPI_NO_64) +#elif defined(__APPLE__) || defined(IOAPI_NO_64) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) #else @@ -30,22 +30,20 @@ #endif #include "ioapi.h" -voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) -{ +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc, const void*filename, int mode) { if (pfilefunc->zfile_func64.zopen64_file != NULL) return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); else { return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); } } -long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) -{ +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); else { uLong offsetTruncated = (uLong)offset; @@ -54,29 +52,26 @@ else return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); } } -ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) -{ +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc, voidpf filestream) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); else { - uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); + uLong tell_uLong = (uLong)(*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); if ((tell_uLong) == MAXU32) return (ZPOS64_T)-1; else return tell_uLong; } } -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) -{ +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32, const zlib_filefunc_def* p_filefunc32) { p_filefunc64_32->zfile_func64.zopen64_file = NULL; p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; - p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; p_filefunc64_32->zfile_func64.ztell64_file = NULL; p_filefunc64_32->zfile_func64.zseek64_file = NULL; p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; @@ -86,22 +81,14 @@ p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; } -static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); -static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); -static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); -static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); -static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); - -static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) -{ +static voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; + (void)opaque; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) mode_fopen = "rb"; else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) mode_fopen = "r+b"; @@ -112,14 +99,14 @@ if ((filename!=NULL) && (mode_fopen != NULL)) file = fopen(filename, mode_fopen); return file; } -static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) -{ +static voidpf ZCALLBACK fopen64_file_func(voidpf opaque, const void* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; + (void)opaque; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) mode_fopen = "rb"; else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) mode_fopen = "r+b"; @@ -131,43 +118,43 @@ file = FOPEN_FUNC((const char*)filename, mode_fopen); return file; } -static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) -{ +static uLong ZCALLBACK fread_file_func(voidpf opaque, voidpf stream, void* buf, uLong size) { uLong ret; + (void)opaque; ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); return ret; } -static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) -{ +static uLong ZCALLBACK fwrite_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) { uLong ret; + (void)opaque; ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); return ret; } -static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) -{ +static long ZCALLBACK ftell_file_func(voidpf opaque, voidpf stream) { long ret; + (void)opaque; ret = ftell((FILE *)stream); return ret; } -static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) -{ +static ZPOS64_T ZCALLBACK ftell64_file_func(voidpf opaque, voidpf stream) { ZPOS64_T ret; - ret = FTELLO_FUNC((FILE *)stream); + (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) -{ +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; @@ -178,19 +165,19 @@ fseek_origin = SEEK_SET; break; default: return -1; } ret = 0; - if (fseek((FILE *)stream, offset, fseek_origin) != 0) + if (fseek((FILE *)stream, (long)offset, fseek_origin) != 0) ret = -1; return ret; } -static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) -{ +static long ZCALLBACK fseek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { int fseek_origin=0; long ret; + (void)opaque; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : fseek_origin = SEEK_CUR; break; @@ -202,34 +189,32 @@ break; default: return -1; } ret = 0; - if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) + if(FSEEKO_FUNC((FILE *)stream, (z_off64_t)offset, fseek_origin) != 0) ret = -1; return ret; } -static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) -{ +static int ZCALLBACK fclose_file_func(voidpf opaque, voidpf stream) { int ret; + (void)opaque; ret = fclose((FILE *)stream); return ret; } -static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) -{ +static int ZCALLBACK ferror_file_func(voidpf opaque, voidpf stream) { int ret; + (void)opaque; ret = ferror((FILE *)stream); return ret; } -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ +void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen_file = fopen_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; pzlib_filefunc_def->ztell_file = ftell_file_func; pzlib_filefunc_def->zseek_file = fseek_file_func; @@ -236,16 +221,15 @@ pzlib_filefunc_def->zclose_file = fclose_file_func; pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->opaque = NULL; } -void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) -{ +void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = fopen64_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; pzlib_filefunc_def->ztell64_file = ftell64_file_func; pzlib_filefunc_def->zseek64_file = fseek64_file_func; pzlib_filefunc_def->zclose_file = fclose_file_func; pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->opaque = NULL; } Index: compat/zlib/contrib/minizip/ioapi.h ================================================================== --- compat/zlib/contrib/minizip/ioapi.h +++ compat/zlib/contrib/minizip/ioapi.h @@ -48,11 +48,11 @@ #if defined(USE_FILE32API) #define fopen64 fopen #define ftello64 ftell #define fseeko64 fseek #else -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) #define fopen64 fopen #define ftello64 ftello #define fseeko64 fseeko #endif #ifdef _MSC_VER @@ -80,31 +80,33 @@ #ifdef HAVE_MINIZIP64_CONF_H #include "mz64conf.h" #endif -/* a type choosen by DEFINE */ +/* a type chosen by DEFINE */ #ifdef HAVE_64BIT_INT_CUSTOM typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; #else #ifdef HAS_STDINT_H #include "stdint.h" typedef uint64_t ZPOS64_T; #else -/* Maximum unsigned 32-bit value used as placeholder for zip64 */ -#define MAXU32 0xffffffff + #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 ZPOS64_T; #else typedef unsigned long long int ZPOS64_T; #endif #endif #endif - +/* Maximum unsigned 32-bit value used as placeholder for zip64 */ +#ifndef MAXU32 +#define MAXU32 (0xffffffff) +#endif #ifdef __cplusplus extern "C" { #endif @@ -130,18 +132,18 @@ #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)); +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 structure */ typedef struct zlib_filefunc_def_s { @@ -153,13 +155,13 @@ close_file_func zclose_file; testerror_file_func zerror_file; voidpf opaque; } zlib_filefunc_def; -typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) (voidpf opaque, voidpf stream); +typedef long (ZCALLBACK *seek64_file_func) (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin); +typedef voidpf (ZCALLBACK *open64_file_func) (voidpf opaque, const void* filename, int mode); typedef struct zlib_filefunc64_def_s { open64_file_func zopen64_file; read_file_func zread_file; @@ -169,12 +171,12 @@ close_file_func zclose_file; testerror_file_func zerror_file; voidpf opaque; } zlib_filefunc64_def; -void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); +void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def); +void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def); /* now internal definition, only for zip.c and unzip.h */ typedef struct zlib_filefunc64_32_def_s { zlib_filefunc64_def zfile_func64; @@ -189,15 +191,15 @@ //#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) //#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) -voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); -long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); -ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); +voidpf call_zopen64(const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode); +long call_zseek64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin); +ZPOS64_T call_ztell64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream); -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) #define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) Index: compat/zlib/contrib/minizip/iowin32.c ================================================================== --- compat/zlib/contrib/minizip/iowin32.c +++ compat/zlib/contrib/minizip/iowin32.c @@ -26,23 +26,20 @@ #endif // see Include/shared/winapifamily.h in the Windows Kit #if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) + +#if !defined(WINAPI_FAMILY_ONE_PARTITION) +#define WINAPI_FAMILY_ONE_PARTITION(PartitionSet, Partition) ((WINAPI_FAMILY & PartitionSet) == Partition) +#endif + #if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP) #define IOWIN32_USING_WINRT_API 1 #endif #endif -voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); -uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); -long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); -int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); - typedef struct { HANDLE hf; int error; } WIN32FILE_IOWIN; @@ -50,12 +47,11 @@ static void win32_translate_open_mode(int mode, DWORD* lpdwDesiredAccess, DWORD* lpdwCreationDisposition, DWORD* lpdwShareMode, - DWORD* lpdwFlagsAndAttributes) -{ + DWORD* lpdwFlagsAndAttributes) { *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) { *lpdwDesiredAccess = GENERIC_READ; @@ -72,12 +68,11 @@ *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; *lpdwCreationDisposition = CREATE_ALWAYS; } } -static voidpf win32_build_iowin(HANDLE hFile) -{ +static voidpf win32_build_iowin(HANDLE hFile) { voidpf ret=NULL; if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) { WIN32FILE_IOWIN w32fiow; @@ -91,12 +86,11 @@ *((WIN32FILE_IOWIN*)ret) = w32fiow; } return ret; } -voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) -{ +voidpf ZCALLBACK win32_open64_file_func(voidpf opaque, const void* filename, int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); @@ -120,12 +114,11 @@ return win32_build_iowin(hFile); } -voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) -{ +voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void* filename, int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); @@ -144,12 +137,11 @@ return win32_build_iowin(hFile); } -voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) -{ +voidpf ZCALLBACK win32_open64_file_funcW(voidpf opaque, const void* filename, int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); @@ -164,12 +156,11 @@ return win32_build_iowin(hFile); } -voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) -{ +voidpf ZCALLBACK win32_open_file_func(voidpf opaque, const char* filename, int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); @@ -193,12 +184,11 @@ return win32_build_iowin(hFile); } -uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) -{ +uLong ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf,uLong size) { uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; @@ -215,12 +205,11 @@ return ret; } -uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) -{ +uLong ZCALLBACK win32_write_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) { uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; @@ -236,12 +225,11 @@ } return ret; } -static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) -{ +static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) { #ifdef IOWIN32_USING_WINRT_API return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); #else LONG lHigh = pos.HighPart; DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod); @@ -256,12 +244,11 @@ } return fOk; #endif } -long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) -{ +long ZCALLBACK win32_tell_file_func(voidpf opaque, voidpf stream) { long ret=-1; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) @@ -279,12 +266,11 @@ ret=(long)pos.LowPart; } return ret; } -ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) -{ +ZPOS64_T ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream) { ZPOS64_T ret= (ZPOS64_T)-1; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream)->hf; @@ -304,12 +290,11 @@ } return ret; } -long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) -{ +long ZCALLBACK win32_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) { DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; long ret=-1; if (stream!=NULL) @@ -342,12 +327,11 @@ ret=0; } return ret; } -long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) -{ +long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; long ret=-1; if (stream!=NULL) @@ -381,12 +365,11 @@ ret=0; } return ret; } -int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) -{ +int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream) { int ret=-1; if (stream!=NULL) { HANDLE hFile; @@ -399,22 +382,20 @@ free(stream); } return ret; } -int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) -{ +int ZCALLBACK win32_error_file_func(voidpf opaque, voidpf stream) { int ret=-1; if (stream!=NULL) { ret = ((WIN32FILE_IOWIN*)stream) -> error; } return ret; } -void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) -{ +void fill_win32_filefunc(zlib_filefunc_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen_file = win32_open_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell_file = win32_tell_file_func; pzlib_filefunc_def->zseek_file = win32_seek_file_func; @@ -421,12 +402,11 @@ pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } -void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) -{ +void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; @@ -434,12 +414,11 @@ pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } -void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) -{ +void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; @@ -447,16 +426,15 @@ pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } -void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) -{ +void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } Index: compat/zlib/contrib/minizip/iowin32.h ================================================================== --- compat/zlib/contrib/minizip/iowin32.h +++ compat/zlib/contrib/minizip/iowin32.h @@ -16,13 +16,13 @@ #ifdef __cplusplus extern "C" { #endif -void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); -void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc(zlib_filefunc_def* pzlib_filefunc_def); +void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def); +void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def); +void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def); #ifdef __cplusplus } #endif Index: compat/zlib/contrib/minizip/miniunz.c ================================================================== --- compat/zlib/contrib/minizip/miniunz.c +++ compat/zlib/contrib/minizip/miniunz.c @@ -25,11 +25,11 @@ #ifndef _FILE_OFFSET_BIT #define _FILE_OFFSET_BIT 64 #endif #endif -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) #else @@ -43,10 +43,11 @@ #include #include #include #include #include +#include #ifdef _WIN32 # include # include #else @@ -78,15 +79,11 @@ /* 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; -{ +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, @@ -96,10 +93,11 @@ 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; @@ -111,40 +109,42 @@ newdate.tm_year=tmu_date.tm_year ; newdate.tm_isdst=-1; ut.actime=ut.modtime=mktime(&newdate); utime(filename,&ut); +#else + (void)filename; + (void)dosdate; + (void)tmu_date; #endif #endif } /* mymkdir and change_file_date are not 100 % portable As I don't know well Unix, I wait feedback for the unix portion */ -int mymkdir(dirname) - const char* dirname; -{ +static int mymkdir(const char* dirname) { int ret=0; #ifdef _WIN32 ret = _mkdir(dirname); #elif unix ret = mkdir (dirname,0775); #elif __APPLE__ ret = mkdir (dirname,0775); +#else + (void)dirname; #endif return ret; } -int makedir (newdir) - char *newdir; -{ +static int makedir(const char *newdir) { char *buffer ; char *p; - int len = (int)strlen(newdir); + size_t len = strlen(newdir); - if (len <= 0) + if (len == 0) return 0; buffer = (char*)malloc(len+1); if (buffer==NULL) { @@ -183,30 +183,27 @@ } free(buffer); return 1; } -void do_banner() -{ +static void do_banner(void) { printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); } -void do_help() -{ +static void do_help(void) { printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ " -e Extract without pathname (junk paths)\n" \ " -x Extract with pathname\n" \ " -v list files\n" \ " -l list files\n" \ " -d directory to extract into\n" \ " -o overwrite files without prompting\n" \ - " -p extract crypted file using password\n\n"); + " -p extract encrypted file using password\n\n"); } -void Display64BitsSize(ZPOS64_T n, int size_char) -{ +static void Display64BitsSize(ZPOS64_T n, int size_char) { /* to avoid compatibility problem , we do here the conversion */ char number[21]; int offset=19; int pos_string = 19; number[20]=0; @@ -229,13 +226,11 @@ } printf("%s",&number[pos_string]); } -int do_list(uf) - unzFile uf; -{ +static int do_list(unzFile uf) { uLong i; unz_global_info64 gi; int err; err = unzGetGlobalInfo64(uf,&gi); @@ -246,11 +241,11 @@ for (i=0;i0) ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); - /* display a '*' if the file is crypted */ + /* display a '*' if the file is encrypted */ if ((file_info.flag & 1) != 0) charCrypt='*'; if (file_info.compression_method==0) string_method="Stored"; @@ -307,26 +302,20 @@ 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; -{ +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; - 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); @@ -437,11 +426,11 @@ { printf("error %d with zipfile in unzReadCurrentFile\n",err); break; } if (err>0) - if (fwrite(buf,err,1,fout)!=1) + if (fwrite(buf,(unsigned)err,1,fout)!=1) { printf("error in writing extracted file\n"); err=UNZ_ERRNO; break; } @@ -470,20 +459,14 @@ 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; -{ +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; - FILE* fout=NULL; err = unzGetGlobalInfo64(uf,&gi); if (err!=UNZ_OK) printf("error %d with zipfile in unzGetGlobalInfo \n",err); @@ -506,18 +489,11 @@ } 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; +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; } @@ -529,14 +505,11 @@ else return 1; } -int main(argc,argv) - int argc; - char *argv[]; -{ +int main(int argc, char *argv[]) { const char *zipfilename=NULL; const char *filename_to_extract=NULL; const char *password=NULL; char filename_try[MAXFILENAME+16] = ""; int i; @@ -563,11 +536,11 @@ { const char *p=argv[i]+1; while ((*p)!='\0') { - char c=*(p++);; + char c=*(p++); if ((c=='l') || (c=='L')) opt_do_list = 1; if ((c=='v') || (c=='V')) opt_do_list = 1; if ((c=='x') || (c=='X')) @@ -605,11 +578,11 @@ # ifdef USEWIN32IOAPI zlib_filefunc64_def ffunc; # endif strncpy(filename_try, zipfilename,MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ + /* strncpy doesn't append the trailing NULL, of the string is too long. */ filename_try[ MAXFILENAME ] = '\0'; # ifdef USEWIN32IOAPI fill_win32_filefunc64A(&ffunc); uf = unzOpen2_64(zipfilename,&ffunc); Index: compat/zlib/contrib/minizip/minizip.c ================================================================== --- compat/zlib/contrib/minizip/minizip.c +++ compat/zlib/contrib/minizip/minizip.c @@ -9,10 +9,11 @@ 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 @@ -63,23 +64,24 @@ #include "zip.h" #ifdef _WIN32 #define USEWIN32IOAPI #include "iowin32.h" +# if defined(_MSC_VER) +# define snprintf _snprintf +# endif #endif #define WRITEBUFFERSIZE (16384) #define MAXFILENAME (256) #ifdef _WIN32 -uLong filetime(f, tmzip, dt) - const char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ +/* f: name of file to get info on, tmzip: return value: access, + modification and creation times, dt: dostime */ +static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { int ret = 0; { FILETIME ftLocal; HANDLE hFind; WIN32_FIND_DATAA ff32; @@ -95,29 +97,28 @@ } return ret; } #else #if defined(unix) || defined(__APPLE__) -uLong filetime(f, tmzip, dt) - const char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ +/* f: name of file to get info on, tmzip: return value: access, + modification and creation times, dt: dostime */ +static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { + (void)dt; int ret=0; struct stat s; /* results of stat() */ struct tm* filedate; time_t tm_t=0; if (strcmp(f,"-")!=0) { char name[MAXFILENAME+1]; - int len = strlen(f); + size_t len = strlen(f); if (len > MAXFILENAME) len = MAXFILENAME; strncpy(name, f,MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ + /* strncpy doesn't append the trailing NULL, of the string is too long. */ name[ MAXFILENAME ] = '\0'; if (name[len - 1] == '/') name[len - 1] = '\0'; /* not all systems allow stat'ing a file with / appended */ @@ -137,26 +138,25 @@ tmzip->tm_year = filedate->tm_year; return ret; } #else -uLong filetime(f, tmzip, dt) - const char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ +/* f: name of file to get info on, tmzip: return value: access, + modification and creation times, dt: dostime */ +static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { + (void)f; + (void)tmzip; + (void)dt; return 0; } #endif #endif -int check_exist_file(filename) - const char* filename; -{ +static int check_exist_file(const char* filename) { FILE* ftestexist; int ret = 1; ftestexist = FOPEN_FUNC(filename,"rb"); if (ftestexist==NULL) ret = 0; @@ -163,18 +163,16 @@ else fclose(ftestexist); return ret; } -void do_banner() -{ +static void do_banner(void) { printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); } -void do_help() -{ +static void do_help(void) { printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ " -r Scan directories recursively\n" \ " -o Overwrite existing file.zip\n" \ " -a Append to existing file.zip\n" \ " -0 Store only\n" \ @@ -183,38 +181,37 @@ " -j exclude path. store only the file name.\n\n"); } /* calculate the CRC32 of a file, because to encrypt a file, we need known the CRC32 of the file before */ -int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) -{ +static int getFileCrc(const char* filenameinzip, void* buf, unsigned long size_buf, unsigned long* result_crc) { unsigned long calculate_crc=0; int err=ZIP_OK; FILE * fin = FOPEN_FUNC(filenameinzip,"rb"); unsigned long size_read = 0; - unsigned long total_read = 0; + /* unsigned long total_read = 0; */ if (fin==NULL) { err = ZIP_ERRNO; } if (err == ZIP_OK) do { err = ZIP_OK; - size_read = (int)fread(buf,1,size_buf,fin); + size_read = fread(buf,1,size_buf,fin); if (size_read < size_buf) if (feof(fin)==0) { printf("error in reading %s\n",filenameinzip); err = ZIP_ERRNO; } if (size_read>0) - calculate_crc = crc32(calculate_crc,buf,size_read); - total_read += size_read; + calculate_crc = crc32_z(calculate_crc,buf,size_read); + /* total_read += size_read; */ } while ((err == ZIP_OK) && (size_read>0)); if (fin) fclose(fin); @@ -222,22 +219,21 @@ *result_crc=calculate_crc; printf("file %s crc %lx\n", filenameinzip, calculate_crc); return err; } -int isLargeFile(const char* filename) -{ +static int isLargeFile(const char* filename) { int largeFile = 0; ZPOS64_T pos = 0; FILE* pFile = FOPEN_FUNC(filename, "rb"); if(pFile != NULL) { - int n = FSEEKO_FUNC(pFile, 0, SEEK_END); - pos = FTELLO_FUNC(pFile); + FSEEKO_FUNC(pFile, 0, SEEK_END); + pos = (ZPOS64_T)FTELLO_FUNC(pFile); - printf("File : %s is %lld bytes\n", filename, pos); + printf("File : %s is %llu bytes\n", filename, pos); if(pos >= 0xffffffff) largeFile = 1; fclose(pFile); @@ -361,21 +357,21 @@ void addPathToZip(zipFile zf, const char *filenameinzip, const char *password, int opt_exclude_path,int opt_compress_level) { tinydir_dir dir; int i; - char newname[512]; + char newname[MAXFILENAME+1+MAXFILENAME+1]; tinydir_open_sorted(&dir, filenameinzip); for (i = 0; i < dir.n_files; i++) { tinydir_file file; tinydir_readfile_n(&dir, &file, i); if(strcmp(file.name,".")==0) continue; if(strcmp(file.name,"..")==0) continue; - sprintf(newname,"%s/%s",dir.path,file.name); + snprintf(newname, sizeof(newname), "%.*s/%.*s", MAXFILENAME, dir.path, MAXFILENAME, file.name); if (file.is_dir) { addPathToZip(zf,newname,password,opt_exclude_path,opt_compress_level); } else { addFileToZip(zf,newname,password,opt_exclude_path,opt_compress_level); @@ -384,24 +380,21 @@ tinydir_close(&dir); } -int main(argc,argv) - int argc; - char *argv[]; -{ +int main(int argc, char *argv[]) { int i; int opt_recursive=0; - int opt_overwrite=1; + int opt_overwrite=0; int opt_compress_level=Z_DEFAULT_COMPRESSION; int opt_exclude_path=0; int zipfilenamearg = 0; char filename_try[MAXFILENAME+16]; int zipok; int err=0; - int size_buf=0; + size_t size_buf=0; void* buf=NULL; const char* password=NULL; do_banner(); @@ -418,11 +411,11 @@ { const char *p=argv[i]+1; while ((*p)!='\0') { - char c=*(p++);; + char c=*(p++); if ((c=='o') || (c=='O')) opt_overwrite = 1; if ((c=='a') || (c=='A')) opt_overwrite = 2; if ((c>='0') && (c<='9')) @@ -429,10 +422,11 @@ 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> 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; -{ +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) { Index: compat/zlib/contrib/minizip/tinydir.h ================================================================== --- compat/zlib/contrib/minizip/tinydir.h +++ compat/zlib/contrib/minizip/tinydir.h @@ -1,7 +1,7 @@ /* -Copyright (c) 2013-2017, tinydir authors: +Copyright (c) 2013-2021, tinydir authors: - Cong Xu - Lautis Sun - Baudouin Feildel - Andargor All rights reserved. @@ -43,11 +43,13 @@ #include #include #include #ifdef _MSC_VER -# define WIN32_LEAN_AND_MEAN +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include # include # pragma warning(push) # pragma warning (disable : 4996) #else @@ -87,16 +89,20 @@ #if (defined _MSC_VER || defined __MINGW32__) # include # define _TINYDIR_PATH_MAX MAX_PATH #elif defined __linux__ # include -# define _TINYDIR_PATH_MAX PATH_MAX +# ifdef PATH_MAX +# define _TINYDIR_PATH_MAX PATH_MAX +# endif #elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) # include # if defined(BSD) # include -# define _TINYDIR_PATH_MAX PATH_MAX +# ifdef PATH_MAX +# define _TINYDIR_PATH_MAX PATH_MAX +# endif # endif #endif #ifndef _TINYDIR_PATH_MAX #define _TINYDIR_PATH_MAX 4096 @@ -117,12 +123,17 @@ #ifdef _MSC_VER # define _TINYDIR_FUNC static __inline #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # define _TINYDIR_FUNC static __inline__ -#else +#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 @@ -363,11 +374,11 @@ goto bail; } } tinydir_close(dir); - if (tinydir_open(dir, path) == -1) + if (n_files == 0 || tinydir_open(dir, path) == -1) { return -1; } dir->n_files = 0; @@ -490,10 +501,11 @@ } _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; } @@ -504,46 +516,35 @@ #endif { errno = ENOENT; return -1; } - if (_tinydir_strlen(dir->path) + - _tinydir_strlen( + filename = #ifdef _MSC_VER - dir->_f.cFileName + dir->_f.cFileName; #else - dir->_e->d_name + dir->_e->d_name; #endif - ) + 1 + _TINYDIR_PATH_EXTRA >= + 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( -#ifdef _MSC_VER - dir->_f.cFileName -#else - dir->_e->d_name -#endif - ) >= _TINYDIR_FILENAME_MAX) + if (_tinydir_strlen(filename) >= _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); + 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( @@ -656,38 +657,38 @@ } /* Get the parent path */ #if (defined _MSC_VER || defined __MINGW32__) #if ((defined _MSC_VER) && (_MSC_VER >= 1400)) - _tsplitpath_s( - path, - drive_buf, _TINYDIR_DRIVE_MAX, - dir_name_buf, _TINYDIR_FILENAME_MAX, - file_name_buf, _TINYDIR_FILENAME_MAX, - ext_buf, _TINYDIR_FILENAME_MAX); + errno = _tsplitpath_s( + path, + drive_buf, _TINYDIR_DRIVE_MAX, + dir_name_buf, _TINYDIR_FILENAME_MAX, + file_name_buf, _TINYDIR_FILENAME_MAX, + ext_buf, _TINYDIR_FILENAME_MAX); #else - _tsplitpath( - path, - drive_buf, - dir_name_buf, - file_name_buf, - ext_buf); -#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'; + _tsplitpath( + path, + drive_buf, + dir_name_buf, + file_name_buf, + ext_buf); #endif if (errno) { - errno = EINVAL; return -1; } + +/* _splitpath_s not work fine with only filename and widechar support */ +#ifdef _UNICODE + if (drive_buf[0] == L'\xFEFE') + drive_buf[0] = '\0'; + if (dir_name_buf[0] == L'\xFEFE') + dir_name_buf[0] = '\0'; +#endif + /* Emulate the behavior of dirname by returning "." for dir name if it's empty */ if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0') { _tinydir_strcpy(dir_name_buf, TINYDIR_STRING(".")); @@ -700,12 +701,27 @@ base_name = file_name_buf; #else _tinydir_strcpy(dir_name_buf, path); dir_name = dirname(dir_name_buf); _tinydir_strcpy(file_name_buf, path); - base_name =basename(file_name_buf); + base_name = basename(file_name_buf); +#endif + + /* Special case: if the path is a root dir, open the parent dir as the file */ +#if (defined _MSC_VER || defined __MINGW32__) + if (_tinydir_strlen(base_name) == 0) +#else + if ((_tinydir_strcmp(base_name, TINYDIR_STRING("/"))) == 0) #endif + { + memset(file, 0, sizeof * file); + file->is_dir = 1; + file->is_reg = 0; + _tinydir_strcpy(file->path, dir_name); + file->extension = file->path + _tinydir_strlen(file->path); + return 0; + } /* Open the parent directory */ if (tinydir_open(&dir, dir_name) == -1) { return -1; Index: compat/zlib/contrib/minizip/unzip.c ================================================================== --- compat/zlib/contrib/minizip/unzip.c +++ compat/zlib/contrib/minizip/unzip.c @@ -47,16 +47,16 @@ 2007-2008 - Even Rouault - Add unzip support for ZIP64 Copyright (C) 2007-2008 Even Rouault - Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G should only read the compressed/uncompressed size from the Zip64 format if the size from normal header was 0xFFFFFFFF - Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant - Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) + Oct-2009 - Mathias Svensson - Applied some bug fixes from patches received from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression method BZIP2 (bzip2 lib is required) Patch created by Daniel Borca Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson @@ -75,12 +75,10 @@ #include "zlib.h" #include "unzip.h" #ifdef STDC # include -# include -# include #endif #ifdef NO_ERRNO_H extern int errno; #else # include @@ -109,13 +107,10 @@ #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) @@ -151,11 +146,11 @@ uLong crc32; /* crc32 of all data uncompressed */ uLong crc32_wait; /* crc32 we must obtain after decompress all */ ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ uLong compression_method; /* compression method (0==store) */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ int raw; } file_in_zip64_read_info_s; @@ -164,11 +159,11 @@ */ typedef struct { zlib_filefunc64_32_def z_filefunc; int is64bitOpenFunction; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ unz_global_info64 gi; /* public global information */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ ZPOS64_T num_file; /* number of the current file in the zipfile*/ ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ @@ -194,162 +189,80 @@ #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. + Reads a long in LSB order from the given gz_stream. Sets */ - -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; +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; } } - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unz64local_getShort OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX)); - - -local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX) -{ - ZPOS64_T x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (ZPOS64_T)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<24; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<32; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<40; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<48; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<56; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - /* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) -{ +local int strcmpcasenosensitive_internal(const char* fileName1, const char* fileName2) { for (;;) { char c1=*(fileName1++); char c2=*(fileName2++); if ((c1>='a') && (c1<='z')) @@ -377,23 +290,21 @@ #ifndef STRCMPCASENOSENTIVEFUNCTION #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal #endif /* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + Compare two filenames (fileName1,fileName2). + If iCaseSensitivity = 1, comparison is case sensitive (like strcmp) + If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + If iCaseSensitivity = 0, case sensitivity is default of your operating system (like 1 on Unix, 2 on Windows) */ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, - const char* fileName2, - int iCaseSensitivity) - -{ + const char* fileName2, + int iCaseSensitivity) { if (iCaseSensitivity==0) iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; if (iCaseSensitivity==1) return strcmp(fileName1,fileName2); @@ -403,35 +314,37 @@ #ifndef BUFREADCOMMENT #define BUFREADCOMMENT (0x400) #endif +#ifndef CENTRALDIRINVALID +#define CENTRALDIRINVALID ((ZPOS64_T)(-1)) +#endif + /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); -local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; + ZPOS64_T uPosFound=CENTRALDIRINVALID; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; + return CENTRALDIRINVALID; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) - return 0; + return CENTRALDIRINVALID; uBackRead = 4; while (uBackRead0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { - uPosFound = uReadPos+i; + uPosFound = uReadPos+(unsigned)i; break; } - if (uPosFound!=0) + if (uPosFound!=CENTRALDIRINVALID) break; } - TRYFREE(buf); + free(buf); return uPosFound; } /* Locate the Central directory 64 of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T unz64local_SearchCentralDir64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream)); - local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream) -{ + voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; + ZPOS64_T uPosFound=CENTRALDIRINVALID; uLong uL; ZPOS64_T relativeOffset; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; + return CENTRALDIRINVALID; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) - return 0; + return CENTRALDIRINVALID; uBackRead = 4; while (uBackRead0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { - uPosFound = uReadPos+i; + uPosFound = uReadPos+(unsigned)i; break; } - if (uPosFound!=0) + if (uPosFound!=CENTRALDIRINVALID) break; } - TRYFREE(buf); - if (uPosFound == 0) - return 0; + free(buf); + if (uPosFound == CENTRALDIRINVALID) + return CENTRALDIRINVALID; /* Zip64 end of central directory locator */ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; + return CENTRALDIRINVALID; /* the signature, already checked */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; + return CENTRALDIRINVALID; /* number of the disk with the start of the zip64 end of central directory */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; + return CENTRALDIRINVALID; if (uL != 0) - return 0; + return CENTRALDIRINVALID; /* relative offset of the zip64 end of central directory record */ if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) - return 0; + return CENTRALDIRINVALID; /* total number of disks */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; + return CENTRALDIRINVALID; if (uL != 1) - return 0; + return CENTRALDIRINVALID; /* Goto end of central directory record */ if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; + return CENTRALDIRINVALID; /* the signature */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; + return CENTRALDIRINVALID; if (uL != 0x06064b50) - return 0; + return CENTRALDIRINVALID; return relativeOffset; } /* @@ -579,23 +487,22 @@ If the zipfile cannot be opened (file doesn't exist or in not valid), the return value is NULL. Else, the return value is a unzFile Handle, usable with other function of this unzip package. */ -local unzFile unzOpenInternal (const void *path, - zlib_filefunc64_32_def* pzlib_filefunc64_32_def, - int is64bitOpenFunction) -{ +local unzFile unzOpenInternal(const void *path, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def, + int is64bitOpenFunction) { unz64_s us; unz64_s *s; ZPOS64_T central_pos; uLong uL; uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ + spanning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ + 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; @@ -619,11 +526,11 @@ ZLIB_FILEFUNC_MODE_EXISTING); if (us.filestream==NULL) return NULL; central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); - if (central_pos) + if (central_pos!=CENTRALDIRINVALID) { uLong uS; ZPOS64_T uL64; us.isZip64 = 1; @@ -681,11 +588,11 @@ us.gi.size_comment = 0; } else { central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); - if (central_pos==0) + if (central_pos==CENTRALDIRINVALID) err=UNZ_ERRNO; us.isZip64 = 0; if (ZSEEK64(us.z_filefunc, us.filestream, @@ -760,13 +667,12 @@ } return (unzFile)s; } -extern unzFile ZEXPORT unzOpen2 (const char *path, - zlib_filefunc_def* pzlib_filefunc32_def) -{ +extern unzFile ZEXPORT unzOpen2(const char *path, + zlib_filefunc_def* pzlib_filefunc32_def) { if (pzlib_filefunc32_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0); @@ -773,13 +679,12 @@ } else return unzOpenInternal(path, NULL, 0); } -extern unzFile ZEXPORT unzOpen2_64 (const void *path, - zlib_filefunc64_def* pzlib_filefunc_def) -{ +extern unzFile ZEXPORT unzOpen2_64(const void *path, + zlib_filefunc64_def* pzlib_filefunc_def) { if (pzlib_filefunc_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; zlib_filefunc64_32_def_fill.ztell32_file = NULL; @@ -788,57 +693,52 @@ } else return unzOpenInternal(path, NULL, 1); } -extern unzFile ZEXPORT unzOpen (const char *path) -{ +extern unzFile ZEXPORT unzOpen(const char *path) { return unzOpenInternal(path, NULL, 0); } -extern unzFile ZEXPORT unzOpen64 (const void *path) -{ +extern unzFile ZEXPORT unzOpen64(const void *path) { return unzOpenInternal(path, NULL, 1); } /* Close a ZipFile opened with unzOpen. If there is files inside the .Zip opened with unzOpenCurrentFile (see later), these files MUST be closed with unzCloseCurrentFile before call unzClose. return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzClose (unzFile file) -{ +extern int ZEXPORT unzClose(unzFile file) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; if (s->pfile_in_zip_read!=NULL) unzCloseCurrentFile(file); ZCLOSE64(s->z_filefunc, s->filestream); - TRYFREE(s); + free(s); return UNZ_OK; } /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) -{ +extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64* pglobal_info) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; *pglobal_info=s->gi; return UNZ_OK; } -extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) -{ +extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; /* to do : check if number_entry is not truncated */ @@ -845,50 +745,37 @@ pglobal_info32->number_entry = (uLong)s->gi.number_entry; pglobal_info32->size_comment = s->gi.size_comment; return UNZ_OK; } /* - Translate date/time from Dos format to tm_unz (readable more easilty) + Translate date/time from Dos format to tm_unz (readable more easily) */ -local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) -{ +local void unz64local_DosDateToTmuDate(ZPOS64_T ulDosDate, tm_unz* ptm) { ZPOS64_T uDate; uDate = (ZPOS64_T)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + ptm->tm_mday = (int)(uDate&0x1f) ; + ptm->tm_mon = (int)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (int)(((uDate&0x0FE00)/0x0200)+1980) ; - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; + ptm->tm_hour = (int) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (int) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (int) (2*(ulDosDate&0x1f)) ; } /* Get Info about the current file in the zipfile, with internal only info */ -local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - 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) -{ +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; @@ -991,11 +878,11 @@ else uSizeRead = extraFieldBufferSize; if (lSeek!=0) { - if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } @@ -1016,11 +903,11 @@ // since lSeek now points to after the extra field we need to move back lSeek -= file_info.size_file_extra; if (lSeek!=0) { - if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } @@ -1036,37 +923,35 @@ 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; - } + 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) @@ -1088,11 +973,11 @@ else uSizeRead = commentBufferSize; if (lSeek!=0) { - if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } @@ -1119,28 +1004,26 @@ /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, - unz_file_info64 * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ +extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) { return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); } -extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, - unz_file_info * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ +extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) { int err; unz_file_info64 file_info64; err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, szFileName,fileNameBufferSize, extraField,extraFieldBufferSize, @@ -1160,11 +1043,11 @@ pfile_info->disk_num_start = file_info64.disk_num_start; pfile_info->internal_fa = file_info64.internal_fa; pfile_info->external_fa = file_info64.external_fa; - pfile_info->tmu_date = file_info64.tmu_date, + pfile_info->tmu_date = file_info64.tmu_date; pfile_info->compressed_size = (uLong)file_info64.compressed_size; pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; @@ -1173,12 +1056,11 @@ } /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ -extern int ZEXPORT unzGoToFirstFile (unzFile file) -{ +extern int ZEXPORT unzGoToFirstFile(unzFile file) { int err=UNZ_OK; unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; @@ -1194,12 +1076,11 @@ /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ -extern int ZEXPORT unzGoToNextFile (unzFile file) -{ +extern int ZEXPORT unzGoToNextFile(unzFile file) { unz64_s* s; int err; if (file==NULL) return UNZ_PARAMERROR; @@ -1227,12 +1108,11 @@ return value : UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ -extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) -{ +extern int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) { unz64_s* s; int err; /* We remember the 'current' position in the file so that we can jump * back there if we fail. @@ -1303,12 +1183,11 @@ ZPOS64_T pos_in_zip_directory; // offset in file ZPOS64_T num_of_file; // # of file } unz_file_pos; */ -extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) -{ +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) { unz64_s* s; if (file==NULL || file_pos==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; @@ -1319,14 +1198,11 @@ file_pos->num_of_file = s->num_file; return UNZ_OK; } -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos) -{ +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; @@ -1333,12 +1209,11 @@ file_pos->num_of_file = (uLong)file_pos64.num_of_file; } return err; } -extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) -{ +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) { unz64_s* s; int err; if (file==NULL || file_pos==NULL) return UNZ_PARAMERROR; @@ -1355,14 +1230,11 @@ /* return results */ s->current_file_ok = (err == UNZ_OK); return err; } -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos) -{ +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; @@ -1380,14 +1252,13 @@ Check the coherency of the local header and info in the end of central directory about this file store in *piSizeVar the size of extra info in local header (filename and size of extra field data) */ -local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, - ZPOS64_T * poffset_local_extrafield, - uInt * psize_local_extrafield) -{ +local int unz64local_CheckCurrentFileCoherencyHeader(unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) { uLong uMagic,uData,uFlags; uLong size_filename; uLong size_extra_field; int err=UNZ_OK; @@ -1467,13 +1338,12 @@ /* Open for reading data the current file in the zipfile. If there is no error and the file is opened, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, - int* level, int raw, const char* password) -{ +extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int* method, + int* level, int raw, const char* password) { int err=UNZ_OK; uInt iSizeVar; unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ @@ -1507,11 +1377,11 @@ pfile_in_zip_read_info->pos_local_extrafield=0; pfile_in_zip_read_info->raw=raw; if (pfile_in_zip_read_info->read_buffer==NULL) { - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info); return UNZ_INTERNALERROR; } pfile_in_zip_read_info->stream_initialised=0; @@ -1564,11 +1434,12 @@ 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); + 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 @@ -1584,11 +1455,12 @@ 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); + 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 @@ -1636,29 +1508,25 @@ return UNZ_OK; } -extern int ZEXPORT unzOpenCurrentFile (unzFile file) -{ +extern int ZEXPORT unzOpenCurrentFile(unzFile file) { return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); } -extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) -{ +extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char* password) { return unzOpenCurrentFile3(file, NULL, NULL, 0, password); } -extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) -{ +extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int* method, int* level, int raw) { return unzOpenCurrentFile3(file, method, level, raw, NULL); } /** Addition for GDAL : START */ -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) -{ +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; s=(unz64_s*)file; if (file==NULL) return 0; //UNZ_PARAMERROR; @@ -1674,17 +1542,16 @@ /* Read bytes from the current file. buf contain buffer where data must be copied len the size of buf. - return the number of byte copied if somes bytes are copied + return the number of byte copied if some bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ -extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) -{ +extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { int err=UNZ_OK; uInt iRead = 0; unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) @@ -1765,11 +1632,11 @@ { uInt uDoCopy,i ; if ((pfile_in_zip_read_info->stream.avail_in == 0) && (pfile_in_zip_read_info->rest_read_compressed == 0)) - return (iRead==0) ? UNZ_EOF : iRead; + return (iRead==0) ? UNZ_EOF : (int)iRead; if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) uDoCopy = pfile_in_zip_read_info->stream.avail_out ; else @@ -1855,10 +1722,13 @@ 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 (uTotalOutAftertotal_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; pfile_in_zip_read_info->crc32 = @@ -1869,27 +1739,26 @@ uOutThis; iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; + return (iRead==0) ? UNZ_EOF : (int)iRead; if (err!=Z_OK) break; } } if (err==Z_OK) - return iRead; + return (int)iRead; return err; } /* Give the current position in uncompressed data */ -extern z_off_t ZEXPORT unztell (unzFile file) -{ +extern z_off_t ZEXPORT unztell(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; @@ -1899,12 +1768,11 @@ return UNZ_PARAMERROR; return (z_off_t)pfile_in_zip_read_info->stream.total_out; } -extern ZPOS64_T ZEXPORT unztell64 (unzFile file) -{ +extern ZPOS64_T ZEXPORT unztell64(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return (ZPOS64_T)-1; @@ -1919,12 +1787,11 @@ /* return 1 if the end of file was reached, 0 elsewhere */ -extern int ZEXPORT unzeof (unzFile file) -{ +extern int ZEXPORT unzeof(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; @@ -1951,12 +1818,11 @@ if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. the return value is the number of bytes copied in buf, or (if <0) the error code */ -extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) -{ +extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; uInt read_now; ZPOS64_T size_to_read; @@ -1999,12 +1865,11 @@ /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ -extern int ZEXPORT unzCloseCurrentFile (unzFile file) -{ +extern int ZEXPORT unzCloseCurrentFile(unzFile file) { int err=UNZ_OK; unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) @@ -2022,11 +1887,11 @@ if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) err=UNZ_CRCERROR; } - TRYFREE(pfile_in_zip_read_info->read_buffer); + free(pfile_in_zip_read_info->read_buffer); pfile_in_zip_read_info->read_buffer = NULL; if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) inflateEnd(&pfile_in_zip_read_info->stream); #ifdef HAVE_BZIP2 else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) @@ -2033,11 +1898,11 @@ BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); #endif pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info); s->pfile_in_zip_read=NULL; return err; } @@ -2046,12 +1911,11 @@ /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ -extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) -{ +extern int ZEXPORT unzGetGlobalComment(unzFile file, char * szComment, uLong uSizeBuf) { unz64_s* s; uLong uReadThis ; if (file==NULL) return (int)UNZ_PARAMERROR; s=(unz64_s*)file; @@ -2074,12 +1938,11 @@ *(szComment+s->gi.size_comment)='\0'; return (int)uReadThis; } /* Additions by RX '2004 */ -extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) -{ +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) { unz64_s* s; if (file==NULL) return 0; //UNZ_PARAMERROR; s=(unz64_s*)file; @@ -2089,22 +1952,20 @@ if (s->num_file==s->gi.number_entry) return 0; return s->pos_in_central_dir; } -extern uLong ZEXPORT unzGetOffset (unzFile file) -{ +extern uLong ZEXPORT unzGetOffset(unzFile file) { ZPOS64_T offset64; if (file==NULL) return 0; //UNZ_PARAMERROR; offset64 = unzGetOffset64(file); return (uLong)offset64; } -extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) -{ +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) { unz64_s* s; int err; if (file==NULL) return UNZ_PARAMERROR; @@ -2117,9 +1978,8 @@ NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) -{ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) { return unzSetOffset64(file,pos); } Index: compat/zlib/contrib/minizip/unzip.h ================================================================== --- compat/zlib/contrib/minizip/unzip.h +++ compat/zlib/contrib/minizip/unzip.h @@ -81,16 +81,16 @@ #define UNZ_CRCERROR (-105) /* tm_unz contain date/time info */ typedef struct tm_unz_s { - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ + int tm_sec; /* seconds after the minute - [0,59] */ + int tm_min; /* minutes after the hour - [0,59] */ + int tm_hour; /* hours since midnight - [0,23] */ + int tm_mday; /* day of the month - [1,31] */ + int tm_mon; /* months since January - [0,11] */ + int tm_year; /* years - [1980..2044] */ } tm_unz; /* unz_global_info structure contain global data about the ZIPfile These data comes from the end of central dir */ typedef struct unz_global_info64_s @@ -148,25 +148,25 @@ uLong external_fa; /* external file attributes 4 bytes */ tm_unz tmu_date; } unz_file_info; -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); +extern int ZEXPORT unzStringFileNameCompare(const char* fileName1, + const char* fileName2, + int iCaseSensitivity); /* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + Compare two filenames (fileName1,fileName2). + If iCaseSensitivity = 1, comparison is case sensitive (like strcmp) + If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + If iCaseSensitivity = 0, case sensitivity is default of your operating system (like 1 on Unix, 2 on Windows) */ -extern unzFile ZEXPORT unzOpen OF((const char *path)); -extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +extern unzFile ZEXPORT unzOpen(const char *path); +extern unzFile ZEXPORT unzOpen64(const void *path); /* Open a Zip file. path contain the full pathname (by example, on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip". If the zipfile cannot be opened (file don't exist or in not valid), the @@ -179,45 +179,45 @@ is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* does not describe the reality */ -extern unzFile ZEXPORT unzOpen2 OF((const char *path, - zlib_filefunc_def* pzlib_filefunc_def)); +extern unzFile ZEXPORT unzOpen2(const char *path, + zlib_filefunc_def* pzlib_filefunc_def); /* Open a Zip file, like unzOpen, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ -extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, - zlib_filefunc64_def* pzlib_filefunc_def)); +extern unzFile ZEXPORT unzOpen2_64(const void *path, + zlib_filefunc64_def* pzlib_filefunc_def); /* Open a Zip file, like unz64Open, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ -extern int ZEXPORT unzClose OF((unzFile file)); +extern int ZEXPORT unzClose(unzFile file); /* Close a ZipFile opened with unzOpen. If there is files inside the .Zip opened with unzOpenCurrentFile (see later), these files MUST be closed with unzCloseCurrentFile before call unzClose. return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); +extern int ZEXPORT unzGetGlobalInfo(unzFile file, + unz_global_info *pglobal_info); -extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, - unz_global_info64 *pglobal_info)); +extern int ZEXPORT unzGetGlobalInfo64(unzFile file, + unz_global_info64 *pglobal_info); /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); +extern int ZEXPORT unzGetGlobalComment(unzFile file, + char *szComment, + uLong uSizeBuf); /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ @@ -224,26 +224,26 @@ /***************************************************************************/ /* Unzip package allow you browse the directory of the zipfile */ -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +extern int ZEXPORT unzGoToFirstFile(unzFile file); /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +extern int ZEXPORT unzGoToNextFile(unzFile file); /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); +extern int ZEXPORT unzLocateFile(unzFile file, + const char *szFileName, + int iCaseSensitivity); /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzStringFileNameCompare return value : @@ -283,30 +283,30 @@ 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)); +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 somes info about + if pfile_info!=NULL, the *pfile_info structure will contain some info about the current file if szFileName!=NULL, the filemane string will be copied in szFileName (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). @@ -316,52 +316,52 @@ */ /** Addition for GDAL : START */ -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file); /** Addition for GDAL : END */ /***************************************************************************/ /* for reading the content of the current zipfile, you can open it, read data from it, and close it (you can close it before reading all the file) */ -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +extern int ZEXPORT unzOpenCurrentFile(unzFile file); /* Open for reading data the current file in the zipfile. If there is no error, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, - const char* password)); +extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, + const char* password); /* Open for reading data the current file in the zipfile. password is a crypting password If there is no error, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, - int* method, - int* level, - int raw)); +extern int ZEXPORT unzOpenCurrentFile2(unzFile file, + int* method, + int* level, + int raw); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 *method will receive method of compression, *level will receive level of compression note : you can set level parameter as NULL (if you did not want known level, but you CANNOT set method parameter as NULL */ -extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, - int* method, - int* level, - int raw, - const char* password)); +extern int ZEXPORT unzOpenCurrentFile3(unzFile file, + int* method, + int* level, + int raw, + const char* password); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 *method will receive method of compression, *level will receive level of compression @@ -368,45 +368,45 @@ note : you can set level parameter as NULL (if you did not want known level, but you CANNOT set method parameter as NULL */ -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +extern int ZEXPORT unzCloseCurrentFile(unzFile file); /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); +extern int ZEXPORT unzReadCurrentFile(unzFile file, + voidp buf, + unsigned len); /* Read bytes from the current file (opened by unzOpenCurrentFile) buf contain buffer where data must be copied len the size of buf. - return the number of byte copied if somes bytes are copied + return the number of byte copied if some bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ -extern z_off_t ZEXPORT unztell OF((unzFile file)); +extern z_off_t ZEXPORT unztell(unzFile file); -extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +extern ZPOS64_T ZEXPORT unztell64(unzFile file); /* Give the current position in uncompressed data */ -extern int ZEXPORT unzeof OF((unzFile file)); +extern int ZEXPORT unzeof(unzFile file); /* return 1 if the end of file was reached, 0 elsewhere */ -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); +extern int ZEXPORT unzGetLocalExtrafield(unzFile file, + voidp buf, + unsigned len); /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is more info in the local-header version than in the central-header) Index: compat/zlib/contrib/minizip/zip.c ================================================================== --- compat/zlib/contrib/minizip/zip.c +++ compat/zlib/contrib/minizip/zip.c @@ -12,11 +12,11 @@ Changes Oct-2009 - Mathias Svensson - Remove old C style function prototypes Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data - It is used when recreting zip archive with RAW when deleting items from a zip. + It is used when recreating zip archive with RAW when deleting items from a zip. ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer */ @@ -23,18 +23,17 @@ #include #include #include +#include #include #include "zlib.h" #include "zip.h" #ifdef STDC # include -# include -# include #endif #ifdef NO_ERRNO_H extern int errno; #else # include @@ -45,11 +44,11 @@ # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef VERSIONMADEBY -# define VERSIONMADEBY (0x0) /* platform depedent */ +# define VERSIONMADEBY (0x0) /* platform dependent */ #endif #ifndef Z_BUFSIZE #define Z_BUFSIZE (64*1024) //(16384) #endif @@ -59,13 +58,10 @@ #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) */ @@ -136,41 +132,41 @@ int stream_initialised; /* 1 is stream is initialised */ uInt pos_in_buffered_data; /* last written byte in buffered_data */ ZPOS64_T pos_local_header; /* offset of the local header of the file - currenty writing */ + currently writing */ char* central_header; /* central header data for the current file */ uLong size_centralExtra; uLong size_centralheader; /* size of the central header for cur file */ uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ uLong flag; /* flag of the file currently writing */ - int method; /* compression method of file currenty wr.*/ + int method; /* compression method of file currently wr.*/ int raw; /* 1 for directly writing raw data */ Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ uLong dosDate; uLong crc32; int encrypt; - int zip64; /* Add ZIP64 extened information in the extra field */ + int zip64; /* Add ZIP64 extended information in the extra field */ ZPOS64_T pos_zip64extrainfo; ZPOS64_T totalCompressedData; ZPOS64_T totalUncompressedData; #ifndef NOCRYPT unsigned long keys[3]; /* keys defining the pseudo-random sequence */ const z_crc_t* pcrc_32_tab; - int crypt_header_size; + unsigned crypt_header_size; #endif } curfile64_info; typedef struct { zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ linkedlist_data central_dir;/* datablock with central dir in construction*/ int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ - curfile64_info ci; /* info on the file curretly writing */ + curfile64_info ci; /* info on the file currently writing */ ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ ZPOS64_T add_position_when_writing_offset; ZPOS64_T number_entry; @@ -184,12 +180,11 @@ #ifndef NOCRYPT #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED #include "crypt.h" #endif -local linkedlist_datablock_internal* allocate_new_datablock() -{ +local linkedlist_datablock_internal* allocate_new_datablock(void) { linkedlist_datablock_internal* ldi; ldi = (linkedlist_datablock_internal*) ALLOC(sizeof(linkedlist_datablock_internal)); if (ldi!=NULL) { @@ -198,34 +193,30 @@ ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; } return ldi; } -local void free_datablock(linkedlist_datablock_internal* ldi) -{ +local void free_datablock(linkedlist_datablock_internal* ldi) { while (ldi!=NULL) { linkedlist_datablock_internal* ldinext = ldi->next_datablock; - TRYFREE(ldi); + free(ldi); ldi = ldinext; } } -local void init_linkedlist(linkedlist_data* ll) -{ +local void init_linkedlist(linkedlist_data* ll) { ll->first_block = ll->last_block = NULL; } -local void free_linkedlist(linkedlist_data* ll) -{ +local void free_linkedlist(linkedlist_data* ll) { free_datablock(ll->first_block); ll->first_block = ll->last_block = NULL; } -local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) -{ +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) { linkedlist_datablock_internal* ldi; const unsigned char* from_copy; if (ll==NULL) return ZIP_INTERNALERROR; @@ -236,11 +227,11 @@ if (ll->first_block == NULL) return ZIP_INTERNALERROR; } ldi = ll->last_block; - from_copy = (unsigned char*)buf; + from_copy = (const unsigned char*)buf; while (len>0) { uInt copy_this; uInt i; @@ -281,13 +272,11 @@ /* =========================================================================== Inputs a long in LSB order to the given file nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) */ -local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); -local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) -{ +local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) { unsigned char buf[8]; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char)(x & 0xff); @@ -299,19 +288,17 @@ { buf[n] = 0xff; } } - if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte)!=(uLong)nbByte) return ZIP_ERRNO; else return ZIP_OK; } -local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); -local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) -{ +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) { unsigned char* buf=(unsigned char*)dest; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char)(x & 0xff); x >>= 8; @@ -327,29 +314,25 @@ } /****************************************************************************/ -local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) -{ +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) { uLong year = (uLong)ptm->tm_year; if (year>=1980) year-=1980; else if (year>=80) year-=80; return - (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | - ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); + (uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon+1)) + (512 * year)) << 16) | + (((uLong)ptm->tm_sec/2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); } /****************************************************************************/ -local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); - -local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) -{ +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) { unsigned char c; int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); if (err==1) { *pi = (int)c; @@ -366,14 +349,11 @@ /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ -local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ +local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); @@ -388,14 +368,11 @@ else *pX = 0; return err; } -local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ +local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); @@ -418,15 +395,12 @@ else *pX = 0; return err; } -local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); - -local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) -{ +local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) { ZPOS64_T x; int i = 0; int err; err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); @@ -473,14 +447,11 @@ #endif /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ ZPOS64_T uPosFound=0; @@ -520,29 +491,26 @@ for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { - uPosFound = uReadPos+i; + uPosFound = uReadPos+(unsigned)i; break; } - if (uPosFound!=0) - break; + if (uPosFound!=0) + break; } - TRYFREE(buf); + free(buf); return uPosFound; } /* Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ ZPOS64_T uPosFound=0; @@ -584,20 +552,20 @@ for (i=(int)uReadSize-3; (i--)>0;) { // Signature "0x07064b50" Zip64 end of central directory locater if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { - uPosFound = uReadPos+i; + uPosFound = uReadPos+(unsigned)i; break; } } if (uPosFound!=0) break; } - TRYFREE(buf); + free(buf); if (uPosFound == 0) return 0; /* Zip64 end of central directory locator */ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) @@ -635,24 +603,23 @@ return 0; return relativeOffset; } -int LoadCentralDirectoryRecord(zip64_internal* pziinit) -{ +local int LoadCentralDirectoryRecord(zip64_internal* pziinit) { int err=ZIP_OK; ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ ZPOS64_T size_central_dir; /* size of the central directory */ ZPOS64_T offset_central_dir; /* offset of start of central directory */ ZPOS64_T central_pos; uLong uL; uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ + spanning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ + 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; @@ -828,11 +795,11 @@ if (err==ZIP_OK) err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); size_central_dir_to_read-=read_this; } - TRYFREE(buf_read); + free(buf_read); } pziinit->begin_pos = byte_before_the_zipfile; pziinit->number_entry = number_entry_CD; if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) @@ -844,12 +811,11 @@ #endif /* !NO_ADDFILEINEXISTINGZIP*/ /************************************************************/ -extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) -{ +extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) { zip64_internal ziinit; zip64_internal* zi; int err=ZIP_OK; ziinit.z_filefunc.zseek32_file = NULL; @@ -903,24 +869,23 @@ # endif /* !NO_ADDFILEINEXISTINGZIP*/ if (err != ZIP_OK) { # ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(ziinit.globalcomment); + free(ziinit.globalcomment); # endif /* !NO_ADDFILEINEXISTINGZIP*/ - TRYFREE(zi); + free(zi); return NULL; } else { *zi = ziinit; return (zipFile)zi; } } -extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) -{ +extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) { if (pzlib_filefunc32_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); @@ -927,12 +892,11 @@ } else return zipOpen3(pathname, append, globalcomment, NULL); } -extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) -{ +extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) { if (pzlib_filefunc_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; zlib_filefunc64_32_def_fill.ztell32_file = NULL; @@ -943,22 +907,19 @@ return zipOpen3(pathname, append, globalcomment, NULL); } -extern zipFile ZEXPORT zipOpen (const char* pathname, int append) -{ +extern zipFile ZEXPORT zipOpen(const char* pathname, int append) { return zipOpen3((const void*)pathname,append,NULL,NULL); } -extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) -{ +extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) { return zipOpen3(pathname,append,NULL,NULL); } -int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) -{ +local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) { /* write the local header */ int err; uInt size_filename = (uInt)strlen(filename); uInt size_extrafield = size_extrafield_local; @@ -1032,12 +993,12 @@ ZPOS64_T UncompressedSize = 0; // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); } @@ -1050,18 +1011,17 @@ before calling this function it can be done with zipRemoveExtraInfoBlock It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize unnecessary allocations. */ -extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase, int zip64) -{ +extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase, int zip64) { zip64_internal* zi; uInt size_filename; uInt size_comment; uInt i; int err = ZIP_OK; @@ -1260,110 +1220,102 @@ 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 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); + 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); + 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) -{ + 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 @@ -1397,12 +1349,11 @@ zi->ci.pos_in_buffered_data = 0; return err; } -extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) -{ +extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) { zip64_internal* zi; int err=ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; @@ -1448,11 +1399,11 @@ err = ZIP_OK; } else #endif { - zi->ci.stream.next_in = (Bytef*)buf; + zi->ci.stream.next_in = (Bytef*)(uintptr_t)buf; zi->ci.stream.avail_in = len; while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) { if (zi->ci.stream.avail_out == 0) @@ -1469,15 +1420,10 @@ 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 { @@ -1504,21 +1450,19 @@ } return err; } -extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) -{ +extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) { return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); } -extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) -{ +extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) { zip64_internal* zi; ZPOS64_T compressed_size; uLong invalidValue = 0xffffffff; - short datasize = 0; + unsigned datasize = 0; int err=ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; zi = (zip64_internal*)file; @@ -1745,17 +1689,15 @@ zi->in_opened_file_inzip = 0; return err; } -extern int ZEXPORT zipCloseFileInZip (zipFile file) -{ +extern int ZEXPORT zipCloseFileInZip(zipFile file) { return zipCloseFileInZipRaw (file,0,0); } -int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) -{ +local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) { int err = ZIP_OK; ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); @@ -1772,12 +1714,11 @@ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); return err; } -int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ +local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; uLong Zip64DataSize = 44; err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); @@ -1811,12 +1752,12 @@ ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); } return err; } -int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ + +local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; /*signature*/ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); @@ -1859,12 +1800,11 @@ } return err; } -int Write_GlobalComment(zip64_internal* zi, const char* global_comment) -{ +local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) { int err = ZIP_OK; uInt size_global_comment = 0; if(global_comment != NULL) size_global_comment = (uInt)strlen(global_comment); @@ -1877,12 +1817,11 @@ err = ZIP_ERRNO; } return err; } -extern int ZEXPORT zipClose (zipFile file, const char* global_comment) -{ +extern int ZEXPORT zipClose(zipFile file, const char* global_comment) { zip64_internal* zi; int err = 0; uLong size_centraldir = 0; ZPOS64_T centraldir_pos_inzip; ZPOS64_T pos; @@ -1939,32 +1878,31 @@ if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) if (err == ZIP_OK) err = ZIP_ERRNO; #ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(zi->globalcomment); + free(zi->globalcomment); #endif - TRYFREE(zi); + free(zi); return err; } -extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) -{ +extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) { char* p = pData; int size = 0; char* pNewHeader; char* pTmp; short header; short dataSize; int retVal = ZIP_OK; - if(pData == NULL || *dataLen < 4) + if(pData == NULL || dataLen == NULL || *dataLen < 4) return ZIP_PARAMERROR; - pNewHeader = (char*)ALLOC(*dataLen); + pNewHeader = (char*)ALLOC((unsigned)*dataLen); pTmp = pNewHeader; while(p < (pData + *dataLen)) { header = *(short*)p; @@ -1999,9 +1937,9 @@ retVal = ZIP_OK; } else retVal = ZIP_ERRNO; - TRYFREE(pNewHeader); + free(pNewHeader); return retVal; } Index: compat/zlib/contrib/minizip/zip.h ================================================================== --- compat/zlib/contrib/minizip/zip.h +++ compat/zlib/contrib/minizip/zip.h @@ -86,16 +86,16 @@ /* default memLevel */ /* tm_zip contain date/time info */ typedef struct tm_zip_s { - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ + int tm_sec; /* seconds after the minute - [0,59] */ + int tm_min; /* minutes after the hour - [0,59] */ + int tm_hour; /* hours since midnight - [0,23] */ + int tm_mday; /* day of the month - [1,31] */ + int tm_mon; /* months since January - [0,11] */ + int tm_year; /* years - [1980..2044] */ } tm_zip; typedef struct { tm_zip tmz_date; /* date in understandable format */ @@ -111,12 +111,12 @@ #define APPEND_STATUS_CREATE (0) #define APPEND_STATUS_CREATEAFTER (1) #define APPEND_STATUS_ADDINZIP (2) -extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); -extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); +extern zipFile ZEXPORT zipOpen(const char *pathname, int append); +extern zipFile ZEXPORT zipOpen64(const void *pathname, int append); /* Create a zipfile. pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip". if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip @@ -129,45 +129,50 @@ 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)); + 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 @@ -182,164 +187,161 @@ 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)); +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 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 - )); +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 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 - )); +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 OF((zipFile file, - const void* buf, - unsigned len)); +extern int ZEXPORT zipWriteInFileInZip(zipFile file, + const void* buf, + unsigned len); /* Write data in the zipfile */ -extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +extern int ZEXPORT zipCloseFileInZip(zipFile file); /* Close the current file in the zipfile */ -extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, - uLong uncompressed_size, - uLong crc32)); +extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, + uLong uncompressed_size, + uLong crc32); -extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, - ZPOS64_T uncompressed_size, - uLong crc32)); +extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, + ZPOS64_T uncompressed_size, + uLong crc32); /* Close the current file in the zipfile, for file opened with parameter raw=1 in zipOpenNewFileInZip2 uncompressed_size and crc32 are value for the uncompressed size */ -extern int ZEXPORT zipClose OF((zipFile file, - const char* global_comment)); +extern int ZEXPORT zipClose(zipFile file, + const char* global_comment); /* Close the zipfile */ -extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); +extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader); /* zipRemoveExtraInfoBlock - Added by Mathias Svensson Remove extra information block from a extra information data for the local file header or central directory header Index: compat/zlib/contrib/pascal/zlibpas.pas ================================================================== --- compat/zlib/contrib/pascal/zlibpas.pas +++ compat/zlib/contrib/pascal/zlibpas.pas @@ -8,11 +8,11 @@ unit zlibpas; interface const - ZLIB_VERSION = '1.2.11'; + ZLIB_VERSION = '1.3.0'; ZLIB_VERNUM = $12a0; type alloc_func = function(opaque: Pointer; items, size: Integer): Pointer; cdecl; Index: compat/zlib/contrib/puff/README ================================================================== --- compat/zlib/contrib/puff/README +++ compat/zlib/contrib/puff/README @@ -36,11 +36,11 @@ Then you can call puff() to decompress a deflate stream that is in memory in its entirety at source, to a sufficiently sized block of memory for the decompressed data at dest. puff() is the only external symbol in puff.c The only C library functions that puff.c needs are setjmp() and longjmp(), which -are used to simplify error checking in the code to improve readabilty. puff.c +are used to simplify error checking in the code to improve readability. puff.c does no memory allocation, and uses less than 2K bytes off of the stack. If destlen is not enough space for the uncompressed data, then inflate will return an error without writing more than destlen bytes. Note that this means that in order to decompress the deflate data successfully, you need to know Index: compat/zlib/contrib/puff/puff.c ================================================================== --- compat/zlib/contrib/puff/puff.c +++ compat/zlib/contrib/puff/puff.c @@ -41,11 +41,11 @@ * maintain easy readability * - Use short data type for large arrays * - Use pointers instead of long to specify source and * destination sizes to avoid arbitrary 4 GB limits * 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!), - * but leave simple version for readabilty + * but leave simple version for readability * - Make sure invalid distances detected if pointers * are 16 bits * - Fix fixed codes table error * - Provide a scanning mode for determining size of * uncompressed data @@ -622,11 +622,11 @@ * * - The list of up to 286 length/literal lengths and up to 30 distance lengths * are themselves compressed using Huffman codes and run-length encoding. In * the list of code lengths, a 0 symbol means no code, a 1..15 symbol means * that length, and the symbols 16, 17, and 18 are run-length instructions. - * Each of 16, 17, and 18 are follwed by extra bits to define the length of + * Each of 16, 17, and 18 are followed by extra bits to define the length of * the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10 * zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols * are common, hence the special coding for zero lengths. * * - The symbols for 0..18 are Huffman coded, and so that code must be Index: compat/zlib/contrib/puff/pufftest.c ================================================================== --- compat/zlib/contrib/puff/pufftest.c +++ compat/zlib/contrib/puff/pufftest.c @@ -141,11 +141,11 @@ fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen); if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n", len - sourcelen); } - /* if requested, inflate again and write decompressd data to stdout */ + /* if requested, inflate again and write decompressed data to stdout */ if (put && ret == 0) { if (fail) destlen >>= 1; dest = malloc(destlen); if (dest == NULL) { Index: compat/zlib/contrib/testzlib/testzlib.c ================================================================== --- compat/zlib/contrib/testzlib/testzlib.c +++ compat/zlib/contrib/testzlib/testzlib.c @@ -1,275 +1,275 @@ -#include -#include -#include - -#include "zlib.h" - - -void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B) -{ - R->HighPart = A.HighPart - B.HighPart; - if (A.LowPart >= B.LowPart) - R->LowPart = A.LowPart - B.LowPart; - else - { - R->LowPart = A.LowPart - B.LowPart; - R->HighPart --; - } -} - -#ifdef _M_X64 -// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc -unsigned __int64 __rdtsc(void); -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ - // printf("rdtsc = %I64x\n",__rdtsc()); - pbeginTime64->QuadPart=__rdtsc(); -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER LIres; - unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart)); - LIres.QuadPart=res; - // printf("rdtsc = %I64x\n",__rdtsc()); - return LIres; -} -#else -#ifdef _M_IX86 -void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) -{ - DWORD dwEdx,dwEax; - _asm - { - rdtsc - mov dwEax,eax - mov dwEdx,edx - } - pbeginTime64->LowPart=dwEax; - pbeginTime64->HighPart=dwEdx; -} - -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ - myGetRDTSC32(pbeginTime64); -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER LIres,endTime64; - myGetRDTSC32(&endTime64); - - LIres.LowPart=LIres.HighPart=0; - MyDoMinus64(&LIres,endTime64,beginTime64); - return LIres; -} -#else -void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) -{ -} - -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER lr; - lr.QuadPart=0; - return lr; -} -#endif -#endif - -void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf) -{ - if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64))) - { - pbeginTime64->LowPart = GetTickCount(); - pbeginTime64->HighPart = 0; - } -} - -DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER endTime64,ticksPerSecond,ticks; - DWORDLONG ticksShifted,tickSecShifted; - DWORD dwLog=16+0; - DWORD dwRet; - if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) - dwRet = (GetTickCount() - beginTime64.LowPart)*1; - else - { - MyDoMinus64(&ticks,endTime64,beginTime64); - QueryPerformanceFrequency(&ticksPerSecond); - - - { - ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); - tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); - - } - - dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); - dwRet *=1; - } - return dwRet; -} - -int ReadFileMemory(const char* filename,long* plFileSize,unsigned char** pFilePtr) -{ - FILE* stream; - unsigned char* ptr; - int retVal=1; - stream=fopen(filename, "rb"); - if (stream==NULL) - return 0; - - fseek(stream,0,SEEK_END); - - *plFileSize=ftell(stream); - fseek(stream,0,SEEK_SET); - ptr=malloc((*plFileSize)+1); - if (ptr==NULL) - retVal=0; - else - { - if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) - retVal=0; - } - fclose(stream); - *pFilePtr=ptr; - return retVal; -} - -int main(int argc, char *argv[]) -{ - int BlockSizeCompress=0x8000; - int BlockSizeUncompress=0x8000; - int cprLevel=Z_DEFAULT_COMPRESSION ; - long lFileSize; - unsigned char* FilePtr; - long lBufferSizeCpr; - long lBufferSizeUncpr; - long lCompressedSize=0; - unsigned char* CprPtr; - unsigned char* UncprPtr; - long lSizeCpr,lSizeUncpr; - DWORD dwGetTick,dwMsecQP; - LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc; - - if (argc<=1) - { - printf("run TestZlib [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); - return 0; - } - - 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]); - - if (argc>=5) - cprLevel=(int)atol(argv[4]); - - lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; - lBufferSizeUncpr = lBufferSizeCpr; - - CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); - - BeginCountPerfCounter(&li_qp,TRUE); - dwGetTick=GetTickCount(); - BeginCountRdtsc(&li_rdtsc); - { - z_stream zcpr; - int ret=Z_OK; - long lOrigToDo = lFileSize; - long lOrigDone = 0; - int step=0; - memset(&zcpr,0,sizeof(z_stream)); - deflateInit(&zcpr,cprLevel); - - zcpr.next_in = FilePtr; - zcpr.next_out = CprPtr; - - - do - { - long all_read_before = zcpr.total_in; - zcpr.avail_in = min(lOrigToDo,BlockSizeCompress); - zcpr.avail_out = BlockSizeCompress; - ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH); - lOrigDone += (zcpr.total_in-all_read_before); - lOrigToDo -= (zcpr.total_in-all_read_before); - step++; - } while (ret==Z_OK); - - lSizeCpr=zcpr.total_out; - deflateEnd(&zcpr); - dwGetTick=GetTickCount()-dwGetTick; - dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); - dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); - printf("total compress size = %u, in %u step\n",lSizeCpr,step); - printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); - printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); - printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); - } - - CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr); - UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); - - BeginCountPerfCounter(&li_qp,TRUE); - dwGetTick=GetTickCount(); - BeginCountRdtsc(&li_rdtsc); - { - z_stream zcpr; - int ret=Z_OK; - long lOrigToDo = lSizeCpr; - long lOrigDone = 0; - int step=0; - memset(&zcpr,0,sizeof(z_stream)); - inflateInit(&zcpr); - - zcpr.next_in = CprPtr; - zcpr.next_out = UncprPtr; - - - do - { - long all_read_before = zcpr.total_in; - zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); - zcpr.avail_out = BlockSizeUncompress; - ret=inflate(&zcpr,Z_SYNC_FLUSH); - lOrigDone += (zcpr.total_in-all_read_before); - lOrigToDo -= (zcpr.total_in-all_read_before); - step++; - } while (ret==Z_OK); - - lSizeUncpr=zcpr.total_out; - inflateEnd(&zcpr); - dwGetTick=GetTickCount()-dwGetTick; - dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); - dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); - printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); - printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); - printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); - printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); - } - - if (lSizeUncpr==lFileSize) - { - if (memcmp(FilePtr,UncprPtr,lFileSize)==0) - printf("compare ok\n"); - - } - - return 0; -} +#include +#include +#include + +#include "zlib.h" + + +void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B) +{ + R->HighPart = A.HighPart - B.HighPart; + if (A.LowPart >= B.LowPart) + R->LowPart = A.LowPart - B.LowPart; + else + { + R->LowPart = A.LowPart - B.LowPart; + R->HighPart --; + } +} + +#ifdef _M_X64 +// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc +unsigned __int64 __rdtsc(void); +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ + // printf("rdtsc = %I64x\n",__rdtsc()); + pbeginTime64->QuadPart=__rdtsc(); +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER LIres; + unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart)); + LIres.QuadPart=res; + // printf("rdtsc = %I64x\n",__rdtsc()); + return LIres; +} +#else +#ifdef _M_IX86 +void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) +{ + DWORD dwEdx,dwEax; + _asm + { + rdtsc + mov dwEax,eax + mov dwEdx,edx + } + pbeginTime64->LowPart=dwEax; + pbeginTime64->HighPart=dwEdx; +} + +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ + myGetRDTSC32(pbeginTime64); +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER LIres,endTime64; + myGetRDTSC32(&endTime64); + + LIres.LowPart=LIres.HighPart=0; + MyDoMinus64(&LIres,endTime64,beginTime64); + return LIres; +} +#else +void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) +{ +} + +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER lr; + lr.QuadPart=0; + return lr; +} +#endif +#endif + +void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf) +{ + if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64))) + { + pbeginTime64->LowPart = GetTickCount(); + pbeginTime64->HighPart = 0; + } +} + +DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER endTime64,ticksPerSecond,ticks; + DWORDLONG ticksShifted,tickSecShifted; + DWORD dwLog=16+0; + DWORD dwRet; + if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) + dwRet = (GetTickCount() - beginTime64.LowPart)*1; + else + { + MyDoMinus64(&ticks,endTime64,beginTime64); + QueryPerformanceFrequency(&ticksPerSecond); + + + { + ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); + tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); + + } + + dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); + dwRet *=1; + } + return dwRet; +} + +int ReadFileMemory(const char* filename,long* plFileSize,unsigned char** pFilePtr) +{ + FILE* stream; + unsigned char* ptr; + int retVal=1; + stream=fopen(filename, "rb"); + if (stream==NULL) + return 0; + + fseek(stream,0,SEEK_END); + + *plFileSize=ftell(stream); + fseek(stream,0,SEEK_SET); + ptr=malloc((*plFileSize)+1); + if (ptr==NULL) + retVal=0; + else + { + if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) + retVal=0; + } + fclose(stream); + *pFilePtr=ptr; + return retVal; +} + +int main(int argc, char *argv[]) +{ + int BlockSizeCompress=0x8000; + int BlockSizeUncompress=0x8000; + int cprLevel=Z_DEFAULT_COMPRESSION ; + long lFileSize; + unsigned char* FilePtr; + long lBufferSizeCpr; + long lBufferSizeUncpr; + long lCompressedSize=0; + unsigned char* CprPtr; + unsigned char* UncprPtr; + long lSizeCpr,lSizeUncpr; + DWORD dwGetTick,dwMsecQP; + LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc; + + if (argc<=1) + { + printf("run TestZlib [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); + return 0; + } + + 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]); + + if (argc>=5) + cprLevel=(int)atol(argv[4]); + + lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; + lBufferSizeUncpr = lBufferSizeCpr; + + CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); + + BeginCountPerfCounter(&li_qp,TRUE); + dwGetTick=GetTickCount(); + BeginCountRdtsc(&li_rdtsc); + { + z_stream zcpr; + int ret=Z_OK; + long lOrigToDo = lFileSize; + long lOrigDone = 0; + int step=0; + memset(&zcpr,0,sizeof(z_stream)); + deflateInit(&zcpr,cprLevel); + + zcpr.next_in = FilePtr; + zcpr.next_out = CprPtr; + + + do + { + long all_read_before = zcpr.total_in; + zcpr.avail_in = min(lOrigToDo,BlockSizeCompress); + zcpr.avail_out = BlockSizeCompress; + ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH); + lOrigDone += (zcpr.total_in-all_read_before); + lOrigToDo -= (zcpr.total_in-all_read_before); + step++; + } while (ret==Z_OK); + + lSizeCpr=zcpr.total_out; + deflateEnd(&zcpr); + dwGetTick=GetTickCount()-dwGetTick; + dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); + dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); + printf("total compress size = %u, in %u step\n",lSizeCpr,step); + printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); + printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); + printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); + } + + CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr); + UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); + + BeginCountPerfCounter(&li_qp,TRUE); + dwGetTick=GetTickCount(); + BeginCountRdtsc(&li_rdtsc); + { + z_stream zcpr; + int ret=Z_OK; + long lOrigToDo = lSizeCpr; + long lOrigDone = 0; + int step=0; + memset(&zcpr,0,sizeof(z_stream)); + inflateInit(&zcpr); + + zcpr.next_in = CprPtr; + zcpr.next_out = UncprPtr; + + + do + { + long all_read_before = zcpr.total_in; + zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); + zcpr.avail_out = BlockSizeUncompress; + ret=inflate(&zcpr,Z_SYNC_FLUSH); + lOrigDone += (zcpr.total_in-all_read_before); + lOrigToDo -= (zcpr.total_in-all_read_before); + step++; + } while (ret==Z_OK); + + lSizeUncpr=zcpr.total_out; + inflateEnd(&zcpr); + dwGetTick=GetTickCount()-dwGetTick; + dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); + dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); + printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); + printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); + printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); + printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); + } + + if (lSizeUncpr==lFileSize) + { + if (memcmp(FilePtr,UncprPtr,lFileSize)==0) + printf("compare ok\n"); + + } + + return 0; +} Index: compat/zlib/contrib/untgz/untgz.c ================================================================== --- compat/zlib/contrib/untgz/untgz.c +++ compat/zlib/contrib/untgz/untgz.c @@ -2,10 +2,26 @@ * untgz.c -- Display contents and extract files from a gzip'd TAR file * * written by Pedro A. Aranda Gutierrez * adaptation to Unix by Jean-loup Gailly * various fixes by Cosmin Truta + * + * 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 #include #include @@ -12,19 +28,14 @@ #include #include #include "zlib.h" -#ifdef unix -# include -#else +#ifdef _WIN32 # include # include -#endif - -#ifdef WIN32 -#include +# include # ifndef F_OK # define F_OK 0 # endif # define mkdir(dirname,mode) _mkdir(dirname) # ifdef _MSC_VER @@ -31,10 +42,12 @@ # define access(path,mode) _access(path,mode) # define chmod(path,mode) _chmod(path,mode) # define strdup(str) _strdup(str) # endif #else +# include +# include # include #endif /* values used in typeflag field */ @@ -100,31 +113,17 @@ 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; + +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 */ @@ -203,11 +202,11 @@ /* set file time */ int setfiletime (char *fname,time_t ftime) { -#ifdef WIN32 +#ifdef _WIN32 static int isWinNT = -1; SYSTEMTIME st; FILETIME locft, modft; struct tm *loctm; HANDLE hFile; @@ -588,16 +587,10 @@ " 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 */ @@ -606,11 +599,11 @@ int main(int argc,char **argv) { int action = TGZ_EXTRACT; int arg = 1; char *TGZfile; - gzFile *f; + gzFile f; prog = strrchr(argv[0],'\\'); if (prog == NULL) { prog = strrchr(argv[0],'/'); Index: compat/zlib/contrib/vstudio/readme.txt ================================================================== --- compat/zlib/contrib/vstudio/readme.txt +++ compat/zlib/contrib/vstudio/readme.txt @@ -1,6 +1,6 @@ -Building instructions for the DLL versions of Zlib 1.2.11 +Building instructions for the DLL versions of Zlib 1.3.0 ======================================================== This directory contains projects that build zlib and minizip using Microsoft Visual C++ 9.0/10.0. @@ -15,13 +15,10 @@ 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) -------------------------------------------------------------- Index: compat/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters ================================================================== --- compat/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters +++ compat/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters @@ -1,11 +1,11 @@ {048af943-022b-4db6-beeb-a54c34774ee2} - cpp;c;cxx;def;odl;idl;hpj;bat;asm + cpp;c;cxx;def;odl;idl;hpj;bat {c1d600d2-888f-4aea-b73e-8b0dd9befa0c} h;hpp;hxx;hm;inl;inc Index: compat/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters ================================================================== --- compat/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters +++ compat/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters @@ -1,11 +1,11 @@ {c0419b40-bf50-40da-b153-ff74215b79de} - cpp;c;cxx;def;odl;idl;hpj;bat;asm + cpp;c;cxx;def;odl;idl;hpj;bat {bb87b070-735b-478e-92ce-7383abb2f36c} h;hpp;hxx;hm;inl;inc Index: compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj +++ compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj @@ -179,11 +179,11 @@ Disabled ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreadedDebug false @@ -192,11 +192,11 @@ $(IntDir) Level3 EditAndContinue - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)testzlib.exe true $(OutDir)testzlib.pdb Console false @@ -239,11 +239,11 @@ MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreaded false true @@ -252,11 +252,11 @@ $(IntDir) Level3 ProgramDatabase - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)testzlib.exe true Console true true @@ -267,18 +267,18 @@ ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDebugDLL false $(IntDir) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) Itanium @@ -350,18 +350,18 @@ ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDLL false $(IntDir) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) Itanium @@ -396,18 +396,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters ================================================================== --- compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters +++ compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters @@ -1,11 +1,11 @@ {c1f6a2e3-5da5-4955-8653-310d3efe05a9} - cpp;c;cxx;def;odl;idl;hpj;bat;asm + cpp;c;cxx;def;odl;idl;hpj;bat {c2aaffdc-2c95-4d6f-8466-4bec5890af2c} h;hpp;hxx;hm;inl;inc @@ -28,13 +28,10 @@ Source Files Source Files - - Source Files - Source Files Source Files Index: compat/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters ================================================================== --- compat/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters +++ compat/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters @@ -1,11 +1,11 @@ {fa61a89f-93fc-4c89-b29e-36224b7592f4} - cpp;c;cxx;def;odl;idl;hpj;bat;asm + cpp;c;cxx;def;odl;idl;hpj;bat {d4b85da0-2ba2-4934-b57f-e2584e3848ee} h;hpp;hxx;hm;inl;inc Index: compat/zlib/contrib/vstudio/vc10/zlib.rc ================================================================== --- compat/zlib/contrib/vstudio/vc10/zlib.rc +++ compat/zlib/contrib/vstudio/vc10/zlib.rc @@ -1,11 +1,11 @@ #include #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0 // not used @@ -15,18 +15,18 @@ BLOCK "040904E4" //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END Index: compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj +++ compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj @@ -158,11 +158,11 @@ Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDebug false @@ -180,20 +180,16 @@ /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true - - cd ..\..\masmx86 -bld_ml32.bat - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded false @@ -208,23 +204,19 @@ 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibstat.lib true - - cd ..\..\masmx86 -bld_ml32.bat - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded @@ -250,11 +242,11 @@ X64 Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -272,22 +264,18 @@ /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true - - cd ..\..\masmx64 -bld_ml64.bat - Itanium Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -312,12 +300,12 @@ X64 OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -332,26 +320,22 @@ 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibstat.lib true - - cd ..\..\masmx64 -bld_ml64.bat - Itanium OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -377,11 +361,11 @@ X64 OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -407,11 +391,11 @@ Itanium OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -441,18 +425,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters ================================================================== --- compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters +++ compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters @@ -31,13 +31,10 @@ Source Files Source Files - - Source Files - Source Files Source Files Index: compat/zlib/contrib/vstudio/vc10/zlibvc.def ================================================================== --- compat/zlib/contrib/vstudio/vc10/zlibvc.def +++ compat/zlib/contrib/vstudio/vc10/zlibvc.def @@ -1,9 +1,9 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.2 +VERSION 1.3 EXPORTS adler32 @1 compress @2 crc32 @3 @@ -149,5 +149,10 @@ 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 Index: compat/zlib/contrib/vstudio/vc10/zlibvc.sln ================================================================== --- compat/zlib/contrib/vstudio/vc10/zlibvc.sln +++ compat/zlib/contrib/vstudio/vc10/zlibvc.sln Index: compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj +++ compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj @@ -195,12 +195,12 @@ Win32 $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) MultiThreadedDebug false $(IntDir)zlibvc.pch @@ -217,24 +217,20 @@ _DEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) true .\zlibvc.def true true Windows false - - cd ..\..\masmx86 -bld_ml32.bat - NDEBUG;%(PreprocessorDefinitions) true @@ -242,11 +238,11 @@ Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -286,12 +282,12 @@ Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreaded false @@ -310,24 +306,20 @@ NDEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) true false .\zlibvc.def true Windows false - - cd ..\..\masmx86 -bld_ml32.bat - _DEBUG;%(PreprocessorDefinitions) true @@ -335,12 +327,12 @@ X64 $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch @@ -356,22 +348,18 @@ _DEBUG;%(PreprocessorDefinitions) 0x040c - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) true .\zlibvc.def true true Windows MachineX64 - - cd ..\..\masmx64 -bld_ml64.bat - _DEBUG;%(PreprocessorDefinitions) true @@ -379,11 +367,11 @@ Itanium $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -422,11 +410,11 @@ X64 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -463,11 +451,11 @@ Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -508,12 +496,12 @@ X64 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -531,22 +519,18 @@ NDEBUG;%(PreprocessorDefinitions) 0x040c - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) true false .\zlibvc.def true Windows MachineX64 - - cd ..\..\masmx64 -bld_ml64.bat - NDEBUG;%(PreprocessorDefinitions) true @@ -554,11 +538,11 @@ Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -599,18 +583,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters ================================================================== --- compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters +++ compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters @@ -40,13 +40,10 @@ Source Files Source Files - - Source Files - Source Files Source Files Index: compat/zlib/contrib/vstudio/vc11/testzlib.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc11/testzlib.vcxproj +++ compat/zlib/contrib/vstudio/vc11/testzlib.vcxproj @@ -185,11 +185,11 @@ Disabled ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false @@ -198,11 +198,11 @@ $(IntDir) Level3 ProgramDatabase - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)testzlib.exe true $(OutDir)testzlib.pdb Console false @@ -245,11 +245,11 @@ MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreaded false true @@ -258,11 +258,11 @@ $(IntDir) Level3 ProgramDatabase - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)testzlib.exe true Console true true @@ -273,18 +273,18 @@ ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDebugDLL false $(IntDir) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) Itanium @@ -356,18 +356,18 @@ ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDLL false $(IntDir) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) Itanium @@ -402,18 +402,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc11/zlib.rc ================================================================== --- compat/zlib/contrib/vstudio/vc11/zlib.rc +++ compat/zlib/contrib/vstudio/vc11/zlib.rc @@ -1,11 +1,11 @@ #include #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0 // not used @@ -15,18 +15,18 @@ BLOCK "040904E4" //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END Index: compat/zlib/contrib/vstudio/vc11/zlibstat.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc11/zlibstat.vcxproj +++ compat/zlib/contrib/vstudio/vc11/zlibstat.vcxproj @@ -165,11 +165,11 @@ Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -191,12 +191,12 @@ OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded false @@ -211,19 +211,19 @@ 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibstat.lib true OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded @@ -249,11 +249,11 @@ X64 Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -278,11 +278,11 @@ Itanium Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -307,12 +307,12 @@ X64 OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -327,11 +327,11 @@ 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibstat.lib true @@ -338,11 +338,11 @@ Itanium OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -368,11 +368,11 @@ X64 OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -398,11 +398,11 @@ Itanium OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -432,18 +432,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc11/zlibvc.def ================================================================== --- compat/zlib/contrib/vstudio/vc11/zlibvc.def +++ compat/zlib/contrib/vstudio/vc11/zlibvc.def @@ -1,9 +1,9 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.2 +VERSION 1.3 EXPORTS adler32 @1 compress @2 crc32 @3 @@ -149,5 +149,10 @@ 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 Index: compat/zlib/contrib/vstudio/vc11/zlibvc.sln ================================================================== --- compat/zlib/contrib/vstudio/vc11/zlibvc.sln +++ compat/zlib/contrib/vstudio/vc11/zlibvc.sln Index: compat/zlib/contrib/vstudio/vc11/zlibvc.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc11/zlibvc.vcxproj +++ compat/zlib/contrib/vstudio/vc11/zlibvc.vcxproj @@ -202,12 +202,12 @@ Win32 $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch @@ -224,11 +224,11 @@ _DEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb @@ -238,14 +238,10 @@ false $(OutDir)zlibwapi.lib - - cd ..\..\masmx86 -bld_ml32.bat - NDEBUG;%(PreprocessorDefinitions) true @@ -253,11 +249,11 @@ Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -301,12 +297,12 @@ Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreaded false @@ -325,11 +321,11 @@ NDEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb @@ -339,14 +335,10 @@ false $(OutDir)zlibwapi.lib - - cd ..\..\masmx86 -bld_ml32.bat - _DEBUG;%(PreprocessorDefinitions) true @@ -354,12 +346,12 @@ X64 $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch @@ -375,11 +367,11 @@ _DEBUG;%(PreprocessorDefinitions) 0x040c - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb @@ -387,14 +379,10 @@ $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineX64 - - cd ..\..\contrib\masmx64 -bld_ml64.bat - _DEBUG;%(PreprocessorDefinitions) true @@ -402,11 +390,11 @@ Itanium $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -445,11 +433,11 @@ X64 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -490,11 +478,11 @@ Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -535,12 +523,12 @@ X64 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -558,11 +546,11 @@ NDEBUG;%(PreprocessorDefinitions) 0x040c - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb @@ -570,14 +558,10 @@ $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineX64 - - cd ..\..\masmx64 -bld_ml64.bat - NDEBUG;%(PreprocessorDefinitions) true @@ -585,11 +569,11 @@ Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -630,18 +614,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc12/testzlib.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc12/testzlib.vcxproj +++ compat/zlib/contrib/vstudio/vc12/testzlib.vcxproj @@ -188,11 +188,11 @@ Disabled ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false @@ -201,11 +201,11 @@ $(IntDir) Level3 ProgramDatabase - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)testzlib.exe true $(OutDir)testzlib.pdb Console false @@ -248,11 +248,11 @@ MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreaded false true @@ -261,11 +261,11 @@ $(IntDir) Level3 ProgramDatabase - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)testzlib.exe true Console true true @@ -277,18 +277,18 @@ ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDebugDLL false $(IntDir) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) Itanium @@ -360,18 +360,18 @@ ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDLL false $(IntDir) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) Itanium @@ -406,18 +406,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc12/zlib.rc ================================================================== --- compat/zlib/contrib/vstudio/vc12/zlib.rc +++ compat/zlib/contrib/vstudio/vc12/zlib.rc @@ -1,11 +1,11 @@ #include #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0 // not used @@ -15,18 +15,18 @@ BLOCK "040904E4" //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END Index: compat/zlib/contrib/vstudio/vc12/zlibstat.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc12/zlibstat.vcxproj +++ compat/zlib/contrib/vstudio/vc12/zlibstat.vcxproj @@ -168,11 +168,11 @@ Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -194,12 +194,12 @@ OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded false @@ -214,19 +214,19 @@ 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibstat.lib true OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded @@ -252,11 +252,11 @@ X64 Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -281,11 +281,11 @@ Itanium Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -310,12 +310,12 @@ X64 OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -330,11 +330,11 @@ 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibstat.lib true @@ -341,11 +341,11 @@ Itanium OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -371,11 +371,11 @@ X64 OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -401,11 +401,11 @@ Itanium OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -435,18 +435,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc12/zlibvc.def ================================================================== --- compat/zlib/contrib/vstudio/vc12/zlibvc.def +++ compat/zlib/contrib/vstudio/vc12/zlibvc.def @@ -1,9 +1,9 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.2 +VERSION 1.3 EXPORTS adler32 @1 compress @2 crc32 @3 @@ -149,5 +149,10 @@ 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 Index: compat/zlib/contrib/vstudio/vc12/zlibvc.sln ================================================================== --- compat/zlib/contrib/vstudio/vc12/zlibvc.sln +++ compat/zlib/contrib/vstudio/vc12/zlibvc.sln @@ -1,119 +1,119 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 -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|Itanium = Debug|Itanium - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Itanium = Release|Itanium - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium - ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 - ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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 -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +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|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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 +EndGlobal Index: compat/zlib/contrib/vstudio/vc12/zlibvc.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc12/zlibvc.vcxproj +++ compat/zlib/contrib/vstudio/vc12/zlibvc.vcxproj @@ -205,12 +205,12 @@ Win32 $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch @@ -227,11 +227,11 @@ _DEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb @@ -241,14 +241,10 @@ false $(OutDir)zlibwapi.lib - - cd ..\..\masmx86 -bld_ml32.bat - NDEBUG;%(PreprocessorDefinitions) true @@ -256,11 +252,11 @@ Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -304,12 +300,12 @@ Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreaded false @@ -328,11 +324,11 @@ NDEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb @@ -343,14 +339,10 @@ $(OutDir)zlibwapi.lib false - - cd ..\..\masmx86 -bld_ml32.bat - _DEBUG;%(PreprocessorDefinitions) true @@ -358,12 +350,12 @@ X64 $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch @@ -379,11 +371,11 @@ _DEBUG;%(PreprocessorDefinitions) 0x040c - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb @@ -391,14 +383,10 @@ $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineX64 - - cd ..\..\contrib\masmx64 -bld_ml64.bat - _DEBUG;%(PreprocessorDefinitions) true @@ -406,11 +394,11 @@ Itanium $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -449,11 +437,11 @@ X64 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -494,11 +482,11 @@ Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -539,12 +527,12 @@ X64 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -562,11 +550,11 @@ NDEBUG;%(PreprocessorDefinitions) 0x040c - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb @@ -574,14 +562,10 @@ $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineX64 - - cd ..\..\masmx64 -bld_ml64.bat - NDEBUG;%(PreprocessorDefinitions) true @@ -589,11 +573,11 @@ Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -634,18 +618,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc14/testzlib.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc14/testzlib.vcxproj +++ compat/zlib/contrib/vstudio/vc14/testzlib.vcxproj @@ -188,11 +188,11 @@ Disabled ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false @@ -201,11 +201,11 @@ $(IntDir) Level3 ProgramDatabase - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)testzlib.exe true $(OutDir)testzlib.pdb Console false @@ -248,11 +248,11 @@ MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreaded false true @@ -261,11 +261,11 @@ $(IntDir) Level3 ProgramDatabase - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)testzlib.exe true Console true true @@ -277,18 +277,18 @@ ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDebugDLL false $(IntDir) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) Itanium @@ -360,18 +360,18 @@ ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDLL false $(IntDir) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) Itanium @@ -406,18 +406,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc14/zlib.rc ================================================================== --- compat/zlib/contrib/vstudio/vc14/zlib.rc +++ compat/zlib/contrib/vstudio/vc14/zlib.rc @@ -1,11 +1,11 @@ #include #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0 // not used @@ -15,18 +15,18 @@ BLOCK "040904E4" //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END Index: compat/zlib/contrib/vstudio/vc14/zlibstat.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc14/zlibstat.vcxproj +++ compat/zlib/contrib/vstudio/vc14/zlibstat.vcxproj @@ -168,11 +168,11 @@ Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -194,12 +194,12 @@ OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded false @@ -214,19 +214,19 @@ 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibstat.lib true OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded @@ -252,11 +252,11 @@ X64 Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -281,11 +281,11 @@ Itanium Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -310,12 +310,12 @@ X64 OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -330,11 +330,11 @@ 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibstat.lib true @@ -341,11 +341,11 @@ Itanium OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -371,11 +371,11 @@ X64 OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -401,11 +401,11 @@ Itanium OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -435,18 +435,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc14/zlibvc.def ================================================================== --- compat/zlib/contrib/vstudio/vc14/zlibvc.def +++ compat/zlib/contrib/vstudio/vc14/zlibvc.def @@ -1,9 +1,9 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.2 +VERSION 1.3 EXPORTS adler32 @1 compress @2 crc32 @3 @@ -149,5 +149,10 @@ 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 Index: compat/zlib/contrib/vstudio/vc14/zlibvc.sln ================================================================== --- compat/zlib/contrib/vstudio/vc14/zlibvc.sln +++ compat/zlib/contrib/vstudio/vc14/zlibvc.sln @@ -1,119 +1,119 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -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|Itanium = Debug|Itanium - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Itanium = Release|Itanium - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium - ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 - ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Debug|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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|Itanium.ActiveCfg = Release|Win32 - {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 -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +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|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Debug|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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|Itanium.ActiveCfg = Release|Win32 + {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 +EndGlobal Index: compat/zlib/contrib/vstudio/vc14/zlibvc.vcxproj ================================================================== --- compat/zlib/contrib/vstudio/vc14/zlibvc.vcxproj +++ compat/zlib/contrib/vstudio/vc14/zlibvc.vcxproj @@ -205,12 +205,12 @@ Win32 $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch @@ -227,11 +227,11 @@ _DEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb @@ -241,14 +241,10 @@ false $(OutDir)zlibwapi.lib - - cd ..\..\masmx86 -bld_ml32.bat - NDEBUG;%(PreprocessorDefinitions) true @@ -256,11 +252,11 @@ Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -304,12 +300,12 @@ Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreaded false @@ -328,11 +324,11 @@ NDEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb @@ -343,14 +339,10 @@ $(OutDir)zlibwapi.lib false - - cd ..\..\masmx86 -bld_ml32.bat - _DEBUG;%(PreprocessorDefinitions) true @@ -358,12 +350,12 @@ X64 $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch @@ -379,11 +371,11 @@ _DEBUG;%(PreprocessorDefinitions) 0x040c - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb @@ -391,14 +383,10 @@ $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineX64 - - cd ..\..\contrib\masmx64 -bld_ml64.bat - _DEBUG;%(PreprocessorDefinitions) true @@ -406,11 +394,11 @@ Itanium $(OutDir)zlibvc.tlb Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false @@ -449,11 +437,11 @@ X64 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -494,11 +482,11 @@ Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -539,12 +527,12 @@ X64 $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + ..\..\..;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -562,11 +550,11 @@ NDEBUG;%(PreprocessorDefinitions) 0x040c - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + %(AdditionalDependencies) $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb @@ -574,14 +562,10 @@ $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineX64 - - cd ..\..\masmx64 -bld_ml64.bat - NDEBUG;%(PreprocessorDefinitions) true @@ -589,11 +573,11 @@ Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ..\..\..;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -634,18 +618,10 @@ - - true - true - true - true - true - true - Index: compat/zlib/contrib/vstudio/vc9/miniunz.vcproj ================================================================== --- compat/zlib/contrib/vstudio/vc9/miniunz.vcproj +++ compat/zlib/contrib/vstudio/vc9/miniunz.vcproj @@ -540,11 +540,11 @@ Index: compat/zlib/contrib/vstudio/vc9/minizip.vcproj ================================================================== --- compat/zlib/contrib/vstudio/vc9/minizip.vcproj +++ compat/zlib/contrib/vstudio/vc9/minizip.vcproj @@ -537,11 +537,11 @@ Index: compat/zlib/contrib/vstudio/vc9/testzlib.vcproj ================================================================== --- compat/zlib/contrib/vstudio/vc9/testzlib.vcproj +++ compat/zlib/contrib/vstudio/vc9/testzlib.vcproj @@ -46,11 +46,11 @@ /> @@ -143,11 +142,10 @@ @@ -515,11 +513,11 @@ Name="VCCLCompilerTool" Optimization="2" InlineFunctionExpansion="1" OmitFramePointers="true" AdditionalIncludeDirectories="..\..\.." - PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS" + PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS" StringPooling="true" BasicRuntimeChecks="0" RuntimeLibrary="0" BufferSecurityCheck="false" EnableFunctionLevelLinking="true" @@ -538,11 +536,10 @@ @@ -615,11 +612,10 @@ @@ -731,11 +727,11 @@ @@ -754,62 +750,10 @@ - - - - - - - - - - - - - - - - - - - - Index: compat/zlib/contrib/vstudio/vc9/zlib.rc ================================================================== --- compat/zlib/contrib/vstudio/vc9/zlib.rc +++ compat/zlib/contrib/vstudio/vc9/zlib.rc @@ -1,11 +1,11 @@ #include #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0 // not used @@ -15,18 +15,18 @@ BLOCK "040904E4" //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END Index: compat/zlib/contrib/vstudio/vc9/zlibstat.vcproj ================================================================== --- compat/zlib/contrib/vstudio/vc9/zlibstat.vcproj +++ compat/zlib/contrib/vstudio/vc9/zlibstat.vcproj @@ -45,11 +45,11 @@ Name="VCMIDLTool" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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. + * 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 + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). - DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. + MAKECRCH can be #defined to write out crc32.h. A main() routine is also + produced, so that this one source file can be compiled to an executable. */ #ifdef MAKECRCH # include # 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 +#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 -# 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)); - +/* ========================================================================= + * 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 - -local volatile int crc_table_empty = 1; -local z_crc_t FAR crc_table[TBLS][256]; -local void make_crc_table OF((void)); +/* ========================================================================= + * Build the tables for byte-wise and braided CRC-32 calculations, and a table + * of powers of x for combining CRC-32s. + */ +local z_crc_t FAR crc_table[256]; +#ifdef W + local z_word_t FAR crc_big_table[256]; + local z_crc_t FAR crc_braid_table[W][256]; + local z_word_t FAR crc_braid_big_table[W][256]; + local void braid(z_crc_t [][256], z_word_t [][256], int, int); +#endif #ifdef MAKECRCH - local void write_table OF((FILE *, const z_crc_t FAR *)); + local void write_table(FILE *, const z_crc_t FAR *, int); + local void write_table32hi(FILE *, const z_word_t FAR *, int); + local void write_table64(FILE *, const z_word_t FAR *, int); #endif /* MAKECRCH */ + +/* + Define a once() function depending on the availability of atomics. If this is + compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in + multiple threads, and if atomics are not available, then get_crc_table() must + be called to initialize the tables and must return before any threads are + allowed to compute or combine CRCs. + */ + +/* Definition of once functionality. */ +typedef struct once_s once_t; + +/* Check for the availability of atomics. */ +#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ + !defined(__STDC_NO_ATOMICS__) + +#include + +/* Structure for once(), which must be initialized with ONCE_INIT. */ +struct once_s { + atomic_flag begun; + atomic_int done; +}; +#define ONCE_INIT {ATOMIC_FLAG_INIT, 0} + +/* + Run the provided init() function exactly once, even if multiple threads + invoke once() at the same time. The state must be a once_t initialized with + ONCE_INIT. + */ +local void once(once_t *state, void (*init)(void)) { + if (!atomic_load(&state->done)) { + if (atomic_flag_test_and_set(&state->begun)) + while (!atomic_load(&state->done)) + ; + else { + init(); + atomic_store(&state->done, 1); + } + } +} + +#else /* no atomics */ + +/* Structure for once(), which must be initialized with ONCE_INIT. */ +struct once_s { + volatile int begun; + volatile int done; +}; +#define ONCE_INIT {0, 0} + +/* Test and set. Alas, not atomic, but tries to minimize the period of + vulnerability. */ +local int test_and_set(int volatile *flag) { + int was; + + was = *flag; + *flag = 1; + return was; +} + +/* Run the provided init() function once. This is not thread-safe. */ +local void once(once_t *state, void (*init)(void)) { + if (!state->done) { + if (test_and_set(&state->begun)) + while (!state->done) + ; + else { + init(); + state->done = 1; + } + } +} + +#endif + +/* State for once(). */ +local once_t made = ONCE_INIT; + /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials + with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the + one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each + taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - 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) - ; - } + 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 - /* write out CRC tables to crc32.h */ { + /* + The crc32.h header file contains tables for both 32-bit and 64-bit + z_word_t's, and so requires a 64-bit type be available. In that case, + z_word_t must be defined to be 64-bits. This code then also generates + and writes out the tables for the case that z_word_t is 32 bits. + */ +#if !defined(W) || W != 8 +# error Need a 64-bit integer type in order to generate crc32.h. +#endif FILE *out; + int k, n; + z_crc_t ltl[8][256]; + z_word_t big[8][256]; out = fopen("crc32.h", "w"); if (out == NULL) return; - 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"); + + /* 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 -local void write_table(out, table) - FILE *out; - const z_crc_t FAR *table; -{ + +/* + 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 < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", - (unsigned long)(table[n]), - n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); + for (n = 0; n < k; n++) + fprintf(out, "%s0x%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 */ -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables of CRC-32s of all single-byte values, made by make_crc_table(). +#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. */ -#include "crc32.h" +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() + * This function can be used by asm versions of crc32(), and to force the + * generation of the CRC tables in a threaded application. */ -const z_crc_t FAR * ZEXPORT get_crc_table() -{ +const z_crc_t FAR * ZEXPORT get_crc_table(void) { #ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); + once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ return (const z_crc_t FAR *)crc_table; } -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -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); +/* ========================================================================= + * 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); } Index: compat/zlib/crc32.h ================================================================== --- compat/zlib/crc32.h +++ compat/zlib/crc32.h @@ -1,441 +1,9446 @@ /* crc32.h -- tables for rapid CRC calculation * Generated automatically by crc32.c */ -local const z_crc_t FAR crc_table[TBLS][256] = -{ - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 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 +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}; Index: compat/zlib/deflate.c ================================================================== --- compat/zlib/deflate.c +++ compat/zlib/deflate.c @@ -1,7 +1,7 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM @@ -50,57 +50,35 @@ /* @(#) $Id$ */ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; + " deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ -/* =========================================================================== - * Function prototypes. - */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ } block_state; -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +typedef block_state (*compress_func)(deflate_state *s, int flush); /* Compression function. Returns the block state after the call. */ -local int deflateStateCheck OF((z_streamp strm)); -local void slide_hash OF((deflate_state *s)); -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_stored(deflate_state *s, int flush); +local block_state deflate_fast(deflate_state *s, int flush); #ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#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 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 */ @@ -158,11 +136,11 @@ * 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)<hash_shift) ^ (c)) & s->hash_mask) +#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return @@ -188,21 +166,27 @@ /* =========================================================================== * 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)); + 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. */ -local void slide_hash(s) - deflate_state *s; -{ +#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; @@ -221,44 +205,186 @@ * its value will never be used. */ } while (--n); #endif } + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) { + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + zmemcpy(buf, strm->next_in, len); + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, buf, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, buf, len); + } +#endif + strm->next_in += len; + strm->total_in += len; + + return len; +} + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(deflate_state *s) { + unsigned n; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize + MAX_DIST(s)) { + + zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + if (s->insert > s->strstart) + s->insert = s->strstart; + slide_hash(s); + more += wsize; + } + if (s->strm->avail_in == 0) break; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); +} /* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ +int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, + int stream_size) { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ +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; - 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; @@ -285,10 +411,12 @@ 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 */ @@ -314,33 +442,75 @@ s->w_mask = s->w_size - 1; s->hash_bits = (uInt)memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->high_water = 0; /* nothing written to s->window yet */ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - 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); + /* 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, 4); + 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; } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + s->sym_buf = s->pending_buf + s->lit_bufsize; + s->sym_end = (s->lit_bufsize - 1) * 3; + /* 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; @@ -348,13 +518,11 @@ } /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ -local int deflateStateCheck (strm) - z_streamp strm; -{ +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; @@ -371,15 +539,12 @@ return 1; return 0; } /* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ +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; @@ -440,15 +605,12 @@ s->wrap = wrap; return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) - z_streamp strm; - Bytef *dictionary; - uInt *dictLength; -{ +int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary, + uInt *dictLength) { deflate_state *s; uInt len; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -462,13 +624,11 @@ *dictLength = len; return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflateResetKeep (strm) - z_streamp strm; -{ +int ZEXPORT deflateResetKeep(z_streamp strm) { deflate_state *s; if (deflateStateCheck(strm)) { return Z_STREAM_ERROR; } @@ -486,72 +646,84 @@ } s->status = #ifdef GZIP s->wrap == 2 ? GZIP_STATE : #endif - s->wrap ? INIT_STATE : BUSY_STATE; + INIT_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; + s->last_flush = -2; _tr_init(s); return Z_OK; } + +/* =========================================================================== + * 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 (strm) - z_streamp strm; -{ +int ZEXPORT deflateReset(z_streamp strm) { int ret; ret = deflateResetKeep(strm); if (ret == Z_OK) lm_init(strm->state); return ret; } /* ========================================================================= */ -int ZEXPORT deflateSetHeader (strm, head) - z_streamp strm; - gz_headerp head; -{ +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 (strm, pending, bits) - unsigned *pending; - int *bits; - z_streamp strm; -{ +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 (strm, bits, value) - z_streamp strm; - int bits; - int value; -{ +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; - if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) + if (bits < 0 || bits > 16 || + s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; do { put = Buf_size - s->bi_valid; if (put > bits) put = bits; @@ -563,15 +735,11 @@ } while (bits); return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ +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; @@ -585,16 +753,16 @@ return Z_STREAM_ERROR; } func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && - s->high_water) { + s->last_flush != -2) { /* Flush the last buffer: */ int err = deflate(strm, Z_BLOCK); if (err == Z_STREAM_ERROR) return err; - if (strm->avail_out == 0) + if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead) return Z_BUF_ERROR; } if (s->level != level) { if (s->level == 0 && s->matches != 0) { if (s->matches == 1) @@ -612,17 +780,12 @@ 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; -{ +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; @@ -631,40 +794,51 @@ 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; -{ + * 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 complen, wraplen; + uLong fixedlen, storelen, wraplen; - /* conservative upper bound for compressed data */ - complen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + /* 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; - /* if can't get parameters, return conservative bound plus zlib wrapper */ + /* 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 complen + 6; + return (fixedlen > storelen ? fixedlen : storelen) + 6; /* compute wrapper length */ s = strm->state; switch (s->wrap) { case 0: /* raw deflate */ @@ -697,28 +871,27 @@ #endif default: /* for compiler happiness */ wraplen = 6; } - /* if not default parameters, return conservative bound */ + /* if not default parameters, return one of the conservative bounds */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return complen + wraplen; + return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) + + wraplen; - /* default settings: return tight bound for that case */ + /* default settings: return tight bound for that case -- ~0.03% overhead + plus a small constant */ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; } /* ========================================================================= * Put a short in the pending buffer. The 16-bit value is put in MSB order. * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ -local void putShortMSB (s, b) - deflate_state *s; - uInt b; -{ +local void putShortMSB(deflate_state *s, uInt b) { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= @@ -725,13 +898,11 @@ * 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; -{ +local void flush_pending(z_streamp strm) { unsigned len; deflate_state *s = strm->state; _tr_flush_bits(s); len = s->pending; @@ -758,14 +929,11 @@ 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 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; @@ -809,13 +977,15 @@ if (s->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Write the header */ + if (s->status == INIT_STATE && s->wrap == 0) + s->status = BUSY_STATE; if (s->status == INIT_STATE) { /* zlib header */ - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) level_flags = 0; else if (s->level < 6) @@ -1071,13 +1241,11 @@ 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 ZEXPORT deflateEnd(z_streamp strm) { int status; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; status = strm->state->status; @@ -1097,20 +1265,18 @@ /* ========================================================================= * 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; -{ +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; - ushf *overlay; if (deflateStateCheck(source) || dest == Z_NULL) { return Z_STREAM_ERROR; } @@ -1126,12 +1292,11 @@ ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; + ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4); if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { deflateEnd (dest); return Z_MEM_ERROR; @@ -1141,86 +1306,20 @@ 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->sym_buf = ds->pending_buf + 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 @@ -1227,18 +1326,11 @@ * 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 */ -{ +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 */ @@ -1255,14 +1347,14 @@ /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); + register ush scan_end = *(ushf*)(scan + best_len - 1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end1 = scan[best_len - 1]; register Byte scan_end = scan[best_len]; #endif /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. @@ -1276,11 +1368,12 @@ /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; @@ -1294,66 +1387,68 @@ */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ - if (*(ushf*)(match+best_len-1) != scan_end || + if (*(ushf*)(match + best_len - 1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient + * strstart + 3, + 5, up to strstart + 257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) && + *(ushf*)(scan += 2) == *(ushf*)(match += 2) && + *(ushf*)(scan += 2) == *(ushf*)(match += 2) && + *(ushf*)(scan += 2) == *(ushf*)(match += 2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + /* Here, scan <= window + strstart + 257 */ + Assert(scan <= s->window + (unsigned)(s->window_size - 1), + "wild scan"); if (*scan == *match) scan++; - len = (MAX_MATCH - 1) - (int)(strend-scan); + len = (MAX_MATCH - 1) - (int)(strend - scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; + if (match[best_len] != scan_end || + match[best_len - 1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; - /* The check at best_len-1 can be removed because it will be made + /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. + * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (unsigned)(s->window_size - 1), + "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ @@ -1361,33 +1456,29 @@ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); + scan_end = *(ushf*)(scan + best_len - 1); #else - scan_end1 = scan[best_len-1]; + scan_end1 = scan[best_len - 1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } -#endif /* ASMV */ #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ +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; @@ -1394,40 +1485,41 @@ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "need lookahead"); Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Return failure if the match length is less than 2: */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - /* The check at best_len-1 can be removed because it will be made + /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match += 2; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. + * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); if (len < MIN_MATCH) return MIN_MATCH - 1; @@ -1443,15 +1535,11 @@ /* 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; -{ +local void check_match(deflate_state *s, IPos start, IPos 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); @@ -1459,147 +1547,18 @@ 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); + 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) { \ @@ -1636,16 +1595,13 @@ * allowed here, then the hash table will be cleared, since two or more slides * is the same as a clear. * * deflate_stored() is written to minimize the number of times an input byte is * copied. It is most efficient with large input and output buffers, which - * maximizes the opportunites to have a single copy from next_in to next_out. + * maximizes the opportunities to have a single copy from next_in to next_out. */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ +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); @@ -1740,24 +1696,27 @@ */ if (used >= s->w_size) { /* supplant the previous history */ s->matches = 2; /* clear hash */ zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); s->strstart = s->w_size; + s->insert = s->strstart; } else { if (s->window_size - s->strstart <= used) { /* Slide the window down. */ s->strstart -= s->w_size; zmemcpy(s->window, s->window + s->w_size, s->strstart); if (s->matches < 2) s->matches++; /* add a pending slide_hash() */ + if (s->insert > s->strstart) + s->insert = s->strstart; } zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); s->strstart += used; + s->insert += MIN(used, s->w_size - s->insert); } s->block_start = s->strstart; - s->insert += MIN(used, s->w_size - s->insert); } if (s->high_water < s->strstart) s->high_water = s->strstart; /* If the last block was written to next_out, then done. */ @@ -1768,25 +1727,28 @@ if (flush != Z_NO_FLUSH && flush != Z_FINISH && s->strm->avail_in == 0 && (long)s->strstart == s->block_start) return block_done; /* Fill the window with any remaining input. */ - have = s->window_size - s->strstart - 1; + have = s->window_size - s->strstart; if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { /* Slide the window down. */ s->block_start -= s->w_size; s->strstart -= s->w_size; zmemcpy(s->window, s->window + s->w_size, s->strstart); if (s->matches < 2) s->matches++; /* add a pending slide_hash() */ have += s->w_size; /* more space now */ + if (s->insert > s->strstart) + s->insert = s->strstart; } if (have > s->strm->avail_in) have = s->strm->avail_in; if (have) { read_buf(s->strm, s->window + s->strstart, have); s->strstart += have; + s->insert += MIN(have, s->w_size - s->insert); } if (s->high_water < s->strstart) s->high_water = s->strstart; /* There was not enough avail_out to write a complete worthy or flushed @@ -1819,14 +1781,11 @@ * 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; -{ +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 @@ -1840,11 +1799,11 @@ return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); @@ -1888,11 +1847,11 @@ #endif { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); + UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. @@ -1899,11 +1858,11 @@ */ } } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } @@ -1910,11 +1869,11 @@ s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } #ifndef FASTEST @@ -1921,14 +1880,11 @@ /* =========================================================================== * 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; -{ +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 (;;) { @@ -1943,11 +1899,11 @@ return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); @@ -1985,21 +1941,21 @@ */ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ - check_match(s, s->strstart-1, s->prev_match, s->prev_length); + check_match(s, s->strstart - 1, s->prev_match, s->prev_length); - _tr_tally_dist(s, s->strstart -1 - s->prev_match, + _tr_tally_dist(s, s->strstart - 1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not + * strstart - 1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ - s->lookahead -= s->prev_length-1; + s->lookahead -= s->prev_length - 1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { INSERT_STRING(s, s->strstart, hash_head); } @@ -2013,12 +1969,12 @@ } else if (s->match_available) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); + Tracevv((stderr,"%c", s->window[s->strstart - 1])); + _tr_tally_lit(s, s->window[s->strstart - 1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; s->lookahead--; @@ -2032,20 +1988,20 @@ s->lookahead--; } } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); + Tracevv((stderr,"%c", s->window[s->strstart - 1])); + _tr_tally_lit(s, s->window[s->strstart - 1], bflush); s->match_available = 0; } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } #endif /* FASTEST */ @@ -2052,14 +2008,11 @@ /* =========================================================================== * 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; -{ +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 (;;) { @@ -2090,11 +2043,12 @@ scan < strend); s->match_length = MAX_MATCH - (uInt)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } - Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (uInt)(s->window_size - 1), + "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->strstart - 1, s->match_length); @@ -2105,11 +2059,11 @@ s->strstart += s->match_length; s->match_length = 0; } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } @@ -2116,23 +2070,20 @@ s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } /* =========================================================================== * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ -local block_state deflate_huff(s, flush) - deflate_state *s; - int flush; -{ +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) { @@ -2145,19 +2096,19 @@ } /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } - if (s->last_lit) + if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } Index: compat/zlib/deflate.h ================================================================== --- compat/zlib/deflate.h +++ compat/zlib/deflate.h @@ -1,7 +1,7 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2016 Jean-loup Gailly + * Copyright (C) 1995-2018 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 @@ -215,11 +215,11 @@ 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 */ + uchf *sym_buf; /* buffer for distances and literals/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 @@ -237,17 +237,12 @@ * 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. - */ + uInt sym_next; /* running index in sym_buf */ + 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 */ @@ -294,18 +289,18 @@ #define WIN_INIT MAX_MATCH /* Number of bytes after end of data in window to initialize in order to avoid memory checker errors from longest match routines */ /* in trees.c */ -void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); -int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); -void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_init(deflate_state *s); +int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc); +void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, + ulg stored_len, int last); +void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s); +void ZLIB_INTERNAL _tr_align(deflate_state *s); +void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, + ulg stored_len, int last); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. _dist_code[256] and _dist_code[257] are never @@ -323,27 +318,29 @@ 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->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->last_lit == s->lit_bufsize-1); \ + flush = (s->sym_next == s->sym_end); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (uch)(length); \ ush dist = (ush)(distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ + s->sym_buf[s->sym_next++] = (uch)dist; \ + s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \ + s->sym_buf[s->sym_next++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ + flush = (s->sym_next == s->sym_end); \ } #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 */ Index: compat/zlib/examples/README.examples ================================================================== --- compat/zlib/examples/README.examples +++ compat/zlib/examples/README.examples @@ -32,10 +32,14 @@ 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 @@ -42,8 +46,9 @@ 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 Index: compat/zlib/examples/enough.c ================================================================== --- compat/zlib/examples/enough.c +++ compat/zlib/examples/enough.c @@ -1,9 +1,9 @@ /* enough.c -- determine the maximum size of inflate's Huffman code tables over - * all possible valid and complete Huffman codes, subject to a length limit. - * Copyright (C) 2007, 2008, 2012 Mark Adler - * Version 1.4 18 August 2012 Mark Adler + * all possible valid and complete prefix codes, subject to a length limit. + * Copyright (C) 2007, 2008, 2012, 2018 Mark Adler + * Version 1.5 5 August 2018 Mark Adler */ /* Version history: 1.0 3 Jan 2007 First version (derived from codecount.c version 1.4) 1.1 4 Jan 2007 Use faster incremental table usage computation @@ -15,105 +15,111 @@ Fix bug for initial root table size == max - 1 Use a macro to compute the history index 1.4 18 Aug 2012 Avoid shifts more than bits in type (caused endless loop!) Clean up comparisons of different types Clean up code indentation + 1.5 5 Aug 2018 Clean up code style, formatting, and comments + Show all the codes for the maximum, and only the maximum */ /* - Examine all possible Huffman codes for a given number of symbols and a - maximum code length in bits to determine the maximum table size for zilb's - inflate. Only complete Huffman codes are counted. + Examine all possible prefix codes for a given number of symbols and a + maximum code length in bits to determine the maximum table size for zlib's + inflate. Only complete prefix codes are counted. Two codes are considered distinct if the vectors of the number of codes per - length are not identical. So permutations of the symbol assignments result + length are not identical. So permutations of the symbol assignments result in the same code for the counting, as do permutations of the assignments of the bit values to the codes (i.e. only canonical codes are counted). We build a code from shorter to longer lengths, determining how many symbols - are coded at each length. At each step, we have how many symbols remain to + are coded at each length. At each step, we have how many symbols remain to be coded, what the last code length used was, and how many bit patterns of that length remain unused. Then we add one to the code length and double the - number of unused patterns to graduate to the next code length. We then + number of unused patterns to graduate to the next code length. We then assign all portions of the remaining symbols to that code length that - preserve the properties of a correct and eventually complete code. Those + preserve the properties of a correct and eventually complete code. Those properties are: we cannot use more bit patterns than are available; and when - all the symbols are used, there are exactly zero possible bit patterns - remaining. + all the symbols are used, there are exactly zero possible bit patterns left + unused. The inflate Huffman decoding algorithm uses two-level lookup tables for - speed. There is a single first-level table to decode codes up to root bits - in length (root == 9 in the current inflate implementation). The table - has 1 << root entries and is indexed by the next root bits of input. Codes - shorter than root bits have replicated table entries, so that the correct - entry is pointed to regardless of the bits that follow the short code. If - the code is longer than root bits, then the table entry points to a second- - level table. The size of that table is determined by the longest code with - that root-bit prefix. If that longest code has length len, then the table - has size 1 << (len - root), to index the remaining bits in that set of - codes. Each subsequent root-bit prefix then has its own sub-table. The - total number of table entries required by the code is calculated - incrementally as the number of codes at each bit length is populated. When - all of the codes are shorter than root bits, then root is reduced to the - longest code length, resulting in a single, smaller, one-level table. + speed. There is a single first-level table to decode codes up to root bits + in length (root == 9 for literal/length codes and root == 6 for distance + codes, in the current inflate implementation). The base table has 1 << root + entries and is indexed by the next root bits of input. Codes shorter than + root bits have replicated table entries, so that the correct entry is + pointed to regardless of the bits that follow the short code. If the code is + longer than root bits, then the table entry points to a second-level table. + The size of that table is determined by the longest code with that root-bit + prefix. If that longest code has length len, then the table has size 1 << + (len - root), to index the remaining bits in that set of codes. Each + subsequent root-bit prefix then has its own sub-table. The total number of + table entries required by the code is calculated incrementally as the number + of codes at each bit length is populated. When all of the codes are shorter + than root bits, then root is reduced to the longest code length, resulting + in a single, smaller, one-level table. The inflate algorithm also provides for small values of root (relative to the log2 of the number of symbols), where the shortest code has more bits - than root. In that case, root is increased to the length of the shortest - code. This program, by design, does not handle that case, so it is verified - that the number of symbols is less than 2^(root + 1). + than root. In that case, root is increased to the length of the shortest + code. This program, by design, does not handle that case, so it is verified + that the number of symbols is less than 1 << (root + 1). In order to speed up the examination (by about ten orders of magnitude for the default arguments), the intermediate states in the build-up of a code - are remembered and previously visited branches are pruned. The memory + are remembered and previously visited branches are pruned. The memory required for this will increase rapidly with the total number of symbols and - the maximum code length in bits. However this is a very small price to pay + the maximum code length in bits. However this is a very small price to pay for the vast speedup. - First, all of the possible Huffman codes are counted, and reachable + First, all of the possible prefix codes are counted, and reachable intermediate states are noted by a non-zero count in a saved-results array. Second, the intermediate states that lead to (root + 1) bit or longer codes are used to look at all sub-codes from those junctures for their inflate - memory usage. (The amount of memory used is not affected by the number of + memory usage. (The amount of memory used is not affected by the number of codes of root bits or less in length.) Third, the visited states in the construction of those sub-codes and the associated calculation of the table size is recalled in order to avoid recalculating from the same juncture. Beginning the code examination at (root + 1) bit codes, which is enabled by identifying the reachable nodes, accounts for about six of the orders of - magnitude of improvement for the default arguments. About another four - orders of magnitude come from not revisiting previous states. Out of - approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes + magnitude of improvement for the default arguments. About another four + orders of magnitude come from not revisiting previous states. Out of + approximately 2x10^16 possible prefix codes, only about 2x10^6 sub-codes need to be examined to cover all of the possible table memory usage cases for the default arguments of 286 symbols limited to 15-bit codes. - Note that an unsigned long long type is used for counting. It is quite easy - to exceed the capacity of an eight-byte integer with a large number of - symbols and a large maximum code length, so multiple-precision arithmetic - would need to replace the unsigned long long arithmetic in that case. This - program will abort if an overflow occurs. The big_t type identifies where - the counting takes place. - - 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. + 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 #include #include +#include +#include #include #define local static -/* special data types */ -typedef unsigned long long big_t; /* type for code counting */ -typedef unsigned long long code_t; /* type for bit pattern counting */ -struct tab { /* type for been here check */ - size_t len; /* length of bit vector in char's */ - char *vec; /* allocated bit vector */ +// Special data types. +typedef uintmax_t big_t; // type for code counting +#define PRIbig "ju" // printf format for big_t +typedef uintmax_t code_t; // type for bit pattern counting +struct tab { // type for been-here check + size_t len; // allocated length of bit vector in octets + char *vec; // allocated bit vector }; /* The array for saving results, num[], is indexed with this triplet: syms: number of symbols remaining to code @@ -124,449 +130,468 @@ syms: 3..totsym (totsym == total symbols to code) left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6) len: 1..max - 1 (max == maximum code length in bits) - syms == 2 is not saved since that immediately leads to a single code. left + syms == 2 is not saved since that immediately leads to a single code. left must be even, since it represents the number of available bit patterns at - the current length, which is double the number at the previous length. - left ends at syms-1 since left == syms immediately results in a single code. + the current length, which is double the number at the previous length. left + ends at syms-1 since left == syms immediately results in a single code. (left > sym is not allowed since that would result in an incomplete code.) len is less than max, since the code completes immediately when len == max. - The offset into the array is calculated for the three indices with the - first one (syms) being outermost, and the last one (len) being innermost. - We build the array with length max-1 lists for the len index, with syms-3 - of those for each symbol. There are totsym-2 of those, with each one - varying in length as a function of sym. See the calculation of index in - count() for the index, and the calculation of size in main() for the size - of the array. + 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 Huffman codes. + has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than half + of the space allocated for saved results is actually used -- not all + possible triplets are reached in the generation of valid prefix codes. */ /* The array for tracking visited states, done[], is itself indexed identically to the num[] array as described above for the (syms, left, len) triplet. Each element in the array is further indexed by the (mem, rem) doublet, where mem is the amount of inflate table space used so far, and rem is the - remaining unused entries in the current inflate sub-table. Each indexed + remaining unused entries in the current inflate sub-table. Each indexed element is simply one bit indicating whether the state has been visited or - not. Since the ranges for mem and rem are not known a priori, each bit + not. Since the ranges for mem and rem are not known a priori, each bit vector is of a variable size, and grows as needed to accommodate the visited - states. mem and rem are used to calculate a single index in a triangular - array. Since the range of mem is expected in the default case to be about + states. mem and rem are used to calculate a single index in a triangular + array. Since the range of mem is expected in the default case to be about ten times larger than the range of rem, the array is skewed to reduce the - memory usage, with eight times the range for mem than for rem. See the - calculations for offset and bit in beenhere() for the details. + memory usage, with eight times the range for mem than for rem. See the + calculations for offset and bit in been_here() for the details. For the deflate example of 286 symbols limited to 15-bit codes, the bit - vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[] - array itself. + vectors grow to total 5.5 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 */ +// 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 < max); + // note and verify the expected state + assert(syms > left && left > 0 && len < g.max); - /* see if we've done this one already */ - index = INDEX(syms, left, len); - got = num[index]; + // see if we've done this one already + size_t index = map(syms, left, len); + big_t got = g.num[index]; if (got) - return got; /* we have -- return the saved result */ + return got; // we have -- return the saved result - /* we need to use at least this many bit patterns so that the code won't be - incomplete at the next length (more bit patterns than symbols) */ - least = (left << 1) - syms; + // we need to use at least this many bit patterns so that the code won't be + // incomplete at the next length (more bit patterns than symbols) + int least = (left << 1) - syms; if (least < 0) least = 0; - /* we can use at most this many bit patterns, lest there not be enough - available for the remaining symbols at the maximum length (if there were - no limit to the code length, this would become: most = left - 1) */ - most = (((code_t)left << (max - len)) - syms) / - (((code_t)1 << (max - len)) - 1); - - /* 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); + // 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)0 - 1 || sum < got) /* overflow */ - return (big_t)0 - 1; + if (got == (big_t)-1 || sum < got) // overflow + return (big_t)-1; } - /* verify that all recursive calls are productive */ + // verify that all recursive calls are productive assert(sum != 0); - /* save the result and return it */ - num[index] = sum; + // save the result and return it + g.num[index] = sum; return sum; } -/* Return true if we've been here before, set to true if not. Set a bit in a - bit vector to indicate visiting this state. Each (syms,len,left) state - has a variable size bit vector indexed by (mem,rem). The bit vector is - lengthened if needed to allow setting the (mem,rem) bit. */ -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; +// 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; - 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 */ + 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 */ + // if we have one already, enlarge it, zero out the appended space + char *vector; if (length) { do { length <<= 1; } while (length <= offset); - vector = realloc(done[index].vec, length); - if (vector != NULL) - memset(vector + done[index].len, 0, length - done[index].len); - } - - /* 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; + 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. 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 */ +// 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 */ - code[len] = left; + // set the last code entry + g.code[len] = left; - /* complete computation of memory used by this code */ + // complete computation of memory used by this code while (rem < left) { left -= rem; - rem = 1 << (len - root); + rem = 1 << (len - g.root); mem += rem; } assert(rem == left); - /* if this is 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 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) */ - 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; + // 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 - root); + rem = 1 << (len - g.root); mem += rem; } rem -= use; - /* examine codes from here, updating table space as we go */ + // examine codes from here, updating table space as we go for (use = least; use <= most; use++) { - code[len] = use; - examine(syms - use, len + 1, (left - use) << 1, - mem + (rem ? 1 << (len - root) : 0), rem << 1); + g.code[len] = use; + examine(syms - use, (left - use) << 1, len + 1, + mem + (rem ? 1 << (len - g.root) : 0), rem << 1); if (rem == 0) { - rem = 1 << (len - root); + rem = 1 << (len - g.root); mem += rem; } rem--; } - /* remove entries as we drop back down in the recursion */ - code[len] = 0; -} - -/* 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; + // 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) { - root = atoi(argv[2]); + g.root = atoi(argv[2]); if (argc > 3) - max = atoi(argv[3]); + g.max = atoi(argv[3]); } } - if (argc > 4 || syms < 2 || root < 1 || max < 1) { + if (argc > 4 || syms < 2 || g.root < 1 || g.max < 1) { fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n", stderr); return 1; } - /* if not restricting the code length, the longest is syms - 1 */ - if (max > syms - 1) - max = syms - 1; - - /* 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))) { + // 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 << 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); + // 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 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 */ + // 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; } Index: compat/zlib/examples/fitblk.c ================================================================== --- compat/zlib/examples/fitblk.c +++ compat/zlib/examples/fitblk.c @@ -15,11 +15,11 @@ fitblk performs three compression passes on a portion of the input data in order to determine how much of that input will compress to nearly the requested output block size. The first pass generates enough deflate blocks to produce output to fill the requested - output size plus a specfied excess amount (see the EXCESS define + output size plus a specified excess amount (see the EXCESS define below). The last deflate block may go quite a bit past that, but is discarded. The second pass decompresses and recompresses just the compressed data that fit in the requested plus excess sized buffer. The deflate process is terminated after that amount of input, which is less than the amount consumed on the first pass. @@ -107,11 +107,11 @@ assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR && ret != Z_NEED_DICT); if (ret == Z_MEM_ERROR) return ret; - /* compress what was decompresed until done or no room */ + /* compress what was decompressed until done or no room */ def->avail_in = RAWLEN - inf->avail_out; def->next_in = raw; if (inf->avail_out != 0) flush = Z_FINISH; ret = deflate(def, flush); @@ -196,11 +196,11 @@ def.next_out = tmp; ret = recompress(&inf, &def); if (ret == Z_MEM_ERROR) quit("out of memory"); - /* set up for next reocmpression */ + /* set up for next recompression */ ret = inflateReset(&inf); assert(ret != Z_STREAM_ERROR); ret = deflateReset(&def); assert(ret != Z_STREAM_ERROR); Index: compat/zlib/examples/gun.c ================================================================== --- compat/zlib/examples/gun.c +++ compat/zlib/examples/gun.c @@ -41,11 +41,11 @@ file. gun will also decompress files made by Unix compress, which uses LZW compression. These files are automatically detected by virtue of their magic header bytes. Since the end of Unix compress stream is marked by the - end-of-file, they cannot be concantenated. If a Unix compress stream is + end-of-file, they cannot be concatenated. If a Unix compress stream is encountered in an input file, it is the last stream in that file. Like gunzip and uncompress, the file attributes of the original compressed file are maintained in the final uncompressed file, to the extent that the user permissions allow it. Index: compat/zlib/examples/gzappend.c ================================================================== --- compat/zlib/examples/gzappend.c +++ compat/zlib/examples/gzappend.c @@ -31,11 +31,11 @@ * - Send help to stdout instead of stderr * - Add some preemptive typecasts * - Add L to constants in lseek() calls * - Remove some debugging information in error messages * - Use new data_type definition for zlib 1.2.1 - * - Simplfy and unify file operations + * - Simplify and unify file operations * - Finish off gzip file in gztack() * - Use deflatePrime() instead of adding empty blocks * - Keep gzip file clean on appended file read errors * - Use in-place rotate instead of auxiliary buffer * (Why you ask? Because it was fun to write!) @@ -52,11 +52,11 @@ This program was written to illustrate the use of the new Z_BLOCK option of zlib 1.2.x's inflate() function. This option returns from inflate() at each block boundary to facilitate locating and modifying the last block bit at the start of the final deflate block. Also whether using Z_BLOCK or not, another required feature of zlib 1.2.x is that inflate() now provides the - number of unusued bits in the last input byte used. gzappend will not work + number of unused bits in the last input byte used. gzappend will not work with versions of zlib earlier than 1.2.1. gzappend first decompresses the gzip file internally, discarding all but the last 32K of uncompressed data, and noting the location of the last block bit and the number of unused bits in the last byte of the compressed data. @@ -135,11 +135,11 @@ last = list + (len - 1); /* do simple left shift by one */ if (rot == 1) { tmp = *list; - memcpy(list, list + 1, len - 1); + memmove(list, list + 1, len - 1); *last = tmp; return; } /* do simple right shift by one */ Index: compat/zlib/examples/gzlog.c ================================================================== --- compat/zlib/examples/gzlog.c +++ compat/zlib/examples/gzlog.c @@ -1,10 +1,10 @@ /* * gzlog.c - * Copyright (C) 2004, 2008, 2012, 2016 Mark Adler, all rights reserved + * Copyright (C) 2004, 2008, 2012, 2016, 2019 Mark Adler, all rights reserved * For conditions of distribution and use, see copyright notice in gzlog.h - * version 2.2, 14 Aug 2012 + * version 2.3, 25 May 2019 */ /* gzlog provides a mechanism for frequently appending short strings to a gzip file that is efficient both in execution time and compression ratio. The @@ -754,16 +754,18 @@ (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"); } Index: compat/zlib/examples/gzlog.h ================================================================== --- compat/zlib/examples/gzlog.h +++ compat/zlib/examples/gzlog.h @@ -38,11 +38,11 @@ 1 MB has been accumulated. At that time, the stored data is compressed, and replaces the uncompressed data in the file. The log file is truncated to its new size at that time. After each write operation, the log file is a valid gzip file that can decompressed to recover what was written. - The gzlog operations can be interupted at any point due to an application or + The gzlog operations can be interrupted at any point due to an application or system crash, and the log file will be recovered the next time the log is opened with gzlog_open(). */ #ifndef GZLOG_H ADDED compat/zlib/examples/gznorm.c Index: compat/zlib/examples/gznorm.c ================================================================== --- /dev/null +++ compat/zlib/examples/gznorm.c @@ -0,0 +1,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 // fread, fwrite, putc, fflush, ferror, fprintf, + // vsnprintf, stdout, stderr, NULL, FILE +#include // malloc, free +#include // strerror +#include // errno +#include // 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 +# include +# 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; +} Index: compat/zlib/examples/zlib_how.html ================================================================== --- compat/zlib/examples/zlib_how.html +++ compat/zlib/examples/zlib_how.html @@ -1,12 +1,12 @@ - + zlib Usage Example - +

zlib Usage Example

We often get questions about how the deflate() and inflate() functions should be used. Users wonder when they should provide more input, when they should use more output, @@ -15,11 +15,11 @@ 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 deflate() and inflate() 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 zlib.

-Without further adieu, here is the program zpipe.c: +Without further ado, here is the program zpipe.c:


 /* 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 */
 
@@ -153,17 +153,15 @@
     /* compress until end of file */
     do {
 
We start off by reading data from the input file. The number of bytes read is put directly into avail_in, and a pointer to those bytes is put into next_in. We also -check to see if end-of-file on the input has been reached. If we are at the end of file, then flush is set to the +check to see if end-of-file on the input has been reached using feof(). +If we are at the end of file, then flush is set to the zlib constant Z_FINISH, which is later passed to deflate() to -indicate that this is the last chunk of input data to compress. We need to use feof() -to check for end-of-file as opposed to seeing if fewer than CHUNK bytes have been read. The -reason is that if the input file length is an exact multiple of CHUNK, we will miss -the fact that we got to the end-of-file, and not know to tell deflate() to finish -up the compressed stream. If we are not yet at the end of the input, then the zlib +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 zlib constant Z_NO_FLUSH will be passed to deflate to indicate that we are still in the middle of the uncompressed data.

If there is an error in reading from the input file, the process is aborted with deflateEnd() being called to free the allocated zlib state before returning @@ -538,8 +536,14 @@ return 1; } }


-Copyright (c) 2004, 2005 by Mark Adler
Last modified 11 December 2005
+Last modified 24 January 2023
+Copyright © 2004-2023 Mark Adler

+ +Creative Commons License + +Creative Commons Attribution-NoDerivatives 4.0 International License. Index: compat/zlib/examples/zran.c ================================================================== --- compat/zlib/examples/zran.c +++ compat/zlib/examples/zran.c @@ -1,385 +1,505 @@ -/* zran.c -- example of zlib/gzip stream indexing and random access - * Copyright (C) 2005, 2012 Mark Adler +/* zran.c -- example of deflate stream indexing and random access + * Copyright (C) 2005, 2012, 2018, 2023 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h - Version 1.1 29 Sep 2012 Mark Adler */ + * Version 1.4 13 Apr 2023 Mark Adler */ /* Version History: 1.0 29 May 2005 First version 1.1 29 Sep 2012 Fix memory reallocation error - */ - -/* 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. - */ + 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 #include #include +#include #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) -{ +#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 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) */ +// 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) { - index = malloc(sizeof(struct access)); - if (index == NULL) return NULL; - index->list = malloc(sizeof(struct point) << 3); + // 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; } - index->size = 8; - index->have = 0; } - /* if list is full, make it bigger */ - else if (index->have == index->size) { - index->size <<= 1; - next = realloc(index->list, sizeof(struct point) * index->size); + else if (index->have == index->mode) { + // The list is full. Make it bigger. + index->mode <<= 1; + point_t *next = realloc(index->list, sizeof(point_t) * index->mode); if (next == NULL) { - free_index(index); + deflate_index_free(index); return NULL; } index->list = next; } - /* fill in entry and increment how many we have */ - next = index->list + index->have; - next->bits = bits; - next->in = in; + // 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); - index->have++; - /* return list, possibly reallocated */ + // Return the index, which may have been newly allocated or destroyed. return index; } -/* Make one entire pass through the compressed stream and build an index, with - access points about every span bytes of uncompressed output -- span is - chosen to balance the speed of random access against the memory requirements - of the list, about 32K bytes per access point. Note that data after the end - of the first zlib or gzip stream in the file is ignored. build_index() - returns the number of access points on success (>= 1), Z_MEM_ERROR for out - 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) +// 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 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 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 */ + // 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; - 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 (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; } - /* build index */ - len = build_index(in, SPAN, &index); + // 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]); @@ -389,21 +509,25 @@ } return 1; } fprintf(stderr, "zran: built index with %d access points\n", len); - /* use index by reading some bytes from an arbitrary offset */ - offset = (index->list[index->have - 1].out << 1) / 3; - len = extract(in, index, offset, buf, CHUNK); - if (len < 0) + // Use index by reading some bytes from an arbitrary offset. + unsigned char buf[LEN]; + if (offset == -1) + offset = ((index->length + 1) << 1) / 3; + ptrdiff_t got = deflate_index_extract(in, index, offset, buf, LEN); + if (got < 0) fprintf(stderr, "zran: extraction failed: %s error\n", - len == Z_MEM_ERROR ? "out of memory" : "input corrupted"); + got == Z_MEM_ERROR ? "out of memory" : "input corrupted"); else { - fwrite(buf, 1, len, stdout); - fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset); + fwrite(buf, 1, got, stdout); + fprintf(stderr, "zran: extracted %ld bytes at %lld\n", got, offset); } - /* clean up and exit */ - free_index(index); + // Clean up and exit. + deflate_index_free(index); fclose(in); return 0; } + +#endif ADDED compat/zlib/examples/zran.h Index: compat/zlib/examples/zran.h ================================================================== --- /dev/null +++ compat/zlib/examples/zran.h @@ -0,0 +1,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 +#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); Index: compat/zlib/gzclose.c ================================================================== --- compat/zlib/gzclose.c +++ compat/zlib/gzclose.c @@ -6,13 +6,11 @@ #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; -{ +int ZEXPORT gzclose(gzFile file) { #ifndef NO_GZCOMPRESS gz_statep state; if (file == NULL) return Z_STREAM_ERROR; Index: compat/zlib/gzguts.h ================================================================== --- compat/zlib/gzguts.h +++ compat/zlib/gzguts.h @@ -1,17 +1,16 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * Copyright (C) 2004-2019 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 +# undef _FILE_OFFSET_BITS +# undef _TIME_BITS #endif #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else @@ -37,11 +36,11 @@ #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include #endif -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_WIN32) # define WIDECHAR #endif #ifdef WINAPI_FAMILY # define open _open @@ -117,12 +116,12 @@ define "local" for the non-static meaning of "static", for readability (compile with -Dlocal if your debugger can't find static symbols) */ /* gz* functions always use library allocation functions */ #ifndef STDC - extern voidp malloc OF((uInt size)); - extern void free OF((voidpf ptr)); + extern voidp malloc(uInt size); + extern void free(voidpf ptr); #endif /* get errno and strerror definition */ #if defined UNDER_CE # include @@ -136,14 +135,14 @@ # endif #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); #endif /* default memLevel */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 @@ -188,10 +187,11 @@ 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 */ @@ -200,19 +200,19 @@ z_stream strm; /* stream structure in-place (not a pointer) */ } gz_state; typedef gz_state FAR *gz_statep; /* shared functions */ -void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +void ZLIB_INTERNAL gz_error(gz_statep, int, const char *); #if defined UNDER_CE -char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +char ZLIB_INTERNAL *gz_strwinerror(DWORD error); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ #ifdef INT_MAX # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) #else -unsigned ZLIB_INTERNAL gz_intmax OF((void)); +unsigned ZLIB_INTERNAL gz_intmax(void); # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) #endif Index: compat/zlib/gzlib.c ================================================================== --- compat/zlib/gzlib.c +++ compat/zlib/gzlib.c @@ -1,26 +1,22 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004-2017 Mark Adler + * Copyright (C) 2004-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" -#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__) +#if defined(_WIN32) && !defined(__BORLANDC__) # define LSEEK _lseeki64 #else #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define LSEEK lseek64 #else # define LSEEK lseek #endif #endif -/* Local functions */ -local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const void *, int, const char *)); - #if defined UNDER_CE /* Map the Windows error number in ERROR to a locale-dependent error message string and return a pointer to it. Typically, the values for ERROR come from GetLastError. @@ -28,13 +24,11 @@ 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; -{ +char ZLIB_INTERNAL *gz_strwinerror(DWORD error) { static char buf[1024]; wchar_t *msgbuf; DWORD lasterr = GetLastError(); DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM @@ -70,31 +64,27 @@ } #endif /* UNDER_CE */ /* Reset gzip file state */ -local void gz_reset(state) - gz_statep 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(path, fd, mode) - const void *path; - int fd; - const char *mode; -{ +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; @@ -265,30 +255,21 @@ /* return stream */ return (gzFile)state; } /* -- see zlib.h -- */ -gzFile ZEXPORT gzopen(path, mode) - const char *path; - const char *mode; -{ +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 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; -{ +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; @@ -302,23 +283,17 @@ return gz; } /* -- see zlib.h -- */ #ifdef WIDECHAR -gzFile ZEXPORT gzopen_w(path, mode) - const wchar_t *path; - const char *mode; -{ +gzFile ZEXPORT gzopen_w(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; -{ +int ZEXPORT gzbuffer(gzFile file, unsigned size) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; @@ -331,20 +306,18 @@ return -1; /* check and set requested size */ if ((size << 1) < size) return -1; /* need to be able to double it */ - if (size < 2) - size = 2; /* need two bytes to check magic header */ + if (size < 8) + size = 8; /* needed to behave well with flushing */ state->want = size; return 0; } /* -- see zlib.h -- */ -int ZEXPORT gzrewind(file) - gzFile file; -{ +int ZEXPORT gzrewind(gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; @@ -361,15 +334,11 @@ gz_reset(state); return 0; } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gzseek64(file, offset, whence) - gzFile file; - z_off64_t offset; - int whence; -{ +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 */ @@ -395,11 +364,11 @@ state->seek = 0; /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) { - ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); + ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); if (ret == -1) return -1; state->x.have = 0; state->eof = 0; state->past = 0; @@ -438,25 +407,19 @@ } 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_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(file) - gzFile file; -{ +z_off64_t ZEXPORT gztell64(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; @@ -467,23 +430,19 @@ /* return position */ return state->x.pos + (state->seek ? state->skip : 0); } /* -- see zlib.h -- */ -z_off_t ZEXPORT gztell(file) - gzFile file; -{ +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(file) - gzFile file; -{ +z_off64_t ZEXPORT gzoffset64(gzFile file) { z_off64_t offset; gz_statep state; /* get internal structure and check integrity */ if (file == NULL) @@ -500,23 +459,19 @@ offset -= state->strm.avail_in; /* don't count buffered input */ return offset; } /* -- see zlib.h -- */ -z_off_t ZEXPORT gzoffset(file) - gzFile file; -{ +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(file) - gzFile file; -{ +int ZEXPORT gzeof(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return 0; @@ -527,14 +482,11 @@ /* 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; -{ +const char * ZEXPORT gzerror(gzFile file, int *errnum) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return NULL; @@ -548,13 +500,11 @@ return state->err == Z_MEM_ERROR ? "out of memory" : (state->msg == NULL ? "" : state->msg); } /* -- see zlib.h -- */ -void ZEXPORT gzclearerr(file) - gzFile file; -{ +void ZEXPORT gzclearerr(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return; @@ -574,15 +524,11 @@ 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; -{ +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; @@ -620,12 +566,11 @@ #ifndef INT_MAX /* portably return maximum value for an int (when limits.h presumed not available) -- we need to do this to cover cases where 2's complement not used, since C standard permits 1's complement and sign-bit representations, otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned ZLIB_INTERNAL gz_intmax() -{ +unsigned ZLIB_INTERNAL gz_intmax(void) { unsigned p, q; p = 1; do { q = p; Index: compat/zlib/gzread.c ================================================================== --- compat/zlib/gzread.c +++ compat/zlib/gzread.c @@ -1,31 +1,18 @@ /* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" -/* Local functions */ -local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); -local int gz_avail OF((gz_statep)); -local int gz_look OF((gz_statep)); -local int gz_decomp OF((gz_statep)); -local int gz_fetch OF((gz_statep)); -local int gz_skip OF((gz_statep, z_off64_t)); -local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); - /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. This function needs to loop on read(), since read() is not guaranteed to read the number of bytes requested, depending on the type of descriptor. */ -local int gz_load(state, buf, len, have) - gz_statep state; - unsigned char *buf; - unsigned len; - unsigned *have; -{ +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 { @@ -51,13 +38,11 @@ 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; -{ +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; @@ -86,13 +71,11 @@ 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; -{ +local int gz_look(gz_statep state) { z_streamp strm = &(state->strm); /* allocate read buffers and inflate memory */ if (state->size == 0) { /* allocate buffers */ @@ -155,15 +138,13 @@ /* doing raw i/o, copy any leftover input to output -- this assumes that the output buffer is larger than the input buffer, which also assures space for gzungetc() */ state->x.next = state->out; - if (strm->avail_in) { - memcpy(state->x.next, strm->next_in, strm->avail_in); - state->x.have = strm->avail_in; - strm->avail_in = 0; - } + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; + strm->avail_in = 0; state->how = COPY; state->direct = 1; return 0; } @@ -170,13 +151,11 @@ /* 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; -{ +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 */ @@ -224,13 +203,11 @@ 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; -{ +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 */ @@ -254,14 +231,11 @@ } 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; -{ +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 */ @@ -289,15 +263,11 @@ /* 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; -{ +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) @@ -312,13 +282,13 @@ /* get len bytes to buf, or less than len if at the end */ got = 0; do { /* set n to the maximum amount of len that fits in an unsigned int */ - n = -1; + n = (unsigned)-1; if (n > len) - n = len; + n = (unsigned)len; /* first just try copying data from the output buffer */ if (state->x.have) { if (state->x.have < n) n = state->x.have; @@ -370,15 +340,11 @@ /* 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; -{ +int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; @@ -395,11 +361,11 @@ gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); return -1; } /* read len or fewer bytes to buf */ - len = gz_read(state, buf, len); + len = (unsigned)gz_read(state, buf, len); /* check for an error */ if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; @@ -406,16 +372,11 @@ /* 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 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) @@ -442,14 +403,11 @@ #ifdef Z_PREFIX_SET # undef z_gzgetc #else # undef gzgetc #endif -int ZEXPORT gzgetc(file) - gzFile file; -{ - int ret; +int ZEXPORT gzgetc(gzFile file) { unsigned char buf[1]; gz_statep state; /* get internal structure */ if (file == NULL) @@ -467,31 +425,29 @@ state->x.pos++; return *(state->x.next)++; } /* nothing there -- try gz_read() */ - ret = gz_read(state, buf, 1); - return ret < 1 ? -1 : buf[0]; + return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; } -int ZEXPORT gzgetc_(file) -gzFile file; -{ +int ZEXPORT gzgetc_(gzFile file) { return gzgetc(file); } /* -- see zlib.h -- */ -int ZEXPORT gzungetc(c, file) - int c; - gzFile file; -{ +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; @@ -538,15 +494,11 @@ state->past = 0; return c; } /* -- see zlib.h -- */ -char * ZEXPORT gzgets(file, buf, len) - gzFile file; - char *buf; - int len; -{ +char * ZEXPORT gzgets(gzFile file, char *buf, int len) { unsigned left, n; char *str; unsigned char *eol; gz_statep state; @@ -602,13 +554,11 @@ buf[0] = 0; return str; } /* -- see zlib.h -- */ -int ZEXPORT gzdirect(file) - gzFile file; -{ +int ZEXPORT gzdirect(gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return 0; @@ -622,13 +572,11 @@ /* return 1 if transparent, 0 if processing a gzip stream */ return state->direct; } /* -- see zlib.h -- */ -int ZEXPORT gzclose_r(file) - gzFile file; -{ +int ZEXPORT gzclose_r(gzFile file) { int ret, err; gz_statep state; /* get internal structure */ if (file == NULL) Index: compat/zlib/gzwrite.c ================================================================== --- compat/zlib/gzwrite.c +++ compat/zlib/gzwrite.c @@ -1,24 +1,16 @@ /* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004-2017 Mark Adler + * Copyright (C) 2004-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" -/* Local functions */ -local int gz_init OF((gz_statep)); -local int gz_comp OF((gz_statep, int)); -local int gz_zero OF((gz_statep, z_off64_t)); -local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); - /* Initialize state for writing a gzip file. Mark initialization by setting state->size to non-zero. Return -1 on a memory allocation failure, or 0 on success. */ -local int gz_init(state) - gz_statep state; -{ +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); @@ -68,14 +60,11 @@ 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; -{ +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 */ @@ -94,10 +83,19 @@ 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 @@ -132,22 +130,19 @@ have -= strm->avail_out; } while (have); /* if that completed a deflate stream, allow another to start */ if (flush == Z_FINISH) - deflateReset(strm); + state->reset = 1; /* all done, no errors */ return 0; } /* Compress len zeros to output. Return -1 on a write error or memory allocation failure by gz_comp(), or 0 on success. */ -local int gz_zero(state, len) - gz_statep state; - z_off64_t len; -{ +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 */ @@ -173,15 +168,11 @@ 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; -{ +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; @@ -207,11 +198,11 @@ state->strm.next_in = state->in; have = (unsigned)((state->strm.next_in + state->strm.avail_in) - state->in); copy = state->size - have; if (copy > len) - copy = len; + copy = (unsigned)len; memcpy(state->in + have, buf, copy); state->strm.avail_in += copy; state->x.pos += copy; buf = (const char *)buf + copy; len -= copy; @@ -227,11 +218,11 @@ /* directly compress user buffer to file */ state->strm.next_in = (z_const Bytef *)buf; do { unsigned n = (unsigned)-1; if (n > len) - n = len; + n = (unsigned)len; state->strm.avail_in = n; state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return 0; len -= n; @@ -241,15 +232,11 @@ /* input was all buffered or compressed */ return put; } /* -- see zlib.h -- */ -int ZEXPORT gzwrite(file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ +int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) { gz_statep state; /* get internal structure */ if (file == NULL) return 0; @@ -269,16 +256,12 @@ /* 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 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) @@ -299,14 +282,11 @@ /* 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; -{ +int ZEXPORT gzputc(gzFile file, int c) { unsigned have; unsigned char buf[1]; gz_statep state; z_streamp strm; @@ -347,16 +327,12 @@ return -1; return c & 0xff; } /* -- see zlib.h -- */ -int ZEXPORT gzputs(file, str) - gzFile file; - const char *str; -{ - int ret; - z_size_t len; +int ZEXPORT gzputs(gzFile file, const char *s) { + z_size_t len, put; gz_statep state; /* get internal structure */ if (file == NULL) return -1; @@ -365,21 +341,24 @@ /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return -1; /* write string */ - len = strlen(str); - ret = gz_write(state, str, len); - return ret == 0 && len != 0 ? -1 : ret; + len = strlen(s); + if ((int)len < 0 || (unsigned)len != len) { + gz_error(state, Z_STREAM_ERROR, "string length does not fit in int"); + return -1; + } + put = gz_write(state, s, len); + return put < len ? -1 : (int)len; } #if defined(STDC) || defined(Z_HAVE_STDARG_H) #include /* -- see zlib.h -- */ -int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) -{ +int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { int len; unsigned left; char *next; gz_statep state; z_streamp strm; @@ -439,19 +418,18 @@ if (strm->avail_in >= state->size) { left = strm->avail_in - state->size; strm->avail_in = state->size; if (gz_comp(state, Z_NO_FLUSH) == -1) return state->err; - memcpy(state->in, state->in + state->size, left); + memmove(state->in, state->in + state->size, left); strm->next_in = state->in; strm->avail_in = left; } return len; } -int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) -{ +int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) { va_list va; int ret; va_start(va, format); ret = gzvprintf(file, format, va); @@ -460,17 +438,14 @@ } #else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ -int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) - gzFile file; - const char *format; - int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; -{ +int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3, + int a4, int a5, int a6, int a7, int a8, int a9, int a10, + int a11, int a12, int a13, int a14, int a15, int a16, + int a17, int a18, int a19, int a20) { unsigned len, left; char *next; gz_statep state; z_streamp strm; @@ -538,24 +513,21 @@ if (strm->avail_in >= state->size) { left = strm->avail_in - state->size; strm->avail_in = state->size; if (gz_comp(state, Z_NO_FLUSH) == -1) return state->err; - memcpy(state->in, state->in + state->size, left); + memmove(state->in, state->in + state->size, left); strm->next_in = state->in; strm->avail_in = left; } return (int)len; } #endif /* -- see zlib.h -- */ -int ZEXPORT gzflush(file, flush) - gzFile file; - int flush; -{ +int ZEXPORT gzflush(gzFile file, int flush) { gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; @@ -580,15 +552,11 @@ (void)gz_comp(state, flush); return state->err; } /* -- see zlib.h -- */ -int ZEXPORT gzsetparams(file, level, strategy) - gzFile file; - int level; - int strategy; -{ +int ZEXPORT gzsetparams(gzFile file, int level, int strategy) { gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) @@ -595,11 +563,11 @@ return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) + if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct) return Z_STREAM_ERROR; /* if no change is requested, then do nothing */ if (level == state->level && strategy == state->strategy) return Z_OK; @@ -622,13 +590,11 @@ state->strategy = strategy; return Z_OK; } /* -- see zlib.h -- */ -int ZEXPORT gzclose_w(file) - gzFile file; -{ +int ZEXPORT gzclose_w(gzFile file) { int ret = Z_OK; gz_statep state; /* get internal structure */ if (file == NULL) Index: compat/zlib/infback.c ================================================================== --- compat/zlib/infback.c +++ compat/zlib/infback.c @@ -1,7 +1,7 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* This code is largely copied from inflate.c. Normally either infback.o or @@ -13,27 +13,20 @@ #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; -{ +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; @@ -64,10 +57,11 @@ 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 @@ -77,13 +71,11 @@ 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; -{ +local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; @@ -245,17 +237,12 @@ 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; -{ +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 */ @@ -475,10 +462,11 @@ 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(); @@ -602,39 +590,39 @@ } while (--copy); } while (state->length != 0); break; case DONE: - /* inflate stream terminated properly -- write leftover output */ + /* inflate stream terminated properly */ ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; - default: /* can't happen, but makes compilers happy */ + default: + /* can't happen, but makes compilers happy */ ret = Z_STREAM_ERROR; goto inf_leave; } - /* Return unused input */ + /* Write leftover output and return unused input */ inf_leave: + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left) && + ret == Z_STREAM_END) + ret = Z_BUF_ERROR; + } strm->next_in = next; strm->avail_in = have; return ret; } -int ZEXPORT inflateBackEnd(strm) -z_streamp strm; -{ +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; } Index: compat/zlib/inffast.c ================================================================== --- compat/zlib/inffast.c +++ compat/zlib/inffast.c @@ -45,14 +45,11 @@ - 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 */ -{ +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 */ @@ -68,11 +65,11 @@ unsigned bits; /* local strm->bits */ code const FAR *lcode; /* local strm->lencode */ code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ - code here; /* retrieved table entry */ + code const *here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char FAR *from; /* where to copy match from */ @@ -105,24 +102,24 @@ hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; } - here = lcode[hold & lmask]; + here = lcode + (hold & lmask); dolen: - op = (unsigned)(here.bits); + op = (unsigned)(here->bits); hold >>= op; bits -= op; - op = (unsigned)(here.op); + op = (unsigned)(here->op); if (op == 0) { /* literal */ - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - *out++ = (unsigned char)(here.val); + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); } else if (op & 16) { /* length base */ - len = (unsigned)(here.val); + len = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; @@ -136,18 +133,18 @@ hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; } - here = dcode[hold & dmask]; + here = dcode + (hold & dmask); dodist: - op = (unsigned)(here.bits); + op = (unsigned)(here->bits); hold >>= op; bits -= op; - op = (unsigned)(here.op); + op = (unsigned)(here->op); if (op & 16) { /* distance base */ - dist = (unsigned)(here.val); + dist = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { @@ -262,21 +259,21 @@ *out++ = *from++; } } } else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode[here.val + (hold & ((1U << op) - 1))]; + here = dcode + here->val + (hold & ((1U << op) - 1)); goto dodist; } else { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode[here.val + (hold & ((1U << op) - 1))]; + here = lcode + here->val + (hold & ((1U << op) - 1)); goto dolen; } else if (op & 32) { /* end-of-block */ Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; Index: compat/zlib/inffast.h ================================================================== --- compat/zlib/inffast.h +++ compat/zlib/inffast.h @@ -6,6 +6,6 @@ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ -void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); +void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start); Index: compat/zlib/inflate.c ================================================================== --- compat/zlib/inflate.c +++ compat/zlib/inflate.c @@ -1,7 +1,7 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * Change history: @@ -89,24 +89,11 @@ # 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; -{ +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; @@ -114,13 +101,11 @@ state->mode < HEAD || state->mode > SYNC) return 1; return 0; } -int ZEXPORT inflateResetKeep(strm) -z_streamp strm; -{ +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; @@ -128,10 +113,11 @@ 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; @@ -139,13 +125,11 @@ state->back = -1; Tracev((stderr, "inflate: reset\n")); return Z_OK; } -int ZEXPORT inflateReset(strm) -z_streamp strm; -{ +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; @@ -152,23 +136,22 @@ state->whave = 0; state->wnext = 0; return inflateResetKeep(strm); } -int ZEXPORT inflateReset2(strm, windowBits) -z_streamp strm; -int windowBits; -{ +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; @@ -190,16 +173,12 @@ 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 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))) @@ -234,26 +213,21 @@ strm->state = Z_NULL; } return ret; } -int ZEXPORT inflateInit_(strm, version, stream_size) -z_streamp strm; -const char *version; -int stream_size; -{ +int ZEXPORT inflateInit_(z_streamp strm, const char *version, + int stream_size) { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } -int ZEXPORT inflatePrime(strm, bits, value) -z_streamp strm; -int bits; -int value; -{ +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; @@ -273,13 +247,11 @@ 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; -{ +local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; @@ -337,11 +309,11 @@ Then that can be linked with zlib built with MAKEFIXED defined and run: a.out > inffixed.h */ -void makefixed() +void makefixed(void) { unsigned low, size; struct inflate_state state; fixedtables(&state); @@ -391,15 +363,11 @@ 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; -{ +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; @@ -445,14 +413,14 @@ /* Macros for inflate(): */ /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP -# define UPDATE(check, buf, len) \ +# define UPDATE_CHECK(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else -# define UPDATE(check, buf, len) adler32(check, buf, len) +# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ @@ -617,14 +585,11 @@ 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; -{ +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 */ @@ -668,11 +633,10 @@ 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 ( @@ -695,10 +659,11 @@ 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; @@ -720,18 +685,20 @@ 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); @@ -738,10 +705,11 @@ } 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) @@ -751,18 +719,20 @@ INITBITS(); } else if (state->head != Z_NULL) state->head->extra = Z_NULL; state->mode = EXTRA; + /* fallthrough */ case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; + state->head->extra != Z_NULL && + (len = state->head->extra_len - state->length) < + state->head->extra_max) { zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } if ((state->flags & 0x0200) && (state->wrap & 4)) @@ -773,10 +743,11 @@ } 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 { @@ -794,10 +765,11 @@ } 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 { @@ -814,10 +786,11 @@ 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"; @@ -837,19 +810,22 @@ 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; @@ -896,12 +872,14 @@ 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; @@ -933,10 +911,11 @@ } #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); @@ -954,10 +933,11 @@ 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; @@ -1037,12 +1017,14 @@ 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(); @@ -1088,10 +1070,11 @@ 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); @@ -1098,10 +1081,11 @@ 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(); @@ -1125,10 +1109,11 @@ 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); @@ -1141,10 +1126,11 @@ 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; @@ -1200,11 +1186,11 @@ out -= left; strm->total_out += out; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = - UPDATE(state->check, put - out, out); + UPDATE_CHECK(state->check, put - out, out); out = left; if ((state->wrap & 4) && ( #ifdef GUNZIP state->flags ? hold : #endif @@ -1216,32 +1202,35 @@ INITBITS(); Tracev((stderr, "inflate: check matches trailer\n")); } #ifdef GUNZIP state->mode = LENGTH; + /* fallthrough */ case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { + if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: length matches trailer\n")); } #endif state->mode = DONE; + /* fallthrough */ case DONE: ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; case MEM: return Z_MEM_ERROR; case SYNC: + /* fallthrough */ default: return Z_STREAM_ERROR; } /* @@ -1263,22 +1252,20 @@ strm->total_in += in; strm->total_out += out; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); + UPDATE_CHECK(state->check, strm->next_out - out, out); strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) ret = Z_BUF_ERROR; return ret; } -int ZEXPORT inflateEnd(strm) -z_streamp strm; -{ +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); @@ -1286,15 +1273,12 @@ 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; -{ +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; @@ -1309,15 +1293,12 @@ if (dictLength != Z_NULL) *dictLength = state->whave; return Z_OK; } -int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) -z_streamp strm; -const Bytef *dictionary; -uInt dictLength; -{ +int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, + uInt dictLength) { struct inflate_state FAR *state; unsigned long dictid; int ret; /* check state */ @@ -1344,14 +1325,11 @@ state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; } -int ZEXPORT inflateGetHeader(strm, head) -z_streamp strm; -gz_headerp head; -{ +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; @@ -1372,15 +1350,12 @@ 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; -{ +local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf, + unsigned len) { unsigned got; unsigned next; got = *have; next = 0; @@ -1395,14 +1370,13 @@ } *have = got; return next; } -int ZEXPORT inflateSync(strm) -z_streamp strm; -{ +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 */ @@ -1431,13 +1405,19 @@ 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; } /* @@ -1446,24 +1426,19 @@ 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; -{ +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(dest, source) -z_streamp dest; -z_streamp source; -{ +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; @@ -1503,14 +1478,11 @@ copy->window = window; dest->state = (struct internal_state FAR *)copy; return Z_OK; } -int ZEXPORT inflateUndermine(strm, subvert) -z_streamp strm; -int subvert; -{ +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 @@ -1521,28 +1493,23 @@ state->sane = 1; return Z_DATA_ERROR; #endif } -int ZEXPORT inflateValidate(strm, check) -z_streamp strm; -int check; -{ +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) + if (check && state->wrap) state->wrap |= 4; else state->wrap &= ~4; return Z_OK; } -long ZEXPORT inflateMark(strm) -z_streamp strm; -{ +long ZEXPORT inflateMark(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return -(1L << 16); state = (struct inflate_state FAR *)strm->state; @@ -1549,13 +1516,11 @@ 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; -{ +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); } Index: compat/zlib/inflate.h ================================================================== --- compat/zlib/inflate.h +++ compat/zlib/inflate.h @@ -1,7 +1,7 @@ /* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is @@ -84,11 +84,12 @@ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip, bit 2 true to validate check value */ int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags (0 if zlib) */ + int flags; /* gzip header method and flags, 0 if zlib, or + -1 if raw or no header yet */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ gz_headerp head; /* where to save gzip header information */ /* sliding window */ Index: compat/zlib/inftrees.c ================================================================== --- compat/zlib/inftrees.c +++ compat/zlib/inftrees.c @@ -1,17 +1,17 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2017 Mark Adler + * Copyright (C) 1995-2023 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.11 Copyright 1995-2017 Mark Adler "; + " inflate 1.3 Copyright 1995-2023 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. @@ -27,18 +27,13 @@ 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; -{ +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 */ @@ -60,11 +55,11 @@ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203}; 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 */ Index: compat/zlib/inftrees.h ================================================================== --- compat/zlib/inftrees.h +++ compat/zlib/inftrees.h @@ -36,11 +36,11 @@ */ /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that + examples/enough.c found in the zlib distribution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is @@ -55,8 +55,8 @@ CODES, LENS, DISTS } codetype; -int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); +int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work); Index: compat/zlib/make_vms.com ================================================================== --- compat/zlib/make_vms.com +++ compat/zlib/make_vms.com @@ -12,13 +12,13 @@ $! 0.01 20060120 First version to receive a number $! 0.02 20061008 Adapt to new Makefile.in $! 0.03 20091224 Add support for large file check $! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite $! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in -$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples +$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new examples $! subdir path, update module search in makefile.in -$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned +$! 0.07 20120115 Triggered by work done by Alexey Chupahin completely redesigned $! shared image creation $! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared $! image $! 0.09 20120305 SMS. P1 sets builder ("MMK", "MMS", " " (built-in)). $! "" -> automatic, preference: MMK, MMS, built-in. Index: compat/zlib/os400/README400 ================================================================== --- compat/zlib/os400/README400 +++ compat/zlib/os400/README400 @@ -1,11 +1,11 @@ - ZLIB version 1.2.11 for OS/400 installation instructions + ZLIB version 1.3.0 for OS/400 installation instructions 1) Download and unpack the zlib tarball to some IFS directory. (i.e.: /path/to/the/zlib/ifs/source/directory) - If the installed IFS command suppors gzip format, this is straightforward, + If the installed IFS command supports gzip format, this is straightforward, else you have to unpack first to some directory on a system supporting it, then move the whole directory to the IFS via the network (via SMB or FTP). 2) Edit the configuration parameters in the compilation script. @@ -41,8 +41,8 @@ C/C++ header files. Please read comments in this member for more information. Remember that most foreign textual data are ASCII coded: this implementation does not handle conversion from/to ASCII, so - text data code conversions must be done explicitely. + text data code conversions must be done explicitly. Mainly for the reason above, always open zipped files in binary mode. Index: compat/zlib/os400/bndsrc ================================================================== --- compat/zlib/os400/bndsrc +++ compat/zlib/os400/bndsrc @@ -113,7 +113,15 @@ 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 Index: compat/zlib/os400/zlib.inc ================================================================== --- compat/zlib/os400/zlib.inc +++ compat/zlib/os400/zlib.inc @@ -1,9 +1,9 @@ * ZLIB.INC - Interface to the general purpose compression library * * ILE RPG400 version by Patrick Monnerat, DATASPHERE. - * Version 1.2.11 + * Version 1.3.0 * * * WARNING: * Procedures inflateInit(), inflateInit2(), deflateInit(), * deflateInit2() and inflateBackInit() need to be called with @@ -20,16 +20,16 @@ * Constants ************************************************************************** * * Versioning information. * - D ZLIB_VERSION C '1.2.11' + D ZLIB_VERSION C '1.3.0' D ZLIB_VERNUM C X'12a0' D ZLIB_VER_MAJOR C 1 - D ZLIB_VER_MINOR C 2 + D ZLIB_VER_MINOR C 3 D ZLIB_VER_REVISION... - D C 11 + D C 0 D ZLIB_VER_SUBREVISION... D C 0 * * Other equates. * Index: compat/zlib/qnx/package.qpg ================================================================== --- compat/zlib/qnx/package.qpg +++ compat/zlib/qnx/package.qpg @@ -23,14 +23,14 @@ - - - - + + + + @@ -61,11 +61,11 @@ http://www.gzip.org/zlib - 1.2.11 + 1.3.0 Medium Stable Index: compat/zlib/test/example.c ================================================================== --- compat/zlib/test/example.c +++ compat/zlib/test/example.c @@ -31,42 +31,19 @@ * 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 *myalloc(void *q, unsigned n, unsigned m) { (void)q; return calloc(n, m); } -void myfree(void *q, void *p) -{ +void myfree(void *q, void *p) { (void)q; free(p); } static alloc_func zalloc = myalloc; @@ -75,22 +52,15 @@ #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; -{ +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"); @@ -109,15 +79,11 @@ } /* =========================================================================== * Test read/write of .gz files */ -void test_gzio(fname, uncompr, uncomprLen) - const char *fname; /* compressed file name */ - Byte *uncompr; - uLong uncomprLen; -{ +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; @@ -195,14 +161,11 @@ #endif /* Z_SOLO */ /* =========================================================================== * Test deflate() with small buffers */ -void test_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ +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; @@ -233,14 +196,12 @@ } /* =========================================================================== * Test inflate() with small buffers */ -void test_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr, + uLong uncomprLen) { int err; z_stream d_stream; /* decompression stream */ strcpy((char*)uncompr, "garbage"); @@ -274,14 +235,12 @@ } /* =========================================================================== * 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; -{ +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; @@ -306,11 +265,11 @@ } /* Feed in already compressed data and switch to no compression: */ deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); c_stream.next_in = compr; - c_stream.avail_in = (uInt)comprLen/2; + c_stream.avail_in = (uInt)uncomprLen/2; err = deflate(&c_stream, Z_NO_FLUSH); CHECK_ERR(err, "deflate"); /* Switch back to compressing mode: */ deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); @@ -329,14 +288,12 @@ } /* =========================================================================== * Test inflate() with large buffers */ -void test_large_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr, + uLong uncomprLen) { int err; z_stream d_stream; /* decompression stream */ strcpy((char*)uncompr, "garbage"); @@ -359,11 +316,11 @@ } err = inflateEnd(&d_stream); CHECK_ERR(err, "inflateEnd"); - if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + if (d_stream.total_out != 2*uncomprLen + uncomprLen/2) { fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); exit(1); } else { printf("large_inflate(): OK\n"); } @@ -370,14 +327,11 @@ } /* =========================================================================== * Test deflate() with full flush */ -void test_flush(compr, comprLen) - Byte *compr; - uLong *comprLen; -{ +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; @@ -408,14 +362,11 @@ } /* =========================================================================== * Test inflateSync() */ -void test_sync(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_sync(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) { int err; z_stream d_stream; /* decompression stream */ strcpy((char*)uncompr, "garbage"); @@ -438,13 +389,12 @@ 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 */ + if (err != Z_STREAM_END) { + fprintf(stderr, "inflate should report Z_STREAM_END\n"); exit(1); } err = inflateEnd(&d_stream); CHECK_ERR(err, "inflateEnd"); @@ -452,14 +402,11 @@ } /* =========================================================================== * Test deflate() with preset dictionary */ -void test_dict_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ +void test_dict_deflate(Byte *compr, uLong comprLen) { z_stream c_stream; /* compression stream */ int err; c_stream.zalloc = zalloc; c_stream.zfree = zfree; @@ -489,14 +436,12 @@ } /* =========================================================================== * Test inflate() with a preset dictionary */ -void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr, + uLong uncomprLen) { int err; z_stream d_stream; /* decompression stream */ strcpy((char*)uncompr, "garbage"); @@ -540,25 +485,23 @@ /* =========================================================================== * Usage: example [output.gz [input.gz]] */ -int main(argc, argv) - int argc; - char *argv[]; -{ +int main(int argc, char *argv[]) { Byte *compr, *uncompr; - uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - uLong uncomprLen = comprLen; + uLong uncomprLen = 20000; + uLong comprLen = 3 * uncomprLen; static const char* myVersion = ZLIB_VERSION; if (zlibVersion()[0] != myVersion[0]) { fprintf(stderr, "incompatible zlib version\n"); exit(1); } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { - fprintf(stderr, "warning: different zlib version\n"); + fprintf(stderr, "warning: different zlib version linked: %s\n", + zlibVersion()); } printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); @@ -588,15 +531,15 @@ test_large_deflate(compr, comprLen, uncompr, uncomprLen); test_large_inflate(compr, comprLen, uncompr, uncomprLen); test_flush(compr, &comprLen); test_sync(compr, comprLen, uncompr, uncomprLen); - comprLen = uncomprLen; + comprLen = 3 * uncomprLen; test_dict_deflate(compr, comprLen); test_dict_inflate(compr, comprLen, uncompr, uncomprLen); free(compr); free(uncompr); return 0; } Index: compat/zlib/test/infcover.c ================================================================== --- compat/zlib/test/infcover.c +++ compat/zlib/test/infcover.c @@ -371,11 +371,11 @@ inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); mem_setup(&strm); strm.avail_in = 0; strm.next_in = Z_NULL; - ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); + ret = inflateInit_(&strm, "!", (int)sizeof(z_stream)); assert(ret == Z_VERSION_ERROR); mem_done(&strm, "wrong version"); strm.avail_in = 0; strm.next_in = Z_NULL; @@ -460,11 +460,12 @@ return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; } local int push(void *desc, unsigned char *buf, unsigned len) { - buf += 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) Index: compat/zlib/test/minigzip.c ================================================================== --- compat/zlib/test/minigzip.c +++ compat/zlib/test/minigzip.c @@ -57,11 +57,11 @@ # include /* for fileno */ #endif #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) #ifndef WIN32 /* unlink already in stdio.h for WIN32 */ - extern int unlink OF((const char *)); + extern int unlink(const char *); #endif #endif #if defined(UNDER_CE) # include @@ -147,24 +147,16 @@ #if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) # include /* 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 *myalloc(void *q, unsigned n, unsigned m) { (void)q; return calloc(n, m); } -void myfree(q, p) - void *q, *p; -{ +void myfree(void *q, void *p) { (void)q; free(p); } typedef struct gzFile_s { @@ -173,33 +165,11 @@ 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_open(const char *path, int fd, const char *mode) { gzFile gz; int ret; gz = malloc(sizeof(struct gzFile_s)); if (gz == NULL) @@ -229,17 +199,19 @@ gz->err = 0; gz->msg = ""; return gz; } -int gzwrite OF((gzFile, const void *, unsigned)); +gzFile gzopen(const char *path, const char *mode) { + return gz_open(path, -1, mode); +} + +gzFile gzdopen(int fd, const char *mode) { + return gz_open(NULL, fd, mode); +} -int gzwrite(gz, buf, len) - gzFile gz; - const void *buf; - unsigned len; -{ +int gzwrite(gzFile gz, const void *buf, unsigned len) { z_stream *strm; unsigned char out[BUFLEN]; if (gz == NULL || !gz->write) return 0; @@ -253,17 +225,11 @@ 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 gzread(gzFile gz, void *buf, unsigned len) { int ret; unsigned got; unsigned char in[1]; z_stream *strm; @@ -290,15 +256,11 @@ inflateReset(strm); } while (strm->avail_out); return len - strm->avail_out; } -int gzclose OF((gzFile)); - -int gzclose(gz) - gzFile gz; -{ +int gzclose(gzFile gz) { z_stream *strm; unsigned char out[BUFLEN]; if (gz == NULL) return Z_STREAM_ERROR; @@ -319,85 +281,33 @@ fclose(gz->file); free(gz); return Z_OK; } -const char *gzerror OF((gzFile, int *)); - -const char *gzerror(gz, err) - gzFile gz; - int *err; -{ +const char *gzerror(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; -{ +void error(const char *msg) { fprintf(stderr, "%s: %s\n", prog, msg); exit(1); } -/* =========================================================================== - * Compress input to output then close both files. - */ - -void gz_compress(in, out) - FILE *in; - gzFile out; -{ - local char buf[BUFLEN]; - int len; - int err; - -#ifdef USE_MMAP - /* Try first compressing with mmap. If mmap fails (minigzip used in a - * pipe), use the normal fread loop. - */ - if (gz_compress_mmap(in, out) == Z_OK) return; -#endif - for (;;) { - len = (int)fread(buf, 1, sizeof(buf), in); - if (ferror(in)) { - perror("fread"); - exit(1); - } - if (len == 0) break; - - if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); - } - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); -} - #ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ /* 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 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 */ @@ -421,18 +331,44 @@ fclose(in); if (gzclose(out) != Z_OK) error("failed gzclose"); return Z_OK; } #endif /* USE_MMAP */ + +/* =========================================================================== + * Compress input to output then close both files. + */ + +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. */ -void gz_uncompress(in, out) - gzFile in; - FILE *out; -{ +void gz_uncompress(gzFile in, FILE *out) { local char buf[BUFLEN]; int len; int err; for (;;) { @@ -452,14 +388,11 @@ /* =========================================================================== * Compress the given file: create a corresponding .gz file and remove the * original. */ -void file_compress(file, mode) - char *file; - char *mode; -{ +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)) { @@ -491,18 +424,16 @@ /* =========================================================================== * Uncompress the given file and remove the original. */ -void file_uncompress(file) - char *file; -{ +void file_uncompress(char *file) { local char buf[MAX_NAME_LEN]; char *infile, *outfile; FILE *out; gzFile in; - unsigned len = strlen(file); + z_size_t len = strlen(file); if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { fprintf(stderr, "%s: filename too long\n", prog); exit(1); } @@ -551,14 +482,11 @@ * -h : compress with Z_HUFFMAN_ONLY * -r : compress with Z_RLE * -1 to -9 : compression level */ -int main(argc, argv) - int argc; - char *argv[]; -{ +int main(int argc, char *argv[]) { int copyout = 0; int uncompr = 0; gzFile file; char *bname, outmode[20]; Index: compat/zlib/treebuild.xml ================================================================== --- compat/zlib/treebuild.xml +++ compat/zlib/treebuild.xml @@ -1,8 +1,8 @@ - - + + zip compression library Index: compat/zlib/trees.c ================================================================== --- compat/zlib/trees.c +++ compat/zlib/trees.c @@ -1,7 +1,7 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2017 Jean-loup Gailly + * Copyright (C) 1995-2021 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 */ /* @@ -120,43 +120,120 @@ 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 = +#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 const static_tree_desc static_d_desc = +local TCONST static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; -local const static_tree_desc static_bl_desc = +local TCONST static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== - * Local (static) routines in this file. + * 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 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)); +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 OF((void)); +local void gen_trees_header(void); #endif #ifndef ZLIB_DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ @@ -165,37 +242,22 @@ # 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 */ -{ +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)) + * (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); @@ -227,12 +289,11 @@ /* the arguments must not have side effects */ /* =========================================================================== * Initialize the various 'constant' tables. */ -local void tr_static_init() -{ +local void tr_static_init(void) { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ @@ -254,38 +315,38 @@ /* 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< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { _dist_code[256 + dist++] = (uch)code; } } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); + Assert (dist == 256, "tr_static_init: 256 + dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; @@ -310,23 +371,22 @@ # endif #endif /* defined(GEN_TREES_H) || !defined(STDC) */ } /* =========================================================================== - * Genererate the file trees.h describing the static trees. + * Generate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef ZLIB_DEBUG # include # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) + ((i) % (width) == (width) - 1 ? ",\n" : ", ")) -void gen_trees_header() -{ +void gen_trees_header(void) { FILE *header = fopen("trees.h", "w"); int i; Assert (header != NULL, "Can't open trees.h"); fprintf(header, @@ -370,17 +430,31 @@ } fclose(header); } #endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(deflate_state *s) { + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->sym_next = s->matches = 0; +} /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ -void ZLIB_INTERNAL _tr_init(s) - deflate_state *s; -{ +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; @@ -399,28 +473,10 @@ /* 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 */ /* =========================================================================== @@ -446,21 +502,17 @@ * 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 */ -{ +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)) { + 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; @@ -481,14 +533,11 @@ * 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 */ -{ +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; @@ -505,11 +554,11 @@ /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + for (h = s->heap_max + 1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].Len = (ush)bits; /* We overwrite tree[n].Dad which is no longer needed */ @@ -516,11 +565,11 @@ if (n > max_code) continue; /* not a leaf node */ s->bl_count[bits]++; xbits = 0; - if (n >= base) xbits = extra[n-base]; + if (n >= base) xbits = extra[n - base]; f = tree[n].Freq; s->opt_len += (ulg)f * (unsigned)(bits + xbits); if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); } if (overflow == 0) return; @@ -528,14 +577,14 @@ Tracev((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { - bits = max_length-1; + bits = max_length - 1; while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; @@ -559,74 +608,32 @@ 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< +#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(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ +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[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++) { @@ -650,11 +657,11 @@ s->opt_len--; if (stree) s->static_len -= stree[node].Len; /* node is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); /* Construct the Huffman tree by repeatedly combining the least two @@ -698,28 +705,24 @@ /* =========================================================================== * 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 */ -{ +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 */ + tree[max_code + 1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { s->bl_tree[curlen].Freq += count; } else if (curlen != 0) { @@ -743,28 +746,24 @@ /* =========================================================================== * 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 */ -{ +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 */ + /* tree[max_code + 1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(s, curlen, s->bl_tree); } while (--count != 0); @@ -771,17 +770,17 @@ } else if (curlen != 0) { if (curlen != prevlen) { send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2); } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3); } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { @@ -794,23 +793,21 @@ /* =========================================================================== * 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; -{ +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. + /* 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.) @@ -817,11 +814,11 @@ */ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; + s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); return max_blindex; } @@ -829,93 +826,167 @@ /* =========================================================================== * 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 */ -{ +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 */ + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } /* =========================================================================== * Send a stored block */ -void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) - 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 */ +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); - zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, 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; + 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; -{ +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(s) - deflate_state *s; -{ +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 sym_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->sym_next != 0) do { + dist = s->sym_buf[sx++] & 0xff; + dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; + lc = s->sym_buf[sx++]; + 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 that the overlay between pending_buf and sym_buf is ok: */ + Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); + + } while (sx < s->sym_next); + + send_code(s, END_BLOCK, ltree); +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "block list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(deflate_state *s) { + /* block_mask is the bit mask of block-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long block_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("block-listed") bytes. */ + for (n = 0; n <= 31; n++, block_mask >>= 1) + if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("allow-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "block-listed" or "allow-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and write out the encoded block. */ -void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) - 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 */ -{ +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) { @@ -940,28 +1011,31 @@ * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; + opt_lenb = (s->opt_len + 3 + 7) >> 3; + static_lenb = (s->static_len + 3 + 7) >> 3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); + s->sym_next / 3)); - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; +#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) { + 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 @@ -968,25 +1042,21 @@ * 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); + } 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); + 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 @@ -1001,25 +1071,22 @@ bi_windup(s); #ifdef ZLIB_DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*last)); + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3, + s->compressed_len - 7*last)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ -int ZLIB_INTERNAL _tr_tally (s, dist, lc) - deflate_state *s; - 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; +int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) { + 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; if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; } else { s->matches++; @@ -1027,177 +1094,10 @@ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST(s) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } - -#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 + return (s->sym_next == s->sym_end); } Index: compat/zlib/uncompr.c ================================================================== --- compat/zlib/uncompr.c +++ compat/zlib/uncompr.c @@ -22,16 +22,12 @@ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted, including if the input data is an incomplete zlib stream. */ -int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong *sourceLen; -{ +int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong *sourceLen) { z_stream stream; int err; const uInt max = (uInt)-1; uLong len, left; Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */ @@ -81,13 +77,9 @@ err == Z_NEED_DICT ? Z_DATA_ERROR : err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : err; } -int ZEXPORT uncompress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ +int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen) { return uncompress2(dest, destLen, source, &sourceLen); } Index: compat/zlib/win32/Makefile.bor ================================================================== --- compat/zlib/win32/Makefile.bor +++ compat/zlib/win32/Makefile.bor @@ -1,11 +1,10 @@ # 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 Index: compat/zlib/win32/Makefile.gcc ================================================================== --- compat/zlib/win32/Makefile.gcc +++ compat/zlib/win32/Makefile.gcc @@ -9,14 +9,10 @@ # 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. @@ -36,11 +32,10 @@ # # 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 Index: compat/zlib/win32/Makefile.msc ================================================================== --- compat/zlib/win32/Makefile.msc +++ compat/zlib/win32/Makefile.msc @@ -2,14 +2,10 @@ # 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 = . Index: compat/zlib/win32/README-WIN32.txt ================================================================== --- compat/zlib/win32/README-WIN32.txt +++ compat/zlib/win32/README-WIN32.txt @@ -1,8 +1,8 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.11 is a general purpose data compression library. All the code is +zlib 1.3.0 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). @@ -20,11 +20,11 @@ before asking for help. Manifest: -The package zlib-1.2.11-win32-x86.zip will contain the following files: +The package zlib-1.3.0-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 Index: compat/zlib/win32/README.txt ================================================================== --- compat/zlib/win32/README.txt +++ compat/zlib/win32/README.txt @@ -4,11 +4,11 @@ The official ZLIB1.DLL Source ====== - zlib version 1.2.11 + zlib version 1.3.0 available at http://www.gzip.org/zlib/ Specification and rationale =========================== Index: compat/zlib/win32/zdll.lib ================================================================== --- compat/zlib/win32/zdll.lib +++ compat/zlib/win32/zdll.lib cannot compute difference between binary files Index: compat/zlib/win32/zlib.def ================================================================== --- compat/zlib/win32/zlib.def +++ compat/zlib/win32/zlib.def @@ -67,17 +67,20 @@ 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_ Index: compat/zlib/win32/zlib1.dll ================================================================== --- compat/zlib/win32/zlib1.dll +++ compat/zlib/win32/zlib1.dll cannot compute difference between binary files Index: compat/zlib/win32/zlib1.rc ================================================================== --- compat/zlib/win32/zlib1.rc +++ compat/zlib/win32/zlib1.rc @@ -24,11 +24,11 @@ //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression library\0" VALUE "FileVersion", ZLIB_VERSION "\0" VALUE "InternalName", "zlib1.dll\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2022 Jean-loup Gailly & Mark Adler\0" VALUE "OriginalFilename", "zlib1.dll\0" VALUE "ProductName", "zlib\0" VALUE "ProductVersion", ZLIB_VERSION "\0" VALUE "Comments", "For more information visit http://www.zlib.net/\0" END ADDED compat/zlib/win64-arm/libz.dll.a Index: compat/zlib/win64-arm/libz.dll.a ================================================================== --- /dev/null +++ compat/zlib/win64-arm/libz.dll.a cannot compute difference between binary files ADDED compat/zlib/win64-arm/zdll.lib Index: compat/zlib/win64-arm/zdll.lib ================================================================== --- /dev/null +++ compat/zlib/win64-arm/zdll.lib cannot compute difference between binary files ADDED compat/zlib/win64-arm/zlib1.dll Index: compat/zlib/win64-arm/zlib1.dll ================================================================== --- /dev/null +++ compat/zlib/win64-arm/zlib1.dll cannot compute difference between binary files Index: compat/zlib/win64/libz.dll.a ================================================================== --- compat/zlib/win64/libz.dll.a +++ compat/zlib/win64/libz.dll.a cannot compute difference between binary files Index: compat/zlib/win64/zdll.lib ================================================================== --- compat/zlib/win64/zdll.lib +++ compat/zlib/win64/zdll.lib cannot compute difference between binary files Index: compat/zlib/win64/zlib1.dll ================================================================== --- compat/zlib/win64/zlib1.dll +++ compat/zlib/win64/zlib1.dll cannot compute difference between binary files Index: compat/zlib/zconf.h ================================================================== --- compat/zlib/zconf.h +++ compat/zlib/zconf.h @@ -36,10 +36,13 @@ # 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 @@ -236,11 +239,15 @@ #else # define z_const #endif #ifdef Z_SOLO - typedef unsigned long z_size_t; +# 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) @@ -347,10 +354,13 @@ */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 @@ -465,15 +475,22 @@ */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif #endif #ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t @@ -505,11 +522,11 @@ #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# if defined(_WIN32) && !defined(__GNUC__) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif Index: compat/zlib/zconf.h.cmakein ================================================================== --- compat/zlib/zconf.h.cmakein +++ compat/zlib/zconf.h.cmakein @@ -38,10 +38,13 @@ # 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 @@ -238,11 +241,15 @@ #else # define z_const #endif #ifdef Z_SOLO - typedef unsigned long z_size_t; +# 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) @@ -349,10 +356,13 @@ */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 @@ -467,15 +477,22 @@ */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif #endif #ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t @@ -507,11 +524,11 @@ #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# if defined(_WIN32) && !defined(__GNUC__) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif Index: compat/zlib/zconf.h.in ================================================================== --- compat/zlib/zconf.h.in +++ compat/zlib/zconf.h.in @@ -36,10 +36,13 @@ # 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 @@ -236,11 +239,15 @@ #else # define z_const #endif #ifdef Z_SOLO - typedef unsigned long z_size_t; +# 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) @@ -347,10 +354,13 @@ */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 @@ -465,15 +475,22 @@ */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif #endif #ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t @@ -505,11 +522,11 @@ #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# if defined(_WIN32) && !defined(__GNUC__) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif Index: compat/zlib/zlib.3 ================================================================== --- compat/zlib/zlib.3 +++ compat/zlib/zlib.3 @@ -1,6 +1,6 @@ -.TH ZLIB 3 "15 Jan 2017" +.TH ZLIB 3 "18 Aug 2023" .SH NAME zlib \- compression/decompression library .SH SYNOPSIS [see .I zlib.h @@ -103,13 +103,13 @@ .LP before asking for help. Send questions and/or comments to zlib@gzip.org, or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). .SH AUTHORS AND LICENSE -Version 1.2.11 +Version 1.3 .LP -Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler +Copyright (C) 1995-2023 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 Index: compat/zlib/zlib.3.pdf ================================================================== --- compat/zlib/zlib.3.pdf +++ compat/zlib/zlib.3.pdf cannot compute difference between binary files Index: compat/zlib/zlib.h ================================================================== --- compat/zlib/zlib.h +++ compat/zlib/zlib.h @@ -1,9 +1,9 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.11, January 15th, 2017 + version 1.3, August 18th, 2023 - Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2023 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. @@ -35,15 +35,15 @@ #ifdef __cplusplus extern "C" { #endif -#define ZLIB_VERSION "1.2.11" -#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VERSION "1.3" +#define ZLIB_VERNUM 0x1300 #define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 0 #define ZLIB_VER_SUBREVISION 0 /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. @@ -76,12 +76,12 @@ The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in the case of corrupted input. */ -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); +typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); +typedef void (*free_func)(voidpf opaque, voidpf address); struct internal_state; typedef struct z_stream_s { z_const Bytef *next_in; /* next input byte */ @@ -215,24 +215,24 @@ /* for compatibility with versions < 1.0.2 */ /* basic functions */ -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +ZEXTERN const char * ZEXPORT zlibVersion(void); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); +ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. + allocation functions. total_in, total_out, adler, and msg are initialized. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently @@ -245,11 +245,11 @@ if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. @@ -274,11 +274,11 @@ never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. See deflatePending(), - which can be used if desired to determine whether or not there is more ouput + which can be used if desired to determine whether or not there is more output in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to maximize compression. @@ -318,12 +318,12 @@ If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this function must be called again with Z_FINISH and more output space (updated @@ -358,11 +358,11 @@ deflate() can be called again with more input and more output space to continue compressing. */ -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. @@ -373,19 +373,20 @@ deallocated). */ /* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateInit(z_streamp strm); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. In the current version of inflate, the provided input is not read or consumed. The allocation of a sliding window will be deferred to the first call of inflate (if the decompression does not complete on the first call). If zalloc and zfree are set to Z_NULL, inflateInit updates - them to use default allocation functions. + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if @@ -395,11 +396,11 @@ implementation of inflateInit() does not process any header information -- that is deferred until inflate() is called. */ -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. @@ -515,11 +516,11 @@ then call inflateSync() to look for a good compression block if a partial recovery of the data is to be attempted. */ -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. @@ -533,20 +534,19 @@ /* The following functions are needed only in some special applications. */ /* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); +ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by the - caller. + 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 @@ -606,13 +606,13 @@ incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); +ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. When using the zlib format, this function must be called immediately after deflateInit, deflateInit2 or deflateReset, and before any call of deflate. When doing raw deflate, this @@ -650,20 +650,20 @@ inconsistent (for example if deflate has already been called for this stream or if not at a block boundary for raw deflate). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ -ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); +ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); /* Returns the sliding dictionary being maintained by deflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If deflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. + Similarly, if dictLength is Z_NULL, then it is not set. deflateGetDictionary() may return a length less than the window size, even when more than the window size in input has been provided. It may return up to 258 bytes less in that case, due to how zlib's implementation of deflate manages the sliding window and lookahead for matches, where matches can be @@ -672,12 +672,12 @@ deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); +ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, + z_streamp source); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input @@ -690,35 +690,36 @@ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +ZEXTERN int ZEXPORT deflateReset(z_streamp strm); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate the internal compression state. The stream will leave the compression level and any other attributes that may have been - set unchanged. + set unchanged. total_in, total_out, adler, and msg are initialized. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); +ZEXTERN int ZEXPORT deflateParams(z_streamp strm, + int level, + int strategy); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression approach (which is a function of the level) or the - strategy is changed, and if any input has been consumed in a previous - deflate() call, then the input available so far is compressed with the old - level and strategy using deflate(strm, Z_BLOCK). There are three approaches - for the compression levels 0, 1..3, and 4..9 respectively. The new level - and strategy will take effect at the next call of deflate(). + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does not have enough output space to complete, then the parameter change will not take effect. In this case, deflateParams() can be called again with the same parameters and more output space to try again. @@ -727,11 +728,11 @@ deflate stream should be flushed using deflate() with Z_BLOCK or other flush request until strm.avail_out is not zero, before calling deflateParams(). Then no more input data should be provided before the deflateParams() call. If this is done, the old level and strategy will be applied to the data compressed before deflateParams(), and the new level and strategy will be - applied to the the data compressed after deflateParams(). + applied to the data compressed after deflateParams(). deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if there was not enough output space to complete the compression of the available input data before a change in the strategy or approach. Note that @@ -738,15 +739,15 @@ in the case of a Z_BUF_ERROR, the parameters are not changed. A return value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be retried with more output space. */ -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); +ZEXTERN int ZEXPORT deflateTune(z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their @@ -755,12 +756,12 @@ deflateTune() can be called after deflateInit() or deflateInit2(), and returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); +ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, + uLong sourceLen); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be @@ -770,13 +771,13 @@ to return Z_STREAM_END. Note that it is possible for the compressed size to be larger than the value returned by deflateBound() if flush options other than Z_FINISH or Z_NO_FLUSH are used. */ -ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, - unsigned *pending, - int *bits)); +ZEXTERN int ZEXPORT deflatePending(z_streamp strm, + unsigned *pending, + int *bits); /* deflatePending() returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not provided would be due to the available output space having being consumed. The number of bits of output not provided are between 0 and 7, where they @@ -785,13 +786,13 @@ deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); +ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, + int bits, + int value); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first @@ -802,12 +803,12 @@ deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the source stream state was inconsistent. */ -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); +ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, + gz_headerp head); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called after deflateInit2() or deflateReset() and before the first call of deflate(). The text, time, os, extra field, name, and comment information @@ -819,20 +820,21 @@ the current versions of the command-line version of gzip (up through version 1.3.x) do not support header crc's, and will report that it is a "multi-part gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); +ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, + int windowBits); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. @@ -863,13 +865,15 @@ windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see - below), inflate() will not automatically decode concatenated gzip streams. - inflate() will return Z_STREAM_END at the end of the gzip stream. The state - would need to be reset to continue decoding a subsequent gzip stream. + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if @@ -879,13 +883,13 @@ next_out and avail_out are unused and unchanged.) The current implementation of inflateInit2() does not process any header information -- that is deferred until inflate() is called. */ -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); +ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the Adler-32 value returned by that call of inflate. @@ -902,26 +906,26 @@ expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ -ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); +ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); /* Returns the sliding dictionary being maintained by inflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. + Similarly, if dictLength is Z_NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateSync(z_streamp strm); /* Skips invalid compressed data until a possible full flush point (see above for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. @@ -936,12 +940,12 @@ total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); +ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, + z_streamp source); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when randomly accessing a large stream. The first pass through the stream can periodically record the inflate state, @@ -952,22 +956,23 @@ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateReset(z_streamp strm); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); +ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, + int windowBits); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted the same as it is for inflateInit2. If the window size is changed, then the memory allocated for the window is freed, and the window will be reallocated @@ -976,13 +981,13 @@ inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if the windowBits parameter is invalid. */ -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); +ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, + int bits, + int value); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the middle of a byte. The provided bits will be used before any bytes are used from next_in. This function should only be used with raw inflate, and @@ -997,11 +1002,11 @@ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +ZEXTERN long ZEXPORT inflateMark(z_streamp strm); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the return value down 16 bits. If the upper value is -1 and the lower value is zero, then inflate() is currently decoding information outside of a block. @@ -1025,12 +1030,12 @@ inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); +ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, + gz_headerp head); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after inflateInit2() or inflateReset(), and before the first call of inflate(). As inflate() processes the gzip stream, head->done is zero until the header @@ -1066,12 +1071,12 @@ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); +ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, + unsigned char FAR *window); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are Z_NULL, then the default library- derived memory allocation routines are used. windowBits is the base two @@ -1087,17 +1092,17 @@ the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ -typedef unsigned (*in_func) OF((void FAR *, - z_const unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); +typedef unsigned (*in_func)(void FAR *, + z_const unsigned char FAR * FAR *); +typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); +ZEXTERN int ZEXPORT inflateBack(z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is potentially more efficient than inflate() for file i/o applications, in that it avoids copying between the output and the sliding window by simply making the window itself the output @@ -1161,19 +1166,19 @@ non-zero. (in() will always be called before out(), so strm->next_in is assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); /* All memory allocated by inflateBackInit() is freed. inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream state was inconsistent. */ -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +ZEXTERN uLong ZEXPORT zlibCompileFlags(void); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: 1.0: size of uInt 3.2: size of uLong @@ -1222,12 +1227,12 @@ are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can be modified if you need special options. */ -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); +ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the @@ -1237,13 +1242,13 @@ compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); +ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by @@ -1253,19 +1258,19 @@ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); +ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved @@ -1278,12 +1283,12 @@ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In the case where there is not enough room, uncompress() will fill the output buffer with the uncompressed data up to that point. */ -ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong *sourceLen)); +ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); /* Same as uncompress, except that sourceLen is a pointer, where the length of the source is *sourceLen. On return, *sourceLen is the number of source bytes consumed. */ @@ -1298,20 +1303,20 @@ */ 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. +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 @@ -1335,15 +1340,15 @@ specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). errno can be checked to determine if the reason gzopen failed was that the file could not be opened. */ -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); /* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since @@ -1358,40 +1363,40 @@ provided, or '+' was provided), or if fd is -1. The file descriptor is not used until the next gz* read, write, seek, or close operation, so gzdopen will not detect if fd is invalid (unless fd is -1). */ -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); /* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Three times that size in buffer space is allocated. A larger buffer - size of, for example, 64K or 128K bytes will noticeably increase the speed - of decompression (reading). + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). gzbuffer() returns 0 on success, or -1 on failure, such as being called too late. */ -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); /* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. Previously provided - data is flushed before the parameter change. + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not opened for writing, Z_ERRNO if there is an error writing the flushed data, or Z_MEM_ERROR if there is a memory allocation error. */ -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); /* - Reads the given number of uncompressed bytes from the compressed file. If + Read and decompress up to len uncompressed bytes from file into buf. If the input file is not in gzip format, gzread copies the given number of bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue to read, looking for another gzip stream. Any number of gzip streams may be @@ -1415,18 +1420,18 @@ len for end of file, or -1 for error. If len is too large to fit in an int, then nothing is read, -1 is returned, and the error state is set to Z_STREAM_ERROR. */ -ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, - gzFile file)); +ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file); /* - Read up to nitems items of size size from file to buf, otherwise operating - as gzread() does. This duplicates the interface of stdio's fread(), with - size_t request and return types. If the library defines size_t, then - z_size_t is identical to size_t. If not, then z_size_t is an unsigned - integer type that can contain a pointer. + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. gzfread() returns the number of full items read of size size, or zero if the end of the file was reached and a full item could not be read, or if there was an error. gzerror() must be consulted if zero is returned in order to determine if there was an error. If the multiplication of size and @@ -1433,30 +1438,28 @@ nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is read, zero is returned, and the error state is set to Z_STREAM_ERROR. In the event that the end of file is reached and only a partial item is available at the end, i.e. the remaining uncompressed data length is not a - multiple of size, then the final partial item is nevetheless read into buf + multiple of size, then the final partial item is nevertheless read into buf and the end-of-file flag is set. The length of the partial item read is not provided, but could be inferred from the result of gztell(). This behavior is the same as the behavior of fread() implementations in common libraries, but it prevents the direct use of gzfread() to read a concurrently written - file, reseting and retrying on end-of-file, when size is not 1. -*/ - -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 + 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 @@ -1463,78 +1466,79 @@ if there was an error. If the multiplication of size and nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is written, zero is returned, and the error state is set to Z_STREAM_ERROR. */ -ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); /* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of uncompressed bytes actually written, or a negative zlib error code in case of error. The number of uncompressed bytes written is limited to 8191, or one less than the buffer size given to gzbuffer(). The caller should assure that this limit is not exceeded. If it is exceeded, then gzprintf() will return an error (0) with nothing written. In this case, there may also be a buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() + zlib was compiled with the insecure functions sprintf() or vsprintf(), because the secure snprintf() or vsnprintf() functions were not available. This can be determined using zlibCompileFlags(). */ -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); /* - Writes the given null-terminated string to the compressed file, excluding + Compress and write the given null-terminated string s to file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); /* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. gzgets returns buf which is a null-terminated string, or it returns NULL for end-of-file or in case of error. If there was an error, the contents at buf are indeterminate. */ -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +ZEXTERN int ZEXPORT gzputc(gzFile file, int c); /* - Writes c, converted to an unsigned char, into the compressed file. gzputc + Compress and write c, converted to an unsigned char, into file. gzputc returns the value that was written, or -1 in case of error. */ -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +ZEXTERN int ZEXPORT gzgetc(gzFile file); /* - Reads one byte from the compressed file. gzgetc returns this byte or -1 + Read and decompress one byte from file. gzgetc returns this byte or -1 in case of end of file or error. This is implemented as a macro for speed. As such, it does not do all of the checking the other functions do. I.e. it does not check to see if file is NULL, nor whether the structure file points to has been clobbered or not. */ -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); /* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if c is -1, and may fail if a character has been pushed but not read yet. If gzungetc is used immediately after gzopen or gzdopen, at least the output buffer size of pushed characters is allowed. (See gzbuffer above.) The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). */ -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); /* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such concatenated gzip streams. @@ -1542,15 +1546,15 @@ gzflush should be called only when strictly necessary because it will degrade compression if called too often. */ /* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); +ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, + z_off_t offset, int whence); - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are @@ -1561,56 +1565,56 @@ the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +ZEXTERN int ZEXPORT gzrewind(gzFile file); /* - Rewinds the given file. This function is supported only for reading. + Rewind file. This function is supported only for reading. - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). */ /* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +ZEXTERN z_off_t ZEXPORT gztell(gzFile file); - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); +ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. */ -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +ZEXTERN int ZEXPORT gzeof(gzFile file); /* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. If gzeof() returns true, then the read functions will return no more data, unless the end-of-file indicator is reset by gzclearerr() and the input file has grown since the previous end of file was detected. */ -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +ZEXTERN int ZEXPORT gzdirect(gzFile file); /* - Returns true (1) if file is being copied directly while reading, or false + Return true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. @@ -1625,25 +1629,25 @@ explicitly requested, so the application already knows the answer. When linking statically, using gzdirect() will include all of the zlib code for gzip file reading and decompression, which may not be desired.) */ -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose(gzFile file); /* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you cannot call gzerror with file, since its structures have been deallocated. gzclose must not be called more than once on the same file, just as free must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the last read ended in the middle of a gzip stream, or Z_OK on success. */ -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_r(gzFile file); +ZEXTERN int ZEXPORT gzclose_w(gzFile file); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to using these instead of gzclose() is that they avoid linking in zlib compression or decompression code that is not used when only reading or only @@ -1650,16 +1654,16 @@ writing respectively. If gzclose() is used, then both compression and decompression code will be included the application when linking to a static zlib library. */ -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); /* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. + Return the error message for the last error which occurred on file. + errnum is set to zlib error number. If an error occurred in the file system + and not in the compression library, errnum is set to Z_ERRNO and the + application may consult errno to get the exact error code. The application must not modify the returned string. Future calls to this function may invalidate the previously returned string. If file is closed, then the string previously returned by gzerror will no longer be available. @@ -1666,13 +1670,13 @@ gzerror() should be used to distinguish errors from end-of-file for those functions above that do not distinguish those cases in their return values. */ -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +ZEXTERN void ZEXPORT gzclearerr(gzFile file); /* - Clears the error and end-of-file flags for file. This is analogous to the + Clear the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ #endif /* !Z_SOLO */ @@ -1683,15 +1687,16 @@ These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is Z_NULL, this function returns the - required initial value for the checksum. + 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: @@ -1702,34 +1707,35 @@ adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ -ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, - z_size_t len)); +ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, + z_size_t len); /* Same as adler32(), but with a size_t length. */ /* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); +ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, + z_off_t len2); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note that the z_off_t type (like off_t) is a signed integer. If len2 is negative, the result has no meaning or utility. */ -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. 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. + 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); @@ -1737,46 +1743,60 @@ crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ -ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, - z_size_t len)); +ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, + z_size_t len); /* Same as crc32(), but with a size_t length. */ /* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); +ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and len2. */ +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). +*/ + +ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); +ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, + const char *version, int stream_size); +ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size); #ifdef Z_PREFIX_SET # define z_deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) @@ -1817,11 +1837,11 @@ struct gzFile_s { unsigned have; unsigned char *next; z_off64_t pos; }; -ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #else @@ -1834,16 +1854,17 @@ * both are true, the application gets the *64 functions, and the regular * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ #ifdef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); #endif #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) # ifdef Z_PREFIX_SET # define z_gzopen z_gzopen64 @@ -1850,63 +1871,68 @@ # define z_gzseek z_gzseek64 # define z_gztell z_gztell64 # define z_gzoffset z_gzoffset64 # define z_adler32_combine z_adler32_combine64 # define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 # else # define gzopen gzopen64 # define gzseek gzseek64 # define gztell gztell64 # define gzoffset gzoffset64 # define adler32_combine adler32_combine64 # define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 # endif # ifndef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); # endif #else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif #else /* Z_SOLO */ - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif /* !Z_SOLO */ /* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); -ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); -ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); -ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); -ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); -#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) -ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, - const char *mode)); +ZEXTERN const char * ZEXPORT zError(int); +ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); +ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); +ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); +ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); +ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, + const char *mode); #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO -ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, - const char *format, - va_list va)); +ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, + const char *format, + va_list va); # endif #endif #ifdef __cplusplus } #endif #endif /* ZLIB_H */ Index: compat/zlib/zlib.map ================================================================== --- compat/zlib/zlib.map +++ compat/zlib/zlib.map @@ -90,5 +90,11 @@ 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 Index: compat/zlib/zlib2ansi ================================================================== --- compat/zlib/zlib2ansi +++ /dev/null @@ -1,152 +0,0 @@ -#!/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; - -} Index: compat/zlib/zutil.c ================================================================== --- compat/zlib/zutil.c +++ compat/zlib/zutil.c @@ -22,17 +22,15 @@ (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ (z_const char *)"" }; -const char * ZEXPORT zlibVersion() -{ +const char * ZEXPORT zlibVersion(void) { return ZLIB_VERSION; } -uLong ZEXPORT zlibCompileFlags() -{ +uLong ZEXPORT zlibCompileFlags(void) { uLong flags; flags = 0; switch ((int)(sizeof(uInt))) { case 2: break; @@ -59,13 +57,15 @@ 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; @@ -117,65 +117,50 @@ # ifndef verbose # define verbose 0 # endif int ZLIB_INTERNAL z_verbose = verbose; -void ZLIB_INTERNAL z_error (m) - char *m; -{ +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(err) - int err; -{ +const char * ZEXPORT zError(int err) { return ERR_MSG(err); } -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have +#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 + /* The older Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ int errno = 0; #endif #ifndef HAVE_MEMCPY -void ZLIB_INTERNAL zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; -{ +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(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; -{ +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(dest, len) - Bytef* dest; - uInt len; -{ +void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } @@ -212,12 +197,11 @@ * Since MSDOS is not a preemptive multitasking OS, this table is not * protected from concurrent access. This hack doesn't work anyway on * a protected system like OS/2. Use Microsoft C instead. */ -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) -{ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { voidpf buf; ulg bsize = (ulg)items*size; (void)opaque; @@ -238,12 +222,11 @@ *(ush*)&buf = 0; table[next_ptr++].new_ptr = buf; return buf; } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; (void)opaque; if (*(ush*)&ptr != 0) { /* object < 64K */ @@ -275,18 +258,16 @@ #if (!defined(_MSC_VER) || (_MSC_VER <= 600)) # define _halloc halloc # define _hfree hfree #endif -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) -{ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) { (void)opaque; return _halloc((long)items, size); } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; _hfree(ptr); } #endif /* M_I86 */ @@ -295,31 +276,24 @@ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); +extern voidp malloc(uInt size); +extern voidp calloc(uInt items, uInt size); +extern void free(voidpf ptr); #endif -voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ +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 (opaque, ptr) - voidpf opaque; - voidpf ptr; -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; free(ptr); } #endif /* MY_ZCALLOC */ #endif /* !Z_SOLO */ Index: compat/zlib/zutil.h ================================================================== --- compat/zlib/zutil.h +++ compat/zlib/zutil.h @@ -1,7 +1,7 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * Copyright (C) 1995-2022 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 @@ -27,14 +27,10 @@ # endif # include # include #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 @@ -43,10 +39,21 @@ 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 +# if (ULONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long +# elif (ULLONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long long +# elif (UINT_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned +# endif +#endif extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] @@ -168,14 +175,10 @@ #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 @@ -186,12 +189,13 @@ #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_WIN32) && \ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); #endif /* common defaults */ #ifndef OS_CODE @@ -226,20 +230,20 @@ # define zmemcpy memcpy # define zmemcmp memcmp # define zmemzero(dest, len) memset(dest, 0, len) # endif #else - void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); + void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len); + int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len); + void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len); #endif /* Diagnostic functions */ #ifdef ZLIB_DEBUG # include extern int ZLIB_INTERNAL z_verbose; - extern void ZLIB_INTERNAL z_error OF((char *m)); + extern void ZLIB_INTERNAL z_error(char *m); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracevv(x) {if (z_verbose>1) fprintf x ;} # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} @@ -252,13 +256,13 @@ # define Tracec(c,x) # define Tracecv(c,x) #endif #ifndef Z_SOLO - voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); - void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, + unsigned size); + void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr); #endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) Index: doc/Access.3 ================================================================== --- doc/Access.3 +++ doc/Access.3 @@ -18,11 +18,11 @@ .sp int \fBTcl_Stat\fR(\fIpath\fR, \fIstatPtr\fR) .SH ARGUMENTS .AS "struct stat" *statPtr out -.AP char *path in +.AP "const char" *path in Native name of the file to check the attributes of. .AP int mode in Mask consisting of one or more of \fBR_OK\fR, \fBW_OK\fR, \fBX_OK\fR and \fBF_OK\fR. \fBR_OK\fR, \fBW_OK\fR and \fBX_OK\fR request checking whether the file exists and has read, write and execute permissions, respectively. Index: doc/AddErrInfo.3 ================================================================== --- doc/AddErrInfo.3 +++ doc/AddErrInfo.3 @@ -26,11 +26,11 @@ .sp \fBTcl_AddObjErrorInfo\fR(\fIinterp, message, length\fR) .sp \fBTcl_SetObjErrorCode\fR(\fIinterp, errorObjPtr\fR) .sp -\fBTcl_SetErrorCode\fR(\fIinterp, element, element, ... \fB(char *) NULL\fR) +\fBTcl_SetErrorCode\fR(\fIinterp, element, element, ... \fBNULL\fR) .sp \fBTcl_GetErrorLine\fR(\fIinterp\fR) .sp \fBTcl_SetErrorLine\fR(\fIinterp, lineNum\fR) .sp @@ -45,11 +45,11 @@ Interpreter in which to record information. .AP int code The code returned from script evaluation. .AP Tcl_Obj *options A dictionary of return options. -.AP char *message in +.AP "const char" *message in For \fBTcl_AddErrorInfo\fR, this is a conventional C string to append to the \fB\-errorinfo\fR return option. For \fBTcl_AddObjErrorInfo\fR, this points to the first byte of an array of \fIlength\fR bytes containing a string to append to the \fB\-errorinfo\fR return option. @@ -56,30 +56,27 @@ This byte array may contain embedded null bytes unless \fIlength\fR is negative. .AP Tcl_Obj *objPtr in A message to be appended to the \fB\-errorinfo\fR return option in the form of a Tcl_Obj value. -.AP size_t length in +.AP Tcl_Size length in The number of bytes to copy from \fImessage\fR when appending to the \fB\-errorinfo\fR return option. -If TCL_INDEX_NONE, all bytes up to the first null byte are used. +If negative, all bytes up to the first null byte are used. .AP Tcl_Obj *errorObjPtr in The \fB\-errorcode\fR return option will be set to this value. -.AP char *element in +.AP "const char" *element in String to record as one element of the \fB\-errorcode\fR return option. Last \fIelement\fR argument must be NULL. -.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 +.AP Tcl_Size commandLength in +Number of bytes in command; a negative value 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 @@ -298,10 +295,26 @@ 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 Index: doc/Alloc.3 ================================================================== --- doc/Alloc.3 +++ doc/Alloc.3 @@ -2,15 +2,15 @@ '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -.TH Tcl_Alloc 3 7.5 Tcl "Tcl Library Procedures" +.TH Tcl_Alloc 3 9.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_Alloc, Tcl_Free, Tcl_Realloc, Tcl_AttemptAlloc, Tcl_AttemptRealloc \- allocate or free heap memory +Tcl_Alloc, Tcl_Free, Tcl_Realloc, Tcl_AttemptAlloc, Tcl_AttemptRealloc, Tcl_GetMemoryInfo \- allocate or free heap memory .SH SYNOPSIS .nf \fB#include \fR .sp char * @@ -25,16 +25,21 @@ void * \fBTcl_AttemptAlloc\fR(\fIsize\fR) .sp void * \fBTcl_AttemptRealloc\fR(\fIptr, size\fR) +.sp +void +\fBTcl_GetMemoryInfo\fR(\fIdsPtr\fR) .SH ARGUMENTS .AS char *size -.AP "unsigned int" size in +.AP "size_t" size in Size in bytes of the memory block to allocate. .AP char *ptr in 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 @@ -66,8 +71,15 @@ .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. + +\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 Index: doc/Async.3 ================================================================== --- doc/Async.3 +++ doc/Async.3 @@ -7,23 +7,28 @@ '\" .TH Tcl_AsyncCreate 3 7.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncInvoke, Tcl_AsyncDelete, Tcl_AsyncReady \- handle asynchronous events +Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncMarkFromSignal, Tcl_AsyncInvoke, Tcl_AsyncDelete, Tcl_AsyncReady \- handle asynchronous events .SH SYNOPSIS .nf \fB#include \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() .SH ARGUMENTS @@ -32,10 +37,12 @@ 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 @@ -58,29 +65,33 @@ occurred, then handle the event later when the world has returned to a clean state, such as after the current Tcl command completes. .PP \fBTcl_AsyncCreate\fR, \fBTcl_AsyncDelete\fR, and \fBTcl_AsyncReady\fR are thread sensitive. They access and/or set a thread-specific data -structure in the event of a core built with \fI\-\-enable\-threads\fR. The token -created by \fBTcl_AsyncCreate\fR contains the needed thread information it -was called from so that calling \fBTcl_AsyncMark\fR(\fItoken\fR) will only yield -the origin thread into the asynchronous handler. +structure in the event of a core built with \fI\-\-enable\-threads\fR. +The token created by \fBTcl_AsyncCreate\fR contains the needed thread +information it was called from so that calling \fBTcl_AsyncMarkFromSignal\fR +or \fBTcl_AsyncMark\fR with this token will only yield the origin +thread into the asynchronous handler. .PP \fBTcl_AsyncCreate\fR creates an asynchronous handler and returns a token for it. The asynchronous handler must be created before any occurrences of the asynchronous event that it is intended to handle (it is not safe to create a handler at the time of an event). When an asynchronous event occurs the code that detects the event -(such as a signal handler) should call \fBTcl_AsyncMark\fR with the -token for the handler. -\fBTcl_AsyncMark\fR will mark the handler as ready to execute, but it -will not invoke the handler immediately. -Tcl will call the \fIproc\fR associated with the handler later, when -the world is in a safe state, and \fIproc\fR can then carry out -the actions associated with the asynchronous event. +(such as a POSIX signal handler) should call \fBTcl_AsyncMarkFromSignal\fR +with the token for the handler and the POSIX signal number. The +return value of this function is true, when the handler will be +marked, false otherwise. +For non-signal contexts, \fBTcl_AsyncMark\fR serves the same purpose. +\fBTcl_AsyncMarkFromSignal\fR and \fBTcl_AsyncMark\fR will mark +the handler as ready to execute, but will not invoke the handler +immediately. Tcl will call the \fIproc\fR associated with the +handler later, when the world is in a safe state, and \fIproc\fR +can then carry out the actions associated with the asynchronous event. \fIProc\fR should have arguments and result that match the type \fBTcl_AsyncProc\fR: .PP .CS typedef int \fBTcl_AsyncProc\fR( Index: doc/BoolObj.3 ================================================================== --- doc/BoolObj.3 +++ doc/BoolObj.3 @@ -7,56 +7,66 @@ '\" .TH Tcl_BooleanObj 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj \- store/retrieve boolean value in a Tcl_Obj +Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj, Tcl_GetBoolFromObj \- store/retrieve boolean value in a Tcl_Obj .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * -\fBTcl_NewBooleanObj\fR(\fIboolValue\fR) +\fBTcl_NewBooleanObj\fR(\fIintValue\fR) .sp -\fBTcl_SetBooleanObj\fR(\fIobjPtr, boolValue\fR) +\fBTcl_SetBooleanObj\fR(\fIobjPtr, intValue\fR) .sp int \fBTcl_GetBooleanFromObj\fR(\fIinterp, objPtr, boolPtr\fR) +.sp +int +\fBTcl_GetBoolFromObj\fR(\fIinterp, objPtr, flags. charPtr\fR) .SH ARGUMENTS -.AS Tcl_Interp boolValue in/out -.AP int boolValue in +.AS Tcl_Interp intValue in/out +.AP int intValue in Integer value to be stored as a boolean value in a Tcl_Obj. .AP Tcl_Obj *objPtr in/out Points to the Tcl_Obj in which to store, or from which to retrieve a boolean value. .AP Tcl_Interp *interp in/out If a boolean value cannot be retrieved, an error message is left in the interpreter's result value unless \fIinterp\fR is NULL. -.AP int *boolPtr out +.AP "bool \&| int" *boolPtr out Points to place where \fBTcl_GetBooleanFromObj\fR stores the boolean value (0 or 1) obtained from \fIobjPtr\fR. +.AP char *charPtr out +Points to place where \fBTcl_GetBoolFromObj\fR +stores the boolean value (0 or 1) obtained from \fIobjPtr\fR. +.AP int flags in +0 or TCL_NULL_OK. If TCL_NULL_OK +is used, then the empty string or NULL will result in \fBTcl_GetBoolFromObj\fR +return TCL_OK, the *charPtr filled with the value \fB'\exFF'\fR; .BE .SH DESCRIPTION .PP These procedures are used to pass boolean values to and from Tcl as Tcl_Obj's. When storing a boolean value into a Tcl_Obj, -any non-zero integer value in \fIboolValue\fR is taken to be +any non-zero integer value in \fIintValue\fR is taken to be the boolean value \fB1\fR, and the integer value \fB0\fR is taken to be the boolean value \fB0\fR. .PP \fBTcl_NewBooleanObj\fR creates a new Tcl_Obj, stores the boolean -value \fIboolValue\fR in it, and returns a pointer to the new Tcl_Obj. +value \fIintValue\fR in it, and returns a pointer to the new Tcl_Obj. The new Tcl_Obj has reference count of zero. .PP \fBTcl_SetBooleanObj\fR accepts \fIobjPtr\fR, a pointer to an existing Tcl_Obj, and stores in the Tcl_Obj \fI*objPtr\fR -the boolean value \fIboolValue\fR. This is a write operation +the boolean value \fIintValue\fR. This is a write operation on \fI*objPtr\fR, so \fIobjPtr\fR must be unshared. Attempts to write to a shared Tcl_Obj will panic. A successful write -of \fIboolValue\fR into \fI*objPtr\fR implies the freeing of +of \fIintValue\fR into \fI*objPtr\fR implies the freeing of any former value stored in \fI*objPtr\fR. .PP \fBTcl_GetBooleanFromObj\fR attempts to retrieve a boolean value from the value stored in \fI*objPtr\fR. If \fIobjPtr\fR holds a string value recognized by \fBTcl_GetBoolean\fR, @@ -73,10 +83,15 @@ 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 @@ -86,10 +101,22 @@ 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 Index: doc/ByteArrObj.3 ================================================================== --- doc/ByteArrObj.3 +++ doc/ByteArrObj.3 @@ -2,90 +2,175 @@ '\" Copyright (c) 1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -.TH Tcl_ByteArrayObj 3 8.1 Tcl "Tcl Library Procedures" +.TH Tcl_ByteArrayObj 3 9.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_NewByteArrayObj, Tcl_SetByteArrayObj, Tcl_GetByteArrayFromObj, Tcl_SetByteArrayLength \- manipulate Tcl values as a arrays of bytes +Tcl_NewByteArrayObj, Tcl_SetByteArrayObj, Tcl_GetBytesFromObj, Tcl_GetByteArrayFromObj, Tcl_SetByteArrayLength \- manipulate a Tcl value as an array of bytes .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * -\fBTcl_NewByteArrayObj\fR(\fIbytes, length\fR) +\fBTcl_NewByteArrayObj\fR(\fIbytes, numBytes\fR) .sp void -\fBTcl_SetByteArrayObj\fR(\fIobjPtr, bytes, length\fR) +\fBTcl_SetByteArrayObj\fR(\fIobjPtr, bytes, numBytes\fR) +.sp +.VS TIP568 +unsigned char * +\fBTcl_GetBytesFromObj\fR(\fIinterp, objPtr, numBytesPtr\fR) +.VE TIP568 .sp unsigned char * -\fBTcl_GetByteArrayFromObj\fR(\fIobjPtr, lengthPtr\fR) +\fBTcl_GetByteArrayFromObj\fR(\fIobjPtr, numBytesPtr\fR) .sp unsigned char * -\fBTcl_SetByteArrayLength\fR(\fIobjPtr, length\fR) +\fBTcl_SetByteArrayLength\fR(\fIobjPtr, numBytes\fR) .SH ARGUMENTS -.AS "const unsigned char" *lengthPtr in/out +.AS "const unsigned char" *numBytesPtr in/out .AP "const unsigned char" *bytes in The array of bytes used to initialize or set a byte-array value. May be NULL -even if \fIlength\fR is non-zero. -.AP size_t length in -The length of the array of bytes. +even if \fInumBytes\fR is non-zero. +.AP Tcl_Size numBytes in +The number of bytes in the array. .AP Tcl_Obj *objPtr in/out -For \fBTcl_SetByteArrayObj\fR, this points to the value to be converted to -byte-array type. For \fBTcl_GetByteArrayFromObj\fR and -\fBTcl_SetByteArrayLength\fR, this points to the value from which to get -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. +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. +Caller may pass NULL when it does not need this information. .BE .SH DESCRIPTION .PP -These procedures are used to create, modify, and read Tcl byte-array values -from C code. Byte-array values are typically used to hold the -results of binary IO operations or data structures created with the -\fBbinary\fR command. In Tcl, an array of bytes is not equivalent to a -string. Conceptually, a string is an array of Unicode characters, while a -byte-array is an array of 8-bit quantities with no implicit meaning. -Accessor functions are provided to get the string representation of a -byte-array or to convert an arbitrary value to a byte-array. Obtaining the +These routines are used to create, modify, store, transfer, and retrieve +arbitrary binary data in Tcl values. Specifically, data that can be +represented as a sequence of arbitrary byte values is supported. +This includes data read from binary channels, values created by the +\fBbinary\fR command, encrypted data, or other information representable as +a finite byte sequence. +.PP +A byte is an 8-bit quantity with no inherent meaning. When the 8 bits are +interpreted as an integer value, the range of possible values is (0-255). +The C type best suited to store a byte is the \fBunsigned char\fR. +An \fBunsigned char\fR array of size \fIN\fR stores an aribtrary binary +value of size \fIN\fR bytes. We call this representation a byte-array. +Here we document the routines that allow us to operate on Tcl values as +byte-arrays. +.PP +All Tcl values must correspond to a string representation. +When a byte-array value must be processed as a string, the sequence +of \fIN\fR bytes is transformed into the corresponding sequence +of \fIN\fR characters, where each byte value transforms to the same +character codepoint value in the range (U+0000 - U+00FF). Obtaining the string representation of a byte-array value (by calling -\fBTcl_GetStringFromObj\fR) produces a properly formed UTF-8 sequence with a -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. +\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_GetByteFromObj\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, internationalization +value, binary data, byte array, utf, unicode Index: doc/Cancel.3 ================================================================== --- doc/Cancel.3 +++ doc/Cancel.3 @@ -24,11 +24,11 @@ .AP Tcl_Obj *resultObjPtr in Error message to use in the cancellation, or NULL to use a default message. If not NULL, this object will have its reference count decremented before \fBTcl_CancelEval\fR returns. .AP int flags in -ORed combination of flag bits that specify additional options. +OR'ed combination of flag bits that specify additional options. For \fBTcl_CancelEval\fR, only \fBTCL_CANCEL_UNWIND\fR is currently supported. For \fBTcl_Canceled\fR, only \fBTCL_LEAVE_ERR_MSG\fR and \fBTCL_CANCEL_UNWIND\fR are currently supported. .AP void *clientData in Currently reserved for future use. @@ -45,11 +45,11 @@ returns \fBTCL_ERROR\fR if it has. Otherwise, \fBTCL_OK\fR is returned. Extensions can use this function to check to see if they should abort a long running command. This function is thread sensitive and may only be called from the thread the interpreter was created in. .SS "FLAG BITS" -Any ORed combination of the following values may be used for the +Any OR'ed combination of the following values may be used for the \fIflags\fR argument to procedures such as \fBTcl_CancelEval\fR: .TP 20 \fBTCL_CANCEL_UNWIND\fR . This flag is used by \fBTcl_CancelEval\fR and \fBTcl_Canceled\fR. @@ -65,10 +65,18 @@ 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 Index: doc/Class.3 ================================================================== --- doc/Class.3 +++ doc/Class.3 @@ -53,10 +53,18 @@ .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" .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. @@ -71,15 +79,15 @@ automatically selected. .AP "const char" *nsName in The name of the namespace to create for the object's private use, or NULL if a new unused name is to be automatically selected. The namespace must not already exist. -.AP int objc in +.AP Tcl_Size objc in The number of elements in the \fIobjv\fR array. .AP "Tcl_Obj *const" *objv in The arguments to the command to create the instance of the class. -.AP int skip in +.AP Tcl_Size skip in The number of arguments at the start of the argument array, \fIobjv\fR, that are not arguments to any constructors. This allows the generation of correct error messages even when complicated calling patterns are used (e.g., via the \fBnext\fR command). .AP Tcl_ObjectMetadataType *metaTypePtr in @@ -112,10 +120,17 @@ 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 @@ -239,13 +254,36 @@ 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: Index: doc/Concat.3 ================================================================== --- doc/Concat.3 +++ doc/Concat.3 @@ -16,11 +16,11 @@ .sp const char * \fBTcl_Concat\fR(\fIargc, argv\fR) .SH ARGUMENTS .AS "const char *const" argv[] -.AP int argc in +.AP Tcl_Size argc in Number of strings. .AP "const char *const" argv[] in Array of strings to concatenate. Must have \fIargc\fR entries. .BE Index: doc/CrtAlias.3 ================================================================== --- doc/CrtAlias.3 +++ doc/CrtAlias.3 @@ -6,21 +6,18 @@ '\" .TH Tcl_CreateAlias 3 7.6 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_IsSafe, Tcl_MakeSafe, Tcl_CreateChild, Tcl_GetChild, Tcl_GetParent, Tcl_GetInterpPath, Tcl_CreateAlias, Tcl_CreateAliasObj, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_ExposeCommand, Tcl_HideCommand \- manage multiple Tcl interpreters, aliases and hidden commands +Tcl_IsSafe, Tcl_CreateChild, Tcl_GetChild, Tcl_GetParent, Tcl_GetInterpPath, Tcl_CreateAlias, Tcl_CreateAliasObj, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_ExposeCommand, Tcl_HideCommand \- manage multiple Tcl interpreters, aliases and hidden commands .SH SYNOPSIS .nf \fB#include \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) @@ -70,16 +67,16 @@ Name of source command for alias. .AP Tcl_Interp *targetInterp in Interpreter that contains the target command for an alias. .AP "const char" *targetCmd in Name of target command for alias in \fItargetInterp\fR. -.AP int argc in +.AP Tcl_Size argc in Count of additional arguments to pass to the alias command. .AP "const char *const" *argv in Vector of strings, the additional arguments to pass to the alias command. This storage is owned by the caller. -.AP int objc in +.AP Tcl_Size objc in Count of additional value arguments to pass to the aliased command. .AP Tcl_Obj **objv in Vector of Tcl_Obj structures, the additional value arguments to pass to the aliased command. This storage is owned by the caller. @@ -136,22 +133,10 @@ \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 @@ -226,11 +211,19 @@ After executing this command, attempts to use \fIcmdName\fR in any script evaluation mechanism will fail. .PP For a description of the Tcl interface to multiple interpreters, see \fIinterp(n)\fR. +.SH "REFERENCE COUNT MANAGEMENT" +.PP +\fBTcl_CreateAliasObj\fR increments the reference counts of the values +in its \fIobjv\fR argument. (That reference lasts the same length of +time as the owning alias.) +.PP +\fBTcl_GetAliasObj\fR returns (via its \fIobjvPtr\fR argument) a +pointer to values that it holds a reference to. .SH "SEE ALSO" -interp +interp(n) .SH KEYWORDS alias, command, exposed commands, hidden commands, interpreter, invoke, parent, child Index: doc/CrtChannel.3 ================================================================== --- doc/CrtChannel.3 +++ doc/CrtChannel.3 @@ -33,10 +33,15 @@ \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 @@ -134,11 +139,11 @@ \fBTCL_READABLE\fR means the input handle is wanted; \fBTCL_WRITABLE\fR means the output handle is wanted. .AP void **handlePtr out Points to the location where the desired OS-specific handle should be stored. -.AP int size in +.AP Tcl_Size size in The size, in bytes, of buffers to allocate in this channel. .AP int mask in An OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR that indicates events that have occurred on this channel. @@ -234,10 +239,20 @@ 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. @@ -251,11 +266,12 @@ .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. +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 @@ -527,13 +543,13 @@ generic layer to move the access point at which subsequent input or output operations will be applied. \fIWideSeekProc\fR must match the following prototype: .PP .CS -typedef Tcl_WideInt \fBTcl_DriverWideSeekProc\fR( +typedef long long \fBTcl_DriverWideSeekProc\fR( void *\fIinstanceData\fR, - Tcl_WideInt \fIoffset\fR, + long long \fIoffset\fR, int \fIseekMode\fR, int *\fIerrorCodePtr\fR); .CE .PP The \fIinstanceData\fR argument is the same as the value given to @@ -759,11 +775,11 @@ length. It can be NULL. .PP .CS typedef int \fBTcl_DriverTruncateProc\fR( void *\fIinstanceData\fR, - Tcl_WideInt \fIlength\fR); + long long \fIlength\fR); .CE .PP \fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR when this channel was created, and \fIlength\fR is the new length of the underlying file, which should Index: doc/CrtChnlHdlr.3 ================================================================== --- doc/CrtChnlHdlr.3 +++ doc/CrtChnlHdlr.3 @@ -27,11 +27,11 @@ Tcl channel such as returned by \fBTcl_CreateChannel\fR. .AP int mask in Conditions under which \fIproc\fR should be called: OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR. Specify a zero value to temporarily disable an existing handler. -.AP Tcl_FileProc *proc in +.AP Tcl_ChannelProc *proc in Procedure to invoke whenever the channel indicated by \fIchannel\fR meets the conditions specified by \fImask\fR. .AP void *clientData in Arbitrary one-word value to pass to \fIproc\fR. .BE Index: doc/CrtObjCmd.3 ================================================================== --- doc/CrtObjCmd.3 +++ doc/CrtObjCmd.3 @@ -6,18 +6,21 @@ '\" .TH Tcl_CreateObjCommand 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_CreateObjCommand, Tcl_DeleteCommand, Tcl_DeleteCommandFromToken, Tcl_GetCommandInfo, Tcl_GetCommandInfoFromToken, Tcl_SetCommandInfo, Tcl_SetCommandInfoFromToken, Tcl_GetCommandName, Tcl_GetCommandFullName, Tcl_GetCommandFromObj, Tcl_RegisterCommandTypeName, Tcl_GetCommandTypeName \- implement new commands in C +Tcl_CreateObjCommand, Tcl_CreateObjCommand2, Tcl_DeleteCommand, Tcl_DeleteCommandFromToken, Tcl_GetCommandInfo, Tcl_GetCommandInfoFromToken, Tcl_SetCommandInfo, Tcl_SetCommandInfoFromToken, Tcl_GetCommandName, Tcl_GetCommandFullName, Tcl_GetCommandFromObj \- implement new commands in C .SH SYNOPSIS .nf \fB#include \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) @@ -41,26 +44,22 @@ \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 +.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 @@ -178,10 +177,21 @@ 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 @@ -212,28 +222,33 @@ in the \fBTcl_CmdInfo\fR structure pointed to by \fIinfoPtr\fR and returns 1. A \fBTcl_CmdInfo\fR structure has the following fields: .PP .CS -typedef struct Tcl_CmdInfo { +typedef struct { int \fIisNativeObjectProc\fR; Tcl_ObjCmdProc *\fIobjProc\fR; void *\fIobjClientData\fR; Tcl_CmdProc *\fIproc\fR; void *\fIclientData\fR; Tcl_CmdDeleteProc *\fIdeleteProc\fR; void *\fIdeleteData\fR; Tcl_Namespace *\fInamespacePtr\fR; + Tcl_ObjCmdProc2 *\fIobjProc2\fR; + void *\fIobjClientData2\fR; } \fBTcl_CmdInfo\fR; .CE .PP -The \fIisNativeObjectProc\fR field has the value 1 -if \fBTcl_CreateObjCommand\fR was called to register the command; -it is 0 if only \fBTcl_CreateCommand\fR was called. +The \fIisNativeObjectProc\fR field has the value 2 if +\fBTcl_CreateObjCommand2\fR was called to register the command; +it has the value 1 if \fBTcl_CreateObjCommand\fR was called to +register the command; it is 0 if only \fBTcl_CreateCommand\fR was called. It allows a program to determine whether it is faster to -call \fIobjProc\fR or \fIproc\fR: -\fIobjProc\fR is normally faster +call \fIobjProc2\fR, \fIobjProc\fR or \fIproc\fR: +\fIobjProc2\fR/\fIobjProc\fR is normally faster +if \fIisNativeObjectProc\fR has the value 2; +\fIobjProc\fR/\fIobjProc\fR is normally faster if \fIisNativeObjectProc\fR has the value 1. The fields \fIobjProc\fR and \fIobjClientData\fR have the same meaning as the \fIproc\fR and \fIclientData\fR arguments to \fBTcl_CreateObjCommand\fR; they hold information about the value-based command procedure @@ -306,24 +321,24 @@ \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 "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 Index: doc/CrtTrace.3 ================================================================== --- doc/CrtTrace.3 +++ doc/CrtTrace.3 @@ -1,18 +1,18 @@ '\" '\" 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 . All rights reserved. +'\" Copyright (c) 2002 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. '\" .TH Tcl_CreateTrace 3 "" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_CreateTrace, Tcl_CreateObjTrace, Tcl_DeleteTrace \- arrange for command execution to be traced +Tcl_CreateTrace, Tcl_CreateObjTrace, Tcl_CreateObjTrace2, Tcl_DeleteTrace \- arrange for command execution to be traced .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Trace @@ -19,16 +19,19 @@ \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) .SH ARGUMENTS .AS Tcl_CmdObjTraceDeleteProc *deleteProc .AP Tcl_Interp *interp in Interpreter containing command to be traced or untraced. -.AP int level in +.AP Tcl_Size level in Only commands at or below this nesting level will be traced unless 0 is specified. 1 means top-level commands only, 2 means top-level commands or those that are invoked as immediate consequences of executing top-level commands (procedure bodies, bracketed commands, etc.) and so on. @@ -36,15 +39,18 @@ .AP int flags in Flags governing the trace execution. See below for details. .AP Tcl_CmdObjTraceProc *objProc in Procedure to call for each command that is executed. See below for details of the calling sequence. +.AP Tcl_CmdObjTraceProc2 *objProc2 in +Procedure to call for each command that is executed. See below for +details of the calling sequence. .AP Tcl_CmdTraceProc *proc in Procedure to call for each command that is executed. See below for details on the calling sequence. .AP void *clientData in -Arbitrary one-word value to pass to \fIobjProc\fR or \fIproc\fR. +Arbitrary one-word value to pass to \fIobjProc\fR, \fIobjProc2\fR or \fIproc\fR. .AP Tcl_CmdObjTraceDeleteProc *deleteProc in Procedure to call when the trace is deleted. See below for details of the calling sequence. A NULL pointer is permissible and results in no callback when the trace is deleted. .AP Tcl_Trace trace in @@ -72,10 +78,24 @@ 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 @@ -97,15 +117,11 @@ 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. +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). @@ -185,7 +201,16 @@ \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 Index: doc/DString.3 ================================================================== --- doc/DString.3 +++ doc/DString.3 @@ -7,11 +7,11 @@ '\" .TH Tcl_DString 3 7.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringFree, Tcl_DStringResult, Tcl_DStringGetResult \- manipulate dynamic strings +Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringFree, Tcl_DStringResult, Tcl_DStringGetResult, Tcl_DStringToObj \- manipulate dynamic strings .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_DStringInit\fR(\fIdsPtr\fR) @@ -24,11 +24,11 @@ .sp \fBTcl_DStringStartSublist\fR(\fIdsPtr\fR) .sp \fBTcl_DStringEndSublist\fR(\fIdsPtr\fR) .sp -size_t +Tcl_Size \fBTcl_DStringLength\fR(\fIdsPtr\fR) .sp char * \fBTcl_DStringValue\fR(\fIdsPtr\fR) .sp @@ -37,22 +37,26 @@ \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) +.sp .SH ARGUMENTS .AS Tcl_DString newLength in/out .AP Tcl_DString *dsPtr in/out Pointer to structure that is used to manage a dynamic string. .AP "const char" *bytes in Pointer to characters to append to dynamic string. .AP "const char" *element in Pointer to characters to append as list element to dynamic string. -.AP size_t length in -Number of bytes from \fIbytes\fR to add to dynamic string. If TCL_INDEX_NONE, +.AP Tcl_Size length in +Number of bytes from \fIbytes\fR to add to dynamic string. If negative, add all characters up to null terminating character. -.AP size_t newLength in +.AP Tcl_Size newLength in New length for dynamic string, not including null terminating character. .AP Tcl_Interp *interp in/out Interpreter whose result is to be set from or moved to the dynamic string. @@ -134,14 +138,28 @@ 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 Index: doc/DetachPids.3 ================================================================== --- doc/DetachPids.3 +++ doc/DetachPids.3 @@ -20,11 +20,11 @@ .sp Tcl_Pid \fBTcl_WaitPid\fR(\fIpid, statusPtr, options\fR) .SH ARGUMENTS .AS Tcl_Pid *statusPtr out -.AP int numPids in +.AP Tcl_Size numPids in Number of process ids contained in the array pointed to by \fIpidPtr\fR. .AP int *pidPtr in Address of array containing \fInumPids\fR process ids. .AP Tcl_Pid pid in The id of the process (pipe) to wait for. Index: doc/DictObj.3 ================================================================== --- doc/DictObj.3 +++ doc/DictObj.3 @@ -68,11 +68,11 @@ .AP Tcl_Obj **valuePtrPtr out Points to a variable that will have the value from a key/value pair placed within it. For \fBTcl_DictObjFirst\fR and \fBTcl_DictObjNext\fR, this may be NULL to indicate that the caller is not interested in the value. -.AP int *sizePtr out +.AP "Tcl_Size \&| int" *sizePtr out Points to a variable that will have the number of key/value pairs contained within the dictionary placed within it. .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 @@ -82,11 +82,11 @@ \fBTcl_DictObjDone\fR to enable the internal locks to be released. .AP int *donePtr out Points to a variable that will have a non-zero value written into it when the enumeration of the key/value pairs in a dictionary has completed, and a zero otherwise. -.AP int keyc in +.AP Tcl_Size keyc in Indicates the number of keys that will be supplied in the \fIkeyv\fR array. .AP "Tcl_Obj *const" *keyv in Array of \fIkeyc\fR pointers to values that \fBTcl_DictObjPutKeyList\fR and \fBTcl_DictObjRemoveKeyList\fR will @@ -136,11 +136,12 @@ converted to a dictionary. .PP \fBTcl_DictObjSize\fR updates the given variable with the number of key/value pairs currently in the given dictionary. The result of this procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be -converted to a dictionary. +converted to a dictionary or if \fIsizePtr\fR points to a variable of type +\fBint\fR and the dict contains more than 2**31 key/value pairs. .PP \fBTcl_DictObjFirst\fR commences an iteration across all the key/value pairs in the given dictionary, placing the key and value in the variables pointed to by the \fIkeyPtrPtr\fR and \fIvaluePtrPtr\fR arguments (which may be NULL to indicate that the caller is @@ -188,10 +189,77 @@ 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 Index: doc/DoubleObj.3 ================================================================== --- doc/DoubleObj.3 +++ doc/DoubleObj.3 @@ -56,9 +56,21 @@ \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 Index: doc/DumpActiveMemory.3 ================================================================== --- doc/DumpActiveMemory.3 +++ doc/DumpActiveMemory.3 @@ -1,8 +1,8 @@ '\" -'\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans. -'\" Copyright (c) 2000 by Scriptics Corporation. +'\" Copyright (c) 1992-1999 Karl Lehenbauer & Mark Diekhans. +'\" Copyright (c) 2000 Scriptics Corporation. '\" All rights reserved. '\" .TH "Tcl_DumpActiveMemory" 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS Index: doc/Encoding.3 ================================================================== --- doc/Encoding.3 +++ doc/Encoding.3 @@ -6,11 +6,11 @@ '\" .TH Tcl_GetEncoding 3 "8.1" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath \- procedures for creating and using encodings +Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtfDStringEx, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternalDStringEx, Tcl_UtfToExternal, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath \- procedures for creating and using encodings .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Encoding @@ -23,13 +23,19 @@ \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 @@ -37,10 +43,13 @@ 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) @@ -75,30 +84,34 @@ specified encoding that are to be converted to UTF-8. For the \fBTcl_UtfToExternal\fR function, an array of UTF-8 characters to be converted to the specified encoding. .AP "const TCHAR" *tsrc in An array of Windows TCHAR characters to convert to UTF-8. -.AP size_t srcLen in +.AP Tcl_Size srcLen in Length of \fIsrc\fR or \fItsrc\fR in bytes. If the length is negative, the encoding-specific length of the string is used. .AP Tcl_DString *dstPtr out Pointer to an uninitialized or free \fBTcl_DString\fR in which the converted result will be stored. .AP int flags in -Various flag bits OR-ed together. +This is a bit mask passed in to control the operation of the encoding functions. \fBTCL_ENCODING_START\fR signifies that the source buffer is the first block in a (potentially multi-block) input stream, telling the conversion routine to reset to an initial state and perform any initialization that needs to occur before the first byte is converted. \fBTCL_ENCODING_END\fR signifies that the source buffer is the last block in a (potentially multi-block) input stream, telling the conversion routine to perform any finalization that needs to occur after the last -byte is converted and then to reset to an initial state. -\fBTCL_ENCODING_STOPONERROR\fR signifies that the conversion routine should -return immediately upon reading a source character that does not exist in -the target encoding; otherwise a default fallback character will -automatically be substituted. +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. +\fBTCL_ENCODING_STOPONERROR\fR is present for backward compatibility with +Tcl 8.6 and forces the encoding profile to \fBstrict\fR. + +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 @@ -120,10 +133,13 @@ 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 @@ -193,10 +209,31 @@ \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 @@ -215,16 +252,16 @@ 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 +The source buffer contained an invalid byte or character sequence. This may occur if the input stream has been damaged or if the input encoding method was misidentified. .IP \fBTCL_CONVERT_UNKNOWN\fR 29 The source buffer contained a character that could not be represented in -the target encoding and \fBTCL_ENCODING_STOPONERROR\fR was specified. +the target encoding. .RE .LP \fBTcl_UtfToExternalDString\fR converts a source buffer \fIsrc\fR from UTF-8 into the specified \fIencoding\fR. The converted bytes are stored in \fIdstPtr\fR, which is then terminated with the appropriate encoding-specific @@ -232,10 +269,19 @@ 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. + +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 @@ -246,10 +292,13 @@ \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 @@ -295,11 +344,11 @@ const char *\fIencodingName\fR; Tcl_EncodingConvertProc *\fItoUtfProc\fR; Tcl_EncodingConvertProc *\fIfromUtfProc\fR; Tcl_EncodingFreeProc *\fIfreeProc\fR; void *\fIclientData\fR; - int \fInullSize\fR; + Tcl_Size \fInullSize\fR; } \fBTcl_EncodingType\fR; .CE .PP The \fIencodingName\fR provides a string name for the encoding, by which it can be referred in other procedures such as @@ -495,17 +544,17 @@ .ta 1.5i # Encoding file: iso2022-jp, escape-driven E init {} final {} -iso8859-1 \ex1b(B -jis0201 \ex1b(J -jis0208 \ex1b$@ -jis0208 \ex1b$B -jis0212 \ex1b$(D -gb2312 \ex1b$A -ksc5601 \ex1b$(C +iso8859-1 \ex1B(B +jis0201 \ex1B(J +jis0208 \ex1B$@ +jis0208 \ex1B$B +jis0212 \ex1B$(D +gb2312 \ex1B$A +ksc5601 \ex1B$(C .CE .PP In the file, the first column represents an option and the second column is the associated value. \fBinit\fR is a string to emit or expect before the first character is converted, while \fBfinal\fR is a string to emit @@ -513,15 +562,38 @@ table-based encodings; the associated value is the escape-sequence that marks that encoding. Tcl syntax is used for the values; in the above example, for instance, .QW \fB{}\fR represents the empty string and -.QW \fB\ex1b\fR +.QW \fB\ex1B\fR represents character 27. .PP When \fBTcl_GetEncoding\fR encounters an encoding \fIname\fR that has not been loaded, it attempts to load an encoding file called \fIname\fB.enc\fR from the \fBencoding\fR subdirectory of each directory that Tcl searches for its script library. If the encoding file exists, but is malformed, an error message will be left in \fIinterp\fR. +.SH "REFERENCE COUNT MANAGEMENT" +.PP +\fBTcl_GetEncodingFromObj\fR does not modify the reference count of its +\fIobjPtr\fR argument; it only reads. Note however that this function may set +the interpreter result; if that is the only place that is holding a reference +to the object, it will be deleted. +.PP +\fBTcl_GetEncodingSearchPath\fR returns an object with a reference count of at +least 1. +.SH "PROFILES" +Encoding profiles define the manner in which errors in the encoding transforms +are handled by the encoding functions. An application can specify the profile +to be used by OR-ing the \fBflags\fR parameter passed to the function +with at most one of \fBTCL_ENCODING_PROFILE_TCL8\fR, +\fBTCL_ENCODING_PROFILE_STRICT\fR or \fBTCL_ENCODING_PROFILE_REPLACE\fR. +These correspond to the \fBtcl8\fR, \fBstrict\fR and \fBreplace\fR profiles +respectively. If none are specified, a version-dependent default profile is used. +For Tcl 9.0, the default profile is \fBtcl8\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 Index: doc/Ensemble.3 ================================================================== --- doc/Ensemble.3 +++ doc/Ensemble.3 @@ -67,18 +67,18 @@ The name of the ensemble command to be created. .AP Tcl_Namespace *namespacePtr in The namespace to which the ensemble command is to be bound, or NULL for the current namespace. .AP int ensFlags in -An ORed set of flag bits describing the basic configuration of the +An OR'ed set of flag bits describing the basic configuration of the ensemble. Currently only one bit has meaning, \fBTCL_ENSEMBLE_PREFIX\fR, which is present when the ensemble command should also match unambiguous prefixes of subcommands. .AP Tcl_Obj *cmdNameObj in A value holding the name of the ensemble command to look up. .AP int flags in -An ORed set of flag bits controlling the behavior of +An OR'ed set of flag bits controlling the behavior of \fBTcl_FindEnsemble\fR. Currently only \fBTCL_LEAVE_ERR_MSG\fR is supported. .AP Tcl_Command token in A normal command token that refers to an ensemble command, or which you wish to use for testing as an ensemble command in \fBTcl_IsEnsemble\fR. .AP int *ensFlagsPtr out @@ -207,9 +207,30 @@ 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 Index: doc/Eval.3 ================================================================== --- doc/Eval.3 +++ doc/Eval.3 @@ -35,25 +35,25 @@ .sp int \fBTcl_GlobalEvalObj\fR(\fIinterp, objPtr\fR) .sp int -\fBTcl_VarEval\fR(\fIinterp, part, part, ... \fB(char *) NULL\fR) +\fBTcl_VarEval\fR(\fIinterp, part, part, ... \fBNULL\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. +OR'ed combination of flag bits that specify additional options. \fBTCL_EVAL_GLOBAL\fR and \fBTCL_EVAL_DIRECT\fR are currently supported. .AP "const char" *fileName in Name of a file containing a Tcl script. -.AP int objc in -The number of values in the array pointed to by \fIobjPtr\fR; +.AP Tcl_Size objc in +The number of values in the array pointed to by \fIobjv\fR; this is also the number of words in the command. .AP Tcl_Obj **objv in Points to an array of pointers to values; each value holds the value of a single word in the command to execute. .AP int numBytes in @@ -60,11 +60,11 @@ The number of bytes in \fIscript\fR, not including any null terminating character. If \-1, then all characters up to the first null byte are used. .AP "const char" *script in Points to first byte of script to execute (null-terminated and UTF-8). -.AP char *part in +.AP "const char" *part in String forming part of a Tcl script. .BE .SH DESCRIPTION .PP @@ -91,21 +91,19 @@ its contents as a Tcl script. It returns the same information as \fBTcl_EvalObjEx\fR. If the file could not be read then a Tcl error is returned to describe why the file could not be read. The eofchar for files is -.QW \e32 +.QW \ex1A (^Z) for all platforms. If you require a .QW ^Z in code for string comparison, you can use -.QW \e032 -or -.QW \eu001a , +.QW \ex1A , which will be safely substituted by the Tcl interpreter into .QW ^Z . .PP -\fBTcl_EvalObjv\fR executes a single pre-parsed command instead of a +\fBTcl_EvalObjv\fR executes a single preparsed command instead of a script. The \fIobjc\fR and \fIobjv\fR arguments contain the values of the words for the Tcl command, one word in each value in \fIobjv\fR. \fBTcl_EvalObjv\fR evaluates the command and returns a completion code and result just like \fBTcl_EvalObjEx\fR. The caller of \fBTcl_EvalObjv\fR has to manage the reference count of the @@ -138,15 +136,15 @@ 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. +of arguments. .SH "FLAG BITS" .PP -Any ORed combination of the following values may be used for the +Any OR'ed combination of the following values may be used for the \fIflags\fR argument to procedures such as \fBTcl_EvalObjEx\fR: .TP 23 \fBTCL_EVAL_DIRECT\fR . This flag is only used by \fBTcl_EvalObjEx\fR; it is ignored by @@ -188,8 +186,22 @@ 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 Index: doc/ExprLongObj.3 ================================================================== --- doc/ExprLongObj.3 +++ doc/ExprLongObj.3 @@ -96,10 +96,19 @@ 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 Index: doc/FileSystem.3 ================================================================== --- doc/FileSystem.3 +++ doc/FileSystem.3 @@ -43,11 +43,11 @@ .sp int \fBTcl_FSDeleteFile\fR(\fIpathPtr\fR) .sp int -\fBTcl_FSRemoveDirectory\fR(\fIpathPtr, int recursive, errorPtr\fR) +\fBTcl_FSRemoveDirectory\fR(\fIpathPtr, recursive, errorPtr\fR) .sp int \fBTcl_FSRenameFile\fR(\fIsrcPathPtr, destPathPtr\fR) .sp Tcl_Obj * @@ -77,14 +77,14 @@ .sp int \fBTcl_FSUtime\fR(\fIpathPtr, tval\fR) .sp int -\fBTcl_FSFileAttrsGet\fR(\fIinterp, int index, pathPtr, objPtrRef\fR) +\fBTcl_FSFileAttrsGet\fR(\fIinterp, index, pathPtr, objPtrRef\fR) .sp int -\fBTcl_FSFileAttrsSet\fR(\fIinterp, int index, pathPtr, Tcl_Obj *objPtr\fR) +\fBTcl_FSFileAttrsSet\fR(\fIinterp, index, pathPtr, objPtr\fR) .sp const char *const * \fBTcl_FSFileAttrStrings\fR(\fIpathPtr, objPtrRef\fR) .sp int @@ -142,20 +142,20 @@ \fBTcl_FSFileSystemInfo\fR(\fIpathPtr\fR) .sp Tcl_StatBuf * \fBTcl_AllocStatBuf\fR() .sp -Tcl_WideInt +long long \fBTcl_GetAccessTimeFromStat\fR(\fIstatPtr\fR) .sp unsigned \fBTcl_GetBlockSizeFromStat\fR(\fIstatPtr\fR) .sp -Tcl_WideUInt +unsigned long long \fBTcl_GetBlocksFromStat\fR(\fIstatPtr\fR) .sp -Tcl_WideInt +long long \fBTcl_GetChangeTimeFromStat\fR(\fIstatPtr\fR) .sp int \fBTcl_GetDeviceTypeFromStat\fR(\fIstatPtr\fR) .sp @@ -172,14 +172,14 @@ \fBTcl_GetLinkCountFromStat\fR(\fIstatPtr\fR) .sp unsigned \fBTcl_GetModeFromStat\fR(\fIstatPtr\fR) .sp -Tcl_WideInt +long long \fBTcl_GetModificationTimeFromStat\fR(\fIstatPtr\fR) .sp -Tcl_WideUInt +unsigned long long \fBTcl_GetSizeFromStat\fR(\fIstatPtr\fR) .sp int \fBTcl_GetUserIdFromStat\fR(\fIstatPtr\fR) .SH ARGUMENTS @@ -195,10 +195,12 @@ 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. @@ -216,20 +218,24 @@ .AP Tcl_Obj *secondPtr in The second of two path values to compare. The value may be converted to \fBpath\fR type. .AP Tcl_Obj *listObj in The list of path elements to operate on with a \fBjoin\fR operation. -.AP int elements in -If non-negative, the number of elements in the \fIlistObj\fR which should +.AP Tcl_Size elements in +The number of elements in the \fIlistObj\fR which should be joined together. If negative, then all elements are joined. .AP Tcl_Obj **errorPtr out In the case of an error, filled with a value containing the name of the file which caused an error in the various copy/rename operations. +.AP int index in +The index of the attribute in question. +.AP Tcl_Obj *objPtr in +The value to set in the operation. .AP Tcl_Obj **objPtrRef out Filled with a value containing the result of the operation. .AP Tcl_Obj *resultPtr out -Pre-allocated value in which to store (using +Preallocated value in which to store (using \fBTcl_ListObjAppendElement\fR) the list of files or directories which are successfully matched. .AP int mode in Mask consisting of one or more of R_OK, W_OK, X_OK and F_OK. R_OK, W_OK and X_OK request checking whether the file exists and has read, @@ -239,13 +245,13 @@ The structure that contains the result of a stat or lstat operation. .AP "const char" *sym1 in Name of a procedure to look up in the file's symbol table .AP "const char" *sym2 in Name of a procedure to look up in the file's symbol table -.AP Tcl_PackageInitProc **proc1Ptr out +.AP Tcl_LibraryInitProc **proc1Ptr out Filled with the init function for this code. -.AP Tcl_PackageInitProc **proc2Ptr out +.AP Tcl_LibraryInitProc **proc2Ptr out Filled with the safe-init function for this code. .AP void **clientDataPtr out Filled with the clientData value to pass to this code's unload function when it is called. .AP Tcl_LoadHandle *loadHandlePtr out @@ -261,15 +267,15 @@ 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 +.AP "Tcl_Size \&| 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 +.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. @@ -417,18 +423,16 @@ If \fIencodingName\fR is NULL, the utf-8 encoding is used for reading the file contents. If the file could not be read then a Tcl error is returned to describe why the file could not be read. The eofchar for files is -.QW \e32 +.QW \ex1A (^Z) for all platforms. If you require a .QW ^Z in code for string comparison, you can use -.QW \e032 -or -.QW \eu001a , +.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. @@ -477,11 +481,11 @@ 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. +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 @@ -643,11 +647,11 @@ \fBTcl_FSEqualPaths\fR tests whether the two paths given represent the same filesystem object. It returns 1 if the paths are equal, and 0 if they are different. If either path is NULL, 0 is always returned. .PP -\fBTcl_FSGetNormalizedPath\fR this important function attempts to extract +\fBTcl_FSGetNormalizedPath\fR attempts to extract from the given Tcl_Obj a unique normalized path representation, whose string value can be used as a unique identifier for the file. .PP It returns the normalized path value, owned by Tcl, or NULL if the path was invalid or could otherwise not be successfully converted. @@ -672,15 +676,10 @@ 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 ~ -(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. @@ -698,18 +697,11 @@ \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 +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 @@ -844,11 +836,11 @@ The \fBTcl_Filesystem\fR structure contains the following fields: .PP .CS typedef struct Tcl_Filesystem { const char *\fItypeName\fR; - int \fIstructureLength\fR; + Tcl_Size \fIstructureLength\fR; Tcl_FSVersion \fIversion\fR; Tcl_FSPathInFilesystemProc *\fIpathInFilesystemProc\fR; Tcl_FSDupInternalRepProc *\fIdupInternalRepProc\fR; Tcl_FSFreeInternalRepProc *\fIfreeInternalRepProc\fR; Tcl_FSInternalToNormalizedProc *\fIinternalToNormalizedProc\fR; @@ -1062,13 +1054,11 @@ 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 ~ , +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 @@ -1626,9 +1616,161 @@ .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 Index: doc/FindExec.3 ================================================================== --- doc/FindExec.3 +++ doc/FindExec.3 @@ -11,11 +11,11 @@ Tcl_FindExecutable, Tcl_GetNameOfExecutable \- identify or return the name of the binary file containing the application .SH SYNOPSIS .nf \fB#include \fR .sp -void +const char * \fBTcl_FindExecutable\fR(\fIargv0\fR) .sp const char * \fBTcl_GetNameOfExecutable\fR() .SH ARGUMENTS @@ -32,10 +32,13 @@ 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. Index: doc/GetCwd.3 ================================================================== --- doc/GetCwd.3 +++ doc/GetCwd.3 @@ -15,21 +15,21 @@ .sp char * \fBTcl_GetCwd\fR(\fIinterp\fR, \fIbufferPtr\fR) .sp int -\fBTcl_Chdir\fR(\fIpath\fR) +\fBTcl_Chdir\fR(\fIdirName\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 +.AP "const char" *dirName in File path in UTF\-8 format. .BE .SH DESCRIPTION .PP @@ -43,10 +43,10 @@ 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 +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 Index: doc/GetHostName.3 ================================================================== --- doc/GetHostName.3 +++ doc/GetHostName.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH Tcl_GetHostName 3 8.3 Tcl "Tcl Library Procedures" .so man.macros .BS Index: doc/GetIndex.3 ================================================================== --- doc/GetIndex.3 +++ doc/GetIndex.3 @@ -52,14 +52,16 @@ Null-terminated string describing what is being looked up, such as \fBoption\fR. This string is included in error messages. .AP int flags in OR-ed combination of bits providing additional information for operation. The only bits that are currently defined are \fBTCL_EXACT\fR -and \fBTCL_INDEX_TEMP_TABLE\fR. -.AP int *indexPtr out -The index of the string in \fItablePtr\fR that matches the value of -\fIobjPtr\fR is returned here. +, \fBTCL_INDEX_TEMP_TABLE\fR, and \fBTCL_NULL_OK\fR. +.AP enum|char|short|int|long *indexPtr out +If not (int *)NULL, the index of the string in \fItablePtr\fR that +matches the value of \fIobjPtr\fR is returned here. The variable can +be any integer type, signed or unsigned, char, short, long or +long long. It can also be an enum. .BE .SH DESCRIPTION .PP These procedures provide an efficient way for looking up keywords, switch names, option names, and similar things where the literal value of @@ -68,12 +70,12 @@ 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. +\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, @@ -89,11 +91,13 @@ 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, +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 @@ -103,9 +107,15 @@ 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 Index: doc/GetInt.3 ================================================================== --- doc/GetInt.3 +++ doc/GetInt.3 @@ -19,11 +19,14 @@ .sp int \fBTcl_GetDouble\fR(\fIinterp, src, doublePtr\fR) .sp int -\fBTcl_GetBoolean\fR(\fIinterp, src, boolPtr\fR) +\fBTcl_GetBoolean\fR(\fIinterp, src, intPtr\fR) +.sp +int +\fBTcl_GetBool\fR(\fIinterp, src, flags, charPtr\fR) .SH ARGUMENTS .AS Tcl_Interp *doublePtr out .AP Tcl_Interp *interp in Interpreter to use for error reporting. .AP "const char" *src in @@ -31,12 +34,16 @@ .AP int *intPtr out Points to place to store integer value converted from \fIsrc\fR. .AP double *doublePtr out Points to place to store double-precision floating-point value converted from \fIsrc\fR. -.AP int *boolPtr out -Points to place to store boolean value (0 or 1) converted from \fIsrc\fR. +.AP char *charPtr out +Points to place to store boolean value (0 or 1) value converted from \fIsrc\fR. +.AP int flags in +0 or TCL_NULL_OK. If TCL_NULL_OK +is used, then the empty string or NULL will result in \fBTcl_GetBool\fR +return TCL_OK, the *charPtr filled with the value \fB'\exFF'\fR; .BE .SH DESCRIPTION .PP These procedures convert from strings to integers or double-precision @@ -46,11 +53,11 @@ the converted value at the location indicated by the procedure's third argument. If all goes well, each of the procedures returns \fBTCL_OK\fR. If \fIsrc\fR does not have the proper syntax for the desired type then \fBTCL_ERROR\fR is returned, an error message is left in the interpreter's result, and nothing is stored at *\fIintPtr\fR -or *\fIdoublePtr\fR or *\fIboolPtr\fR. +or *\fIdoublePtr\fR. .PP \fBTcl_GetInt\fR expects \fIsrc\fR to consist of a collection of integer digits, optionally signed and optionally preceded and followed by white space. If the first two characters of \fIsrc\fR after the optional white space and sign are @@ -89,13 +96,17 @@ inter-digit separator be present. .PP \fBTcl_GetBoolean\fR expects \fIsrc\fR to specify a boolean value. If \fIsrc\fR is any of \fB0\fR, \fBfalse\fR, \fBno\fR, or \fBoff\fR, then \fBTcl_GetBoolean\fR stores a zero -value at \fI*boolPtr\fR. +value at \fI*intPtr\fR. If \fIsrc\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR, -then 1 is stored at \fI*boolPtr\fR. +then 1 is stored at \fI*intPtr\fR. Any of these values may be abbreviated, and upper-case spellings are also acceptable. +.PP +\fBTcl_GetBool\fR functions almost the same as \fBTcl_GetBoolean\fR, +but it has an additional parameter \fBflags\fR, which can be used +to specify whether the empty string or NULL is accepted as valid. .SH KEYWORDS boolean, conversion, double, floating-point, integer Index: doc/GetStdChan.3 ================================================================== --- doc/GetStdChan.3 +++ doc/GetStdChan.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1996 by Sun Microsystems, Inc. +'\" Copyright (c) 1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_GetStdChannel 3 7.5 Tcl "Tcl Library Procedures" Index: doc/GetTime.3 ================================================================== --- doc/GetTime.3 +++ doc/GetTime.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 2001 by Kevin B. Kenny . +'\" Copyright (c) 2001 Kevin B. Kenny . '\" '\" 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" @@ -42,11 +42,11 @@ \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 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 Index: doc/GetVersion.3 ================================================================== --- doc/GetVersion.3 +++ doc/GetVersion.3 @@ -13,18 +13,17 @@ .nf \fB#include \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 +.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 Index: doc/Hash.3 ================================================================== --- doc/Hash.3 +++ doc/Hash.3 @@ -322,7 +322,21 @@ .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 Index: doc/Init.3 ================================================================== --- doc/Init.3 +++ doc/Init.3 @@ -1,10 +1,10 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" -.TH Tcl_Init 3 8.0 Tcl "Tcl Library Procedures" +.TH Tcl_Init 3 9.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Init \- find and source initialization script .SH SYNOPSIS @@ -11,24 +11,40 @@ .nf \fB#include \fR .sp int \fBTcl_Init\fR(\fIinterp\fR) +.sp +const char * +\fBTcl_SetPreInitScript\fR(\fIscriptPtr\fR) .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. + +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 Index: doc/InitSubSyst.3 ================================================================== --- doc/InitSubSyst.3 +++ doc/InitSubSyst.3 @@ -11,21 +11,24 @@ Tcl_InitSubsystems \- initialize the Tcl library. .SH SYNOPSIS .nf \fB#include \fR .sp -void +const char * \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 +The result of \fBTcl_InitSubsystems\fR is the full Tcl version with +build information (e.g., \fB9.0.0+abcdef...abcdef.gcc-1002\fR). +.PP \fBTcl_InitSubsystems\fR is very similar in use to \fBTcl_FindExecutable\fR. It can be used when Tcl is used as utility library, no other encodings than utf-8, -iso8859-1 or unicode are used, and no interest exists in the +iso8859-1 or utf-16 are used, and no interest exists in the value of \fBinfo nameofexecutable\fR. The system encoding will not be extracted from the environment, but falls back to utf-8. .SH KEYWORDS binary, executable file Index: doc/IntObj.3 ================================================================== --- doc/IntObj.3 +++ doc/IntObj.3 @@ -6,11 +6,11 @@ '\" .TH Tcl_IntObj 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers +Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_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 \fR .sp Tcl_Obj * @@ -30,18 +30,24 @@ .sp int \fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR) .sp int -\fBTcl_GetIntForIndex\fR(\fIinterp, objPtr, endValue, intPtr\fR) +\fBTcl_GetIntForIndex\fR(\fIinterp, objPtr, endValue, indexPtr\fR) .sp int \fBTcl_GetLongFromObj\fR(\fIinterp, objPtr, longPtr\fR) .sp int \fBTcl_GetWideIntFromObj\fR(\fIinterp, objPtr, widePtr\fR) .sp +int +\fBTcl_GetWideUIntFromObj\fR(\fIinterp, objPtr, uwidePtr\fR) +.sp +int +\fBTcl_GetSizeIntFromObj\fR(\fIinterp, objPtr, sizePtr\fR) +.sp .sp \fB#include \fR .sp Tcl_Obj * \fBTcl_NewBignumObj\fR(\fIbigValue\fR) @@ -56,11 +62,11 @@ .sp int \fBTcl_InitBignumFromDouble\fR(\fIinterp, doubleValue, bigValue\fR) .SH ARGUMENTS .AS Tcl_WideInt doubleValue in/out -.AP int endValue in +.AP Tcl_Size endValue in \fBTcl_GetIntForIndex\fR will return this when the input value is "end". .AP int intValue in Integer value used to initialize or set a Tcl value. .AP long longValue in Long integer value used to initialize or set a Tcl value. @@ -78,12 +84,18 @@ 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 @@ -100,11 +112,11 @@ \fBTcl_WideInt\fR, and \fBmp_int\fR. The \fBint\fR and \fBlong int\fR types are provided by the C language standard. The \fBTcl_WideInt\fR type is a typedef defined to be whatever signed integral type covers at least the 64-bit integer range (-9223372036854775808 to 9223372036854775807). Depending on the platform and the C compiler, the actual type might be -\fBlong long int\fR, \fB__int64\fR, or something else. +\fBlong long int\fR, or something else. The \fBmp_int\fR type is a multiple-precision integer type defined by the LibTomMath multiple-precision integer library. .PP The \fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR, \fBTcl_NewWideIntObj\fR, and \fBTcl_NewBignumObj\fR routines each create and return a new @@ -129,11 +141,12 @@ an error message is left in \fIinterp\fR. The \fBTcl_ObjType\fR of \fIobjPtr\fR may be changed to make subsequent calls to the same routine more efficient. .PP The \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR, -\fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and +\fBTcl_GetWideIntFromObj\fR, \fBTcl_GetSizeIntFromObj\fR, +\fBTcl_GetBignumFromObj\fR, and \fBTcl_TakeBignumFromObj\fR routines attempt to retrieve an integral value of the appropriate type from the Tcl value \fIobjPtr\fR. If the attempt succeeds, then \fBTCL_OK\fR is returned, and the value is written to the storage provided by the caller. The attempt might fail if \fIobjPtr\fR does not hold an integral value, or if the @@ -158,10 +171,31 @@ \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 Index: doc/Limit.3 ================================================================== --- doc/Limit.3 +++ doc/Limit.3 @@ -63,11 +63,11 @@ Interpreter that the limit being managed applies to or that will have its limits checked. .AP int type in The type of limit that the operation refers to. This must be either \fBTCL_LIMIT_COMMANDS\fR or \fBTCL_LIMIT_TIME\fR. -.AP int commandLimit in +.AP Tcl_Size commandLimit in The maximum number of commands (as reported by \fBinfo cmdcount\fR) that may be executed in the interpreter. .AP Tcl_Time *timeLimitPtr in/out A pointer to a structure that will either have the new time limit read from (\fBTcl_LimitSetTime\fR) or the current time limit written to Index: doc/LinkVar.3 ================================================================== --- doc/LinkVar.3 +++ doc/LinkVar.3 @@ -51,17 +51,17 @@ In \fBTcl_LinkVar\fR, the additional linked type \fBTCL_LINK_STRING\fR may be used. .sp .VS "TIP 312" In \fBTcl_LinkArray\fR, the additional linked types \fBTCL_LINK_CHARS\fR and -\fBTCL_LINK_BYTES\fR may be used. +\fBTCL_LINK_BINARY\fR may be used. .VE "TIP 312" .sp All the above for both functions may be optionally OR'ed with \fBTCL_LINK_READ_ONLY\fR to make the Tcl variable read-only. -.AP size_t size in +.AP Tcl_Size size in .VS "TIP 312" The number of elements in the C array. Must be greater than zero. .VE "TIP 312" .BE .SH DESCRIPTION @@ -144,15 +144,15 @@ representations (like the empty string, '+', '-' or the hex/octal/decimal/binary prefix) are accepted as if they are valid too. .RS .PP .VS "TIP 312" -If using an array of these, consider using \fBTCL_LINK_BYTES\fR instead. +If using an array of these, consider using \fBTCL_LINK_BINARY\fR instead. .VE "TIP 312" .RE .TP -\fBTCL_LINK_BYTES\fR +\fBTCL_LINK_BINARY\fR .VS "TIP 312" The C array is of type \fBunsigned char *\fR and is mapped into Tcl as a bytearray. Any value written into the Tcl variable must have the same length as the underlying storage. Only supported with \fBTcl_LinkArray\fR. @@ -237,13 +237,11 @@ . 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. +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 Index: doc/ListObj.3 ================================================================== --- doc/ListObj.3 +++ doc/ListObj.3 @@ -26,11 +26,11 @@ .sp int \fBTcl_ListObjGetElements\fR(\fIinterp, listPtr, objcPtr, objvPtr\fR) .sp int -\fBTcl_ListObjLength\fR(\fIinterp, listPtr, intPtr\fR) +\fBTcl_ListObjLength\fR(\fIinterp, listPtr, lengthPtr\fR) .sp int \fBTcl_ListObjIndex\fR(\fIinterp, listPtr, index, objPtrPtr\fR) .sp int @@ -57,17 +57,17 @@ For \fBTcl_ListObjAppendElement\fR, points to the Tcl value that will be appended to \fIlistPtr\fR. For \fBTcl_SetListObj\fR, this points to the Tcl value that will be converted to a list value containing the \fIobjc\fR elements of the array referenced by \fIobjv\fR. -.AP int *objcPtr in +.AP "Tcl_Size \&| int" *objcPtr in Points to location where \fBTcl_ListObjGetElements\fR stores the number of element values in \fIlistPtr\fR. .AP Tcl_Obj ***objvPtr out A location where \fBTcl_ListObjGetElements\fR stores a pointer to an array of pointers to the element values of \fIlistPtr\fR. -.AP int objc in +.AP Tcl_Size objc in The number of Tcl values that \fBTcl_NewListObj\fR will insert into a new list value, and \fBTcl_ListObjReplace\fR will insert into \fIlistPtr\fR. For \fBTcl_SetListObj\fR, the number of Tcl values to insert into \fIobjPtr\fR. @@ -74,25 +74,25 @@ .AP "Tcl_Obj *const" objv[] in An array of pointers to values. \fBTcl_NewListObj\fR will insert these values into a new list value and \fBTcl_ListObjReplace\fR will insert them into an existing \fIlistPtr\fR. Each value will become a separate list element. -.AP int *intPtr out +.AP "Tcl_Size \&| int" *lengthPtr out Points to location where \fBTcl_ListObjLength\fR stores the length of the list. -.AP int index in +.AP Tcl_Size index in Index of the list element that \fBTcl_ListObjIndex\fR is to return. The first element has index 0. .AP Tcl_Obj **objPtrPtr out Points to place where \fBTcl_ListObjIndex\fR is to store a pointer to the resulting list element value. -.AP int first in +.AP Tcl_Size first in Index of the starting list element that \fBTcl_ListObjReplace\fR is to replace. The list's first element has index 0. -.AP int count in +.AP Tcl_Size count in The number of elements that \fBTcl_ListObjReplace\fR is to replace. .BE .SH DESCRIPTION @@ -151,20 +151,24 @@ the elements in a list value. It returns the count by storing it in the address \fIobjcPtr\fR. Similarly, it returns the array pointer by storing it in the address \fIobjvPtr\fR. The memory pointed to is managed by Tcl and should not be freed or written to by the caller. If the list is empty, 0 is stored at \fIobjcPtr\fR -and NULL at \fIobjvPtr\fR. +and NULL at \fIobjvPtr\fR. If \fIobjcPtr\fR points to a variable +of type \fBint\fR and the list contains more than 2**31 elements, the +function returns \fBTCL_ERROR\fR. If \fIlistPtr\fR is not already a list value, \fBTcl_ListObjGetElements\fR will attempt to convert it to one; if the conversion fails, it returns \fBTCL_ERROR\fR and leaves an error message in the interpreter's result value if \fIinterp\fR is not NULL. Otherwise it returns \fBTCL_OK\fR after storing the count and array pointer. .PP \fBTcl_ListObjLength\fR returns the number of elements in the list value referenced by \fIlistPtr\fR. -It returns this count by storing an integer in the address \fIintPtr\fR. +It returns this count by storing a value in the address \fIlengthPtr\fR. +If \fIlengthPtr\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 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. @@ -244,10 +248,35 @@ .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 Index: doc/Load.3 ================================================================== --- doc/Load.3 +++ doc/Load.3 @@ -58,10 +58,14 @@ .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: Index: doc/Method.3 ================================================================== --- doc/Method.3 +++ doc/Method.3 @@ -56,11 +56,11 @@ \fBTcl_ObjectContextMethod\fR(\fIcontext\fR) .sp Tcl_Object \fBTcl_ObjectContextObject\fR(\fIcontext\fR) .sp -int +Tcl_Size \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. @@ -93,15 +93,15 @@ .AP Tcl_Method method in A reference to a method to query. .AP Tcl_ObjectContext context in A reference to a method-call context. Note that client code \fImust not\fR retain a reference to a context. -.AP int objc in +.AP Tcl_Size objc in The number of arguments to pass to the method implementation. .AP "Tcl_Obj *const" *objv in An array of arguments to pass to the method implementation. -.AP int skip in +.AP Tcl_Size skip in The number of arguments passed to the method implementation that do not represent "real" arguments. .BE .SH DESCRIPTION .PP @@ -256,14 +256,38 @@ attempt to clone the object is to fail, in which case the clone procedure must also return TCL_ERROR; it should return TCL_OK otherwise. The \fIoldClientData\fR field to a Tcl_CloneProc gives the value from the method being copied from, and the \fInewClientDataPtr\fR field will point to a variable in which to write the value for the method being copied to. +.SH "REFERENCE COUNT MANAGEMENT" +.PP +The \fInameObj\fR argument to \fBTcl_NewMethod\fR and +\fBTcl_NewInstanceMethod\fR (when non-NULL) will have its reference count +incremented if there is no existing method with that name in that +class/object. +.PP +The result of \fBTcl_MethodName\fR is a value with a reference count of at +least one. It should not be modified without first duplicating it (with +\fBTcl_DuplicateObj\fR). +.PP +The values in the first \fIobjc\fR values of the \fIobjv\fR argument to +\fBTcl_ObjectContextInvokeNext\fR are assumed to have a reference count of at +least 1; the containing array is assumed to endure until the next method +implementation (see \fBnext\fR) returns. Be aware that methods may +\fByield\fR; if any post-call actions are desired (e.g., decrementing the +reference count of values passed in here), they must be scheduled with +\fBTcl_NRAddCallback\fR. +.PP +The \fIcallProc\fR of the \fBTcl_MethodType\fR structure takes values of at +least reference count 1 in its \fIobjv\fR argument. It may add its own +references, but must not decrement the reference count below that level; the +caller of the method will decrement the reference count once the method +returns properly (and the reference will be held if the method \fByield\fRs). .SH "SEE ALSO" -Class(3), oo::class(n), oo::define(n), oo::object(n) +Class(3), NRE(3), oo::class(n), oo::define(n), oo::object(n) .SH KEYWORDS constructor, method, object .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: Index: doc/NRE.3 ================================================================== --- doc/NRE.3 +++ doc/NRE.3 @@ -1,28 +1,35 @@ .\" -.\" Copyright (c) 2008 by Kevin B. Kenny. -.\" Copyright (c) 2018 by Nathan Coulter. +.\" Copyright (c) 2008 Kevin B. Kenny. +.\" Copyright (c) 2018 Nathan Coulter. .\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH NRE 3 8.6 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_NRCreateCommand, Tcl_NRCallObjProc, Tcl_NREvalObj, Tcl_NREvalObjv, Tcl_NRCmdSwap, Tcl_NRExprObj, Tcl_NRAddCallback \- Non-Recursive (stackless) evaluation of Tcl scripts. +Tcl_NRCreateCommand, Tcl_NRCreateCommand2, Tcl_NRCallObjProc, Tcl_NRCallObjProc2, Tcl_NREvalObj, Tcl_NREvalObjv, Tcl_NRCmdSwap, Tcl_NRExprObj, Tcl_NRAddCallback \- Non-Recursive (stackless) evaluation of Tcl scripts. .SH SYNOPSIS .nf \fB#include \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) @@ -38,26 +45,33 @@ .fi .SH ARGUMENTS .AS Tcl_CmdDeleteProc *interp in .AP Tcl_Interp *interp in The relevant Interpreter. -.AP char *cmdName in +.AP "const char" *cmdName in Name of the command to create. .AP Tcl_ObjCmdProc *proc in Called in order to evaluate a command. Is often just a small wrapper that uses \fBTcl_NRCallObjProc\fR to call \fInreProc\fR using a new trampoline. Behaves in the same way as the \fIproc\fR argument to \fBTcl_CreateObjCommand\fR(3) (\fIq.v.\fR). +.AP Tcl_ObjCmdProc2 *proc2 in +Called in order to evaluate a command. Is often just a small wrapper that uses +\fBTcl_NRCallObjProc2\fR to call \fInreProc2\fR using a new trampoline. Behaves +in the same way as the \fIproc2\fR argument to \fBTcl_CreateObjCommand2\fR(3) +(\fIq.v.\fR). .AP Tcl_ObjCmdProc *nreProc in Called instead of \fIproc\fR when a trampoline is already in use. +.AP Tcl_ObjCmdProc2 *nreProc2 in +Called instead of \fIproc2\fR when a trampoline is already in use. .AP void *clientData in Arbitrary one-word value passed to \fIproc\fR, \fInreProc\fR, \fIdeleteProc\fR and \fIobjProc\fR. .AP Tcl_CmdDeleteProc *deleteProc in/out Called before \fIcmdName\fR is deleted from the interpreter, allowing for command-specific cleanup. May be NULL. -.AP int objc in +.AP Tcl_Size objc in Number of items in \fIobjv\fR. .AP Tcl_Obj **objv in Words in the command. .AP Tcl_Obj *objPtr in A script or expression to evaluate. @@ -101,10 +115,13 @@ 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 @@ -225,12 +242,31 @@ .CE .PP Any function comprising a routine can push other functions, making it possible implement looping and sequencing constructs using the function stack. .PP +.SH "REFERENCE COUNT MANAGEMENT" +.PP +The first \fIobjc\fR values in the \fIobjv\fR array passed to the functions +\fBTcl_NRCallObjProc\fR, \fBTcl_NREvalObjv\fR, and \fBTcl_NRCmdSwap\fR should +have a reference count of at least 1; they may have additional references +taken during the execution. +.PP +The \fIobjPtr\fR argument to \fBTcl_NREvalObj\fR and \fBTcl_NRExprObj\fR +should have a reference count of at least 1, and may have additional +references taken to it during execution. +.PP +The \fIresultObj\fR argument to \fBTcl_NRExprObj\fR should be an unshared +object. +.PP +Use \fBTcl_NRAddCallback\fR to schedule any required final decrementing of the +reference counts of arguments to any of the other functions on this page, as +with any other post-processing step in the non-recursive execution engine. +.PP +The .SH "SEE ALSO" Tcl_CreateCommand(3), Tcl_CreateObjCommand(3), Tcl_EvalObjEx(3), Tcl_GetCommandFromObj(3), Tcl_ExprObj(3) .SH KEYWORDS stackless, nonrecursive, execute, command, global, value, result, script .SH COPYRIGHT -Copyright (c) 2008 by Kevin B. Kenny. -Copyright (c) 2018 by Nathan Coulter. +Copyright \(co 2008 Kevin B. Kenny. +Copyright \(co 2018 Nathan Coulter. Index: doc/Namespace.3 ================================================================== --- doc/Namespace.3 +++ doc/Namespace.3 @@ -44,14 +44,14 @@ .sp Tcl_Command \fBTcl_FindCommand\fR(\fIinterp, name, contextNsPtr, flags\fR) .sp Tcl_Obj * -\fBTcl_GetNamespaceUnknownHandler(\fIinterp, nsPtr\fR) +\fBTcl_GetNamespaceUnknownHandler\fR(\fIinterp, nsPtr\fR) .sp int -\fBTcl_SetNamespaceUnknownHandler(\fIinterp, nsPtr, handlerPtr\fR) +\fBTcl_SetNamespaceUnknownHandler\fR(\fIinterp, nsPtr, handlerPtr\fR) .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. @@ -131,11 +131,11 @@ namespace. Patterns are appended unless the \fIresetListFirst\fR flag is true. .PP \fBTcl_Import\fR imports commands matching a pattern into a namespace. Note that the pattern must include the name of the -namespace to import from. This function returns an error if +namespace to import from. This function returns TCL_ERROR if an attempt to import a command over an existing command is made, unless the \fIallowOverwrite\fR flag has been set. .PP \fBTcl_ForgetImport\fR removes imports matching a pattern. .PP @@ -157,9 +157,21 @@ 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 Index: doc/Notifier.3 ================================================================== --- doc/Notifier.3 +++ doc/Notifier.3 @@ -88,13 +88,14 @@ is NULL, it means there is no maximum wait time: wait forever if necessary. .AP Tcl_Event *evPtr in An event to add to the event queue. The storage for the event must have been allocated by the caller using \fBTcl_Alloc\fR. -.AP Tcl_QueuePosition position in +.AP int position in Where to add the new event in the queue: \fBTCL_QUEUE_TAIL\fR, -\fBTCL_QUEUE_HEAD\fR, or \fBTCL_QUEUE_MARK\fR. +\fBTCL_QUEUE_HEAD\fR, \fBTCL_QUEUE_MARK\fR, and whether to do +an alert if the queue is empty: \fBTCL_QUEUE_ALERT_IF_EMPTY\fR. .AP Tcl_ThreadId threadId in A unique identifier for a thread. .AP Tcl_EventDeleteProc *deleteProc in Procedure to invoke for each queued event in \fBTcl_DeleteEvents\fR. .AP int flags in @@ -101,11 +102,11 @@ What types of events to service. These flags are the same as those passed to \fBTcl_DoOneEvent\fR. .AP int mode in Indicates whether events should be serviced by \fBTcl_ServiceAll\fR. Must be one of \fBTCL_SERVICE_NONE\fR or \fBTCL_SERVICE_ALL\fR. -.AP Tcl_NotifierProcs* notifierProcPtr in +.AP const Tcl_NotifierProcs* notifierProcPtr in Structure of function pointers describing notifier procedures that are to replace the ones installed in the executable. See \fBREPLACING THE NOTIFIER\fR for details. .BE .SH INTRODUCTION @@ -264,11 +265,11 @@ a structure that describes a time interval in seconds and microseconds: .PP .CS typedef struct Tcl_Time { - long \fIsec\fR; + long long \fIsec\fR; long \fIusec\fR; } \fBTcl_Time\fR; .CE .PP The \fIusec\fR field should be less than 1000000. @@ -338,25 +339,29 @@ The \fInextPtr\fR is used to link together the events in the queue and should not be modified by the event source. .PP An event may be added to the queue at any of three positions, depending on the \fIposition\fR argument to \fBTcl_QueueEvent\fR: -.IP \fBTCL_QUEUE_TAIL\fR 24 +.IP \fBTCL_QUEUE_TAIL\fR 32 Add the event at the back of the queue, so that all other pending events will be serviced first. This is almost always the right place for new events. -.IP \fBTCL_QUEUE_HEAD\fR 24 +.IP \fBTCL_QUEUE_HEAD\fR 32 Add the event at the front of the queue, so that it will be serviced before all other queued events. -.IP \fBTCL_QUEUE_MARK\fR 24 +.IP \fBTCL_QUEUE_MARK\fR 32 Add the event at the front of the queue, unless there are other events at the front whose position is \fBTCL_QUEUE_MARK\fR; if so, add the new event just after all other \fBTCL_QUEUE_MARK\fR events. This value of \fIposition\fR is used to insert an ordered sequence of events at the front of the queue, such as a series of Enter and Leave events synthesized during a grab or ungrab operation in Tk. +.IP \fBTCL_QUEUE_ALERT_IF_EMPTY\fR 32 +When used in \fBTcl_ThreadQueueEvent\fR +arranges for an automatic call of \fBTcl_ThreadAlert\fR when the queue was +empty. .PP When it is time to handle an event from the queue (steps 1 and 4 above) \fBTcl_ServiceEvent\fR will invoke the \fIproc\fR specified in the first queued \fBTcl_Event\fR structure. \fIProc\fR must match the following prototype: ADDED doc/Number.3 Index: doc/Number.3 ================================================================== --- /dev/null +++ doc/Number.3 @@ -0,0 +1,123 @@ +'\" +'\" 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 \fR +.sp +\fB#include \fR +.sp +int +\fBTcl_GetNumber\fR(\fIinterp, bytes, numBytes, clientDataPtr, typePtr\fR) +.sp +int +\fBTcl_GetNumberFromObj\fR(\fIinterp, objPtr, clientDataPtr, typePtr\fR) +.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 Index: doc/Object.3 ================================================================== --- doc/Object.3 +++ doc/Object.3 @@ -6,11 +6,11 @@ '\" .TH Tcl_Obj 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl values +Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_BounceRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl values .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * @@ -20,10 +20,12 @@ \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) @@ -109,13 +111,13 @@ 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; + Tcl_Size \fIrefCount\fR; char *\fIbytes\fR; - size_t \fIlength\fR; + Tcl_Size \fIlength\fR; const Tcl_ObjType *\fItypePtr\fR; union { long \fIlongValue\fR; double \fIdoubleValue\fR; void *\fIotherValuePtr\fR; @@ -276,25 +278,31 @@ 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. +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. +\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. @@ -304,16 +312,29 @@ 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 +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 @@ -343,10 +364,15 @@ 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 Index: doc/ObjectType.3 ================================================================== --- doc/ObjectType.3 +++ doc/ObjectType.3 @@ -2,11 +2,11 @@ '\" Copyright (c) 1996-1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -.TH Tcl_ObjType 3 8.0 Tcl "Tcl Library Procedures" +.TH Tcl_ObjType 3 9.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_RegisterObjType, Tcl_GetObjType, Tcl_AppendAllObjTypes, Tcl_ConvertToType \- manipulate Tcl value types .SH SYNOPSIS @@ -91,26 +91,36 @@ 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: +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 Tcl_ObjType { 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. @@ -203,10 +213,11 @@ .PP The \fIdupIntRepProc\fR member contains the address of a function called to copy an internal representation from one value to another. .PP .CS + typedef void \fBTcl_DupInternalRepProc\fR( Tcl_Obj *\fIsrcPtr\fR, Tcl_Obj *\fIdupPtr\fR); .CE .PP @@ -226,10 +237,11 @@ .PP The \fIfreeIntRepProc\fR member contains the address of a function that is called when a value is freed. .PP .CS + typedef void \fBTcl_FreeInternalRepProc\fR( Tcl_Obj *\fIobjPtr\fR); .CE .PP The \fIfreeIntRepProc\fR function can deallocate the storage @@ -246,9 +258,176 @@ 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 compatability +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 +(Tcl_ObjTypeIndexProc) ( + 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 specifed. +.CS + +typedef int +(Tcl_ObjTypeSliceProc) ( + 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 +(Tcl_ObjTypeReverseProc) ( + 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 is a +correlary to the \fBTcl_ListObjGetElements\fR C API call. +.CS + +typedef int +(Tcl_ObjTypeGetElements) ( + 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* +Tcl_ObjTypeSetElement) ( + 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 modfying 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 +(Tcl_ObjTypeReplaceProc) ( + Tcl_Interp *interp, + Tcl_Obj *listObj, + Tcl_Size first, + Tcl_Size numToDelete, + Tcl_Size numToInsert, + Tcl_Obj *const insertObjs[]); +.CE +.SS "THE INOPERATORPROC 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 +(Tcl_ObjTypeInOperatorProc) ( + Tcl_Interp *interp, + Tcl_Obj *valueObj, + Tcl_Obj *listObj, + int *boolResult); +.CE +.SH "REFERENCE COUNT MANAGEMENT" +.PP +The \fIobjPtr\fR argument to \fBTcl_AppendAllObjTypes\fR should be an unshared +value; this function will not modify the reference count of that value, but +will modify its contents. If \fIobjPtr\fR is not (interpretable as) a list, +this function will set the interpreter result and produce an error; using an +unshared empty value is strongly recommended. +.PP +The \fIobjPtr\fR argument to \fBTcl_ConvertToType\fR can have any non-zero +reference count; this function will not modify the reference count, but may +write to the interpreter result on error so values that originate from there +should have an additional reference made before calling this. +.PP +None of the callback functions in the \fBTcl_ObjType\fR structure should +modify the reference count of their arguments, but if the values contain +subsidiary values (e.g., the elements of a list or the keys of a dictionary) +then those subsidiary values may have their reference counts modified. .SH "SEE ALSO" -Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3) +Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3), Tcl_BounceRefCount(3) .SH KEYWORDS internal representation, value, value type, string representation, type conversion Index: doc/OpenFileChnl.3 ================================================================== --- doc/OpenFileChnl.3 +++ doc/OpenFileChnl.3 @@ -45,38 +45,38 @@ \fBTcl_IsStandardChannel\fR(\fIchannel\fR) .sp int \fBTcl_Close\fR(\fIinterp, channel\fR) .sp -int +Tcl_Size \fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR) .sp -int +Tcl_Size \fBTcl_Read\fR(\fIchannel, readBuf, bytesToRead\fR) .sp -size_t +Tcl_Size \fBTcl_GetsObj\fR(\fIchannel, lineObjPtr\fR) .sp -size_t +Tcl_Size \fBTcl_Gets\fR(\fIchannel, lineRead\fR) .sp -size_t +Tcl_Size \fBTcl_Ungets\fR(\fIchannel, input, inputLen, addAtEnd\fR) .sp -size_t +Tcl_Size \fBTcl_WriteObj\fR(\fIchannel, writeObjPtr\fR) .sp -size_t +Tcl_Size \fBTcl_WriteChars\fR(\fIchannel, charBuf, bytesToWrite\fR) .sp -size_t +Tcl_Size \fBTcl_Write\fR(\fIchannel, byteBuf, bytesToWrite\fR) .sp -size_t +Tcl_Size \fBTcl_ReadRaw\fR(\fIchannel, readBuf, bytesToRead\fR) .sp -size_t +Tcl_Size \fBTcl_WriteRaw\fR(\fIchannel, byteBuf, bytesToWrite\fR) .sp int \fBTcl_Eof\fR(\fIchannel\fR) .sp @@ -90,14 +90,14 @@ \fBTcl_InputBuffered\fR(\fIchannel\fR) .sp int \fBTcl_OutputBuffered\fR(\fIchannel\fR) .sp -Tcl_WideInt +long long \fBTcl_Seek\fR(\fIchannel, offset, seekMode\fR) .sp -Tcl_WideInt +long long \fBTcl_Tell\fR(\fIchannel\fR) .sp int \fBTcl_TruncateChannel\fR(\fIchannel, length\fR) .sp @@ -117,11 +117,11 @@ Specifies how the file is to be accessed. May have any of the values allowed for the \fImode\fR argument to the Tcl \fBopen\fR command. .AP int permissions in POSIX-style permission flags such as 0644. If a new file is created, these permissions will be set on the created file. -.AP int argc in +.AP Tcl_Size argc in The number of elements in \fIargv\fR. .AP "const char" **argv in Arguments for constructing a command pipeline. These values have the same meaning as the non-switch arguments to the Tcl \fBexec\fR command. .AP int flags in @@ -152,20 +152,20 @@ A Tcl channel for input or output. Must have been the return value from a procedure such as \fBTcl_OpenFileChannel\fR. .AP Tcl_Obj *readObjPtr in/out A pointer to a Tcl value in which to store the characters read from the channel. -.AP size_t charsToRead in +.AP Tcl_Size charsToRead in The number of characters to read from the channel. If the channel's encoding is \fBbinary\fR, this is equivalent to the number of bytes to read from the channel. .AP int appendFlag in If non-zero, data read from the channel will be appended to the value. Otherwise, the data will replace the existing contents of the value. .AP char *readBuf out A buffer in which to store the bytes read from the channel. -.AP size_t bytesToRead in +.AP Tcl_Size bytesToRead in The number of bytes to read from the channel. The buffer \fIreadBuf\fR must be large enough to hold this many bytes. .AP Tcl_Obj *lineObjPtr in/out A pointer to a Tcl value in which to store the line read from the channel. The line read will be appended to the current value of the @@ -174,11 +174,11 @@ A pointer to a Tcl dynamic string in which to store the line read from the channel. Must have been initialized by the caller. The line read will be appended to any data already in the dynamic string. .AP "const char" *input in The input to add to a channel buffer. -.AP size_t inputLen in +.AP Tcl_Size inputLen in Length of the input .AP int addAtEnd in Flag indicating whether the input should be added to the end or beginning of the channel buffer. .AP Tcl_Obj *writeObjPtr in @@ -185,22 +185,22 @@ A pointer to a Tcl value whose contents will be output to the channel. .AP "const char" *charBuf in A buffer containing the characters to output to the channel. .AP "const char" *byteBuf in A buffer containing the bytes to output to the channel. -.AP size_t bytesToWrite in +.AP Tcl_Size bytesToWrite in The number of bytes to consume from \fIcharBuf\fR or \fIbyteBuf\fR and output to the channel. -.AP Tcl_WideInt offset in +.AP "long long" offset in How far to move the access point in the channel at which the next input or output operation will be applied, measured in bytes from the position given by \fIseekMode\fR. May be either positive or negative. .AP int seekMode in Relative to which point to seek; used with \fIoffset\fR to calculate the new access point for the channel. Legal values are \fBSEEK_SET\fR, \fBSEEK_CUR\fR, and \fBSEEK_END\fR. -.AP Tcl_WideInt length in +.AP "long long" length in The (non-negative) length to truncate the channel the channel to. .AP "const char" *optionName in The name of an option applicable to this channel, such as \fB\-blocking\fR. May have any of the values accepted by the \fBfconfigure\fR command. .AP Tcl_DString *optionValue in @@ -404,23 +404,25 @@ \fBTcl_ReadChars\fR consumes bytes from \fIchannel\fR, converting the bytes to UTF-8 based on the channel's encoding and storing the produced data in \fIreadObjPtr\fR's string representation. The return value of \fBTcl_ReadChars\fR is the number of characters, up to \fIcharsToRead\fR, that were stored in \fIreadObjPtr\fR. If an error occurs while reading, the -return value is \-1 and \fBTcl_ReadChars\fR records a POSIX error code that -can be retrieved with \fBTcl_GetErrno\fR. +return value is -1 and \fBTcl_ReadChars\fR records a POSIX error +code that can be retrieved with \fBTcl_GetErrno\fR. If an encoding error happens +while the channel is in blocking mode with -profile strict, the characters +retrieved until the encoding error happened will be stored in \fIreadObjPtr\fR. .PP -Setting \fIcharsToRead\fR to \fB\-1\fR will cause the command to read +Setting \fIcharsToRead\fR to -1 will cause the command to read all characters currently available (non-blocking) or everything until eof (blocking mode). .PP The return value may be smaller than the value to read, indicating that less data than requested was available. This is called a \fIshort read\fR. In blocking mode, this can only happen on an end-of-file. In nonblocking mode, -a short read can also occur if there is not enough input currently -available: \fBTcl_ReadChars\fR returns a short count rather than waiting -for more data. +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 @@ -469,18 +471,18 @@ are appended to \fIlineObjPtr\fR's string representation. The end-of-line character(s) are read and discarded. .PP If a line was successfully read, the return value is greater than or equal to zero and indicates the number of bytes stored in \fIlineObjPtr\fR. If an -error occurs, \fBTcl_GetsObj\fR returns \-1 and records a POSIX error code +error occurs, \fBTcl_GetsObj\fR returns -1 and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. \fBTcl_GetsObj\fR also -returns \-1 if the end of the file is reached; the \fBTcl_Eof\fR procedure +returns -1 if the end of the file is reached; the \fBTcl_Eof\fR procedure can be used to distinguish an error from an end-of-file condition. .PP -If the channel is in nonblocking mode, the return value can also be \-1 if -no data was available or the data that was available did not contain an -end-of-line character. When \-1 is returned, the \fBTcl_InputBlocked\fR +If the channel is in nonblocking mode, the return value can also be -1 +if no data was available or the data that was available did not contain an +end-of-line character. When -1 is returned, the \fBTcl_InputBlocked\fR procedure may be invoked to determine if the channel is blocked because of input unavailability. .PP \fBTcl_Gets\fR is the same as \fBTcl_GetsObj\fR except the resulting characters are appended to the dynamic string given by @@ -494,11 +496,11 @@ data is to be added at the end of queue; otherwise it will be added at the head of the queue. If \fIchannel\fR has a .QW sticky EOF set, no data will be added to the input queue. \fBTcl_Ungets\fR returns \fIinputLen\fR or -\-1 if an error occurs. +-1 if an error occurs. .SH "TCL_WRITECHARS, TCL_WRITEOBJ, AND TCL_WRITE" .PP \fBTcl_WriteChars\fR accepts \fIbytesToWrite\fR bytes of character data at \fIcharBuf\fR. The UTF-8 characters in the buffer are converted to the channel's encoding and queued for output to \fIchannel\fR. If @@ -511,14 +513,14 @@ \fB\-buffering\fR option on the channel to \fBnone\fR. If you wish the data to appear as soon as a complete line is accepted for output, set the \fB\-buffering\fR option on the channel to \fBline\fR mode. .PP The return value of \fBTcl_WriteChars\fR is a count of how many bytes were -accepted for output to the channel. This is either greater than zero to -indicate success or \-1 to indicate that an error occurred. If an error -occurs, \fBTcl_WriteChars\fR records a POSIX error code that may be -retrieved with \fBTcl_GetErrno\fR. +accepted for output to the channel. This is either -1 to +indicate that an error occurred or another number greater than +zero to indicate success. If an error occurs, \fBTcl_WriteChars\fR records +a POSIX error code that may be retrieved with \fBTcl_GetErrno\fR. .PP Newline characters in the output data are translated to platform-specific end-of-line sequences according to the \fB\-translation\fR option for the channel. This is done even if the channel has no encoding. .PP @@ -597,11 +599,11 @@ \fBTcl_DStringAppendElement\fR. The various preexisting options and their possible values are described in the manual entry for the Tcl \fBfconfigure\fR command. Other options can be added by each channel type. These channel type specific options are described in the manual entry for the Tcl command that creates a channel of that type; for example, the -additional options for TCP based channels are described in the manual entry +additional options for TCP-based channels are described in the manual entry for the Tcl \fBsocket\fR command. The procedure normally returns \fBTCL_OK\fR. If an error occurs, it returns \fBTCL_ERROR\fR and calls \fBTcl_SetErrno\fR to store an appropriate POSIX error code. .SH TCL_SETCHANNELOPTION @@ -639,10 +641,28 @@ 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 Index: doc/OpenTcp.3 ================================================================== --- doc/OpenTcp.3 +++ doc/OpenTcp.3 @@ -22,11 +22,11 @@ .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) +\fBTcl_OpenTcpServerEx\fR(\fIinterp, service, myaddr, flags, backlog, 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 @@ -45,12 +45,14 @@ 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 +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 @@ -169,15 +171,18 @@ replacement for the standard channel. .SS TCL_OPENTCPSERVEREX .PP \fBTcl_OpenTcpServerEx\fR behaviour is identical to \fBTcl_OpenTcpServer\fR but gives more flexibility to the user by providing a mean to further customize some -aspects of the socket via the \fIflags\fR parameter. +aspects of the socket via the \fIflags\fR parameter. Available +flags (dependent on platform) are +\fITCL_TCPSERVER_REUSEADDR\fR +\fITCL_TCPSERVER_REUSEPORT\fR .SH "PLATFORM ISSUES" .PP On Unix platforms, the socket handle is a Unix file descriptor as returned by the \fBsocket\fR system call. On the Windows platform, the socket handle is a \fBSOCKET\fR as defined in the WinSock API. .SH "SEE ALSO" Tcl_OpenFileChannel(3), Tcl_RegisterChannel(3), vwait(n) .SH KEYWORDS channel, client, server, socket, TCP Index: doc/Panic.3 ================================================================== --- doc/Panic.3 +++ doc/Panic.3 @@ -13,11 +13,11 @@ \fB#include \fR .sp void \fBTcl_Panic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR) .sp -void +const char * \fBTcl_SetPanicProc\fR(\fIpanicProc\fR) .sp void \fBTcl_ConsolePanic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR) .sp @@ -25,14 +25,10 @@ .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 @@ -76,17 +72,19 @@ \fBTcl_Panic\fR will call \fIpanicProc\fR, passing along the \fIformat\fR and \fIarg\fR arguments. \fIpanicProc\fR should avoid making calls into the Tcl library, or into other libraries that may call the Tcl library, since the original call to \fBTcl_Panic\fR indicates the Tcl library is not in a state of reliable operation. +.PP +The result of \fBTcl_SetPanicProc\fR is the full Tcl version with build +information (e.g., \fB9.0.0+abcdef...abcdef.gcc-1002\fR). .PP The typical use of \fBTcl_SetPanicProc\fR arranges for the error message to be displayed or reported in a manner more suitable for the application or the platform. .PP -\fBTcl_SetPanicProc\fR can not be used safely by stub-enabled extensions, so its -symbol is not included in the stub table. +\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 Index: doc/ParseArgs.3 ================================================================== --- doc/ParseArgs.3 +++ doc/ParseArgs.3 @@ -19,11 +19,11 @@ .AS "const Tcl_ArgvInfo" ***remObjv in/out .AP Tcl_Interp *interp out Where to store error messages. .AP "const Tcl_ArgvInfo" *argTable in Pointer to array of option descriptors. -.AP int *objcPtr in/out +.AP "Tcl_Size \&| int" *objcPtr in/out A pointer to variable holding number of arguments in \fIobjv\fR. Will be modified to hold number of arguments left in the unprocessed argument list stored in \fIremObjv\fR. .AP "Tcl_Obj *const" *objv in The array of arguments to be parsed. @@ -187,12 +187,18 @@ 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: Index: doc/ParseCmd.3 ================================================================== --- doc/ParseCmd.3 +++ doc/ParseCmd.3 @@ -43,11 +43,11 @@ if NULL, then no error messages are left after errors. For \fBTcl_EvalTokensStandard\fR, determines the context for evaluating the script and also is used for error reporting; must not be NULL. .AP "const char" *start in Pointer to first character in string to parse. -.AP int numBytes in +.AP Tcl_Size numBytes in Number of bytes in string to parse, not including any terminating null character. If less than 0 then the script consists of all characters following \fIstart\fR up to the first null character. .AP int nested in Non-zero means that the script is part of a command substitution so an @@ -194,24 +194,24 @@ 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; + Tcl_Size \fIcommentSize\fR; const char *\fIcommandStart\fR; - int \fIcommandSize\fR; - int \fInumWords\fR; + Tcl_Size \fIcommandSize\fR; + Tcl_Size \fInumWords\fR; Tcl_Token *\fItokenPtr\fR; - int \fInumTokens\fR; + Tcl_Size \fInumTokens\fR; ... } \fBTcl_Parse\fR; typedef struct Tcl_Token { int \fItype\fR; const char *\fIstart\fR; - size_t \fIsize\fR; - size_t \fInumComponents\fR; + Tcl_Size \fIsize\fR; + Tcl_Size \fInumComponents\fR; } \fBTcl_Token\fR; .CE .PP The first five fields of a Tcl_Parse structure are filled in only by \fBTcl_ParseCommand\fR. Index: doc/PkgRequire.3 ================================================================== --- doc/PkgRequire.3 +++ doc/PkgRequire.3 @@ -53,11 +53,11 @@ .AP void *clientDataPtr out Pointer to place to store the value associated with the matching package. It is only changed if the pointer is not NULL and the function completed successfully. The storage can be any pointer type with the same size as a void pointer. -.AP int objc in +.AP Tcl_Size objc in Number of requirements. .AP Tcl_Obj* objv[] in Array of requirements. .BE .SH DESCRIPTION @@ -89,9 +89,13 @@ functions. .PP \fBTcl_PkgRequireProc\fR is the form of \fBpackage require\fR handling multiple requirements. The other forms are present for backward compatibility and translate their invocations to this form. +.SH "REFERENCE COUNT MANAGEMENT" +.PP +The requirements values given (in the \fIobjv\fR argument) to +\fBTcl_PkgRequireProc\fR must have non-zero reference counts. .SH KEYWORDS package, present, provide, require, version .SH "SEE ALSO" -package(n), Tcl_StaticPackage(3) +package(n), Tcl_StaticLibrary(3) Index: doc/RecEvalObj.3 ================================================================== --- doc/RecEvalObj.3 +++ doc/RecEvalObj.3 @@ -42,10 +42,16 @@ 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 Index: doc/RegConfig.3 ================================================================== --- doc/RegConfig.3 +++ doc/RegConfig.3 @@ -26,11 +26,11 @@ Contains the name of the package registering the embedded configuration as ASCII string. This means that this information is in UTF-8 too. Must not be NULL. .AP "const Tcl_Config" *configuration in Refers to an array of Tcl_Config entries containing the information -embedded in the binary library. Must not be NULL. The end of the array +embedded in the library. Must not be NULL. The end of the array is signaled by either a key identical to NULL, or a key referring to the empty string. .AP "const char" *valEncoding in Contains the name of the encoding used to store the configuration values as ASCII string. This means that this information is in UTF-8 @@ -38,14 +38,14 @@ .BE .SH DESCRIPTION .PP The function described here has its base in TIP 59 and provides extensions with support for the embedding of configuration -information into their binary library and the generation of a +information into their library and the generation of a Tcl-level interface for querying this information. .PP -To embed configuration information into their binary library an +To embed configuration information into their library an extension has to define a non-volatile array of Tcl_Config entries in one if its source files and then call \fBTcl_RegisterConfig\fR to register that information. .PP \fBTcl_RegisterConfig\fR takes four arguments; first, a reference to @@ -106,6 +106,6 @@ } \fBTcl_Config\fR; .CE .\" No cross references yet. .\" .SH "SEE ALSO" .SH KEYWORDS -embedding, configuration, binary library +embedding, configuration, library Index: doc/RegExp.3 ================================================================== --- doc/RegExp.3 +++ doc/RegExp.3 @@ -49,24 +49,24 @@ internal representation of the value may be converted to a form that can be efficiently searched. .AP Tcl_Obj *patObj in/out Refers to the value from which to get a regular expression. The compiled regular expression is cached in the value. -.AP char *text in +.AP "const char" *text in Text to search for a match with a regular expression. .AP "const char" *pattern in String in the form of a regular expression pattern. .AP Tcl_RegExp regexp in Compiled regular expression. Must have been returned previously by \fBTcl_GetRegExpFromObj\fR or \fBTcl_RegExpCompile\fR. -.AP char *start in +.AP "const char" *start in If \fItext\fR is just a portion of some other string, this argument identifies the beginning of the larger string. If it is not the same as \fItext\fR, then no .QW \fB^\fR matches will be allowed. -.AP size_t index in +.AP Tcl_Size index in Specifies which range is desired: 0 means the range of the entire match, 1 or greater means the range that matched a parenthesized sub-expression. .AP "const char" **startPtr out The address of the first character in the range is stored here, or @@ -78,18 +78,18 @@ OR-ed combination of the compilation flags \fBTCL_REG_ADVANCED\fR, \fBTCL_REG_EXTENDED\fR, \fBTCL_REG_BASIC\fR, \fBTCL_REG_EXPANDED\fR, \fBTCL_REG_QUOTE\fR, \fBTCL_REG_NOCASE\fR, \fBTCL_REG_NEWLINE\fR, \fBTCL_REG_NLSTOP\fR, \fBTCL_REG_NLANCH\fR, \fBTCL_REG_NOSUB\fR, and \fBTCL_REG_CANMATCH\fR. See below for more information. -.AP size_t offset in +.AP Tcl_Size offset in The character offset into the text where matching should begin. The value of the offset has no impact on \fB^\fR matches. This behavior is controlled by \fIeflags\fR. -.AP size_t nmatches in +.AP Tcl_Size nmatches in The number of matching subexpressions that should be remembered for later use. If this value is 0, then no subexpression match -information will be computed. If the value is TCL_INDEX_NONE, then +information will be computed. If the value is negative, then all of the matching subexpressions will be remembered. Any other value will be taken as the maximum number of subexpressions to remember. .AP int eflags in OR-ed combination of the execution flags \fBTCL_REG_NOTBOL\fR and @@ -335,13 +335,13 @@ \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_Size \fInsubs\fR; Tcl_RegExpIndices *\fImatches\fR; - size_t \fIextendStart\fR; + Tcl_Size \fIextendStart\fR; } \fBTcl_RegExpInfo\fR; .CE .PP The \fInsubs\fR field contains a count of the number of parenthesized subexpressions within the regular expression. If the \fBTCL_REG_NOSUB\fR @@ -353,12 +353,12 @@ 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; + 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. @@ -375,9 +375,25 @@ 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 Index: doc/SaveInterpState.3 ================================================================== --- /dev/null +++ doc/SaveInterpState.3 @@ -0,0 +1,54 @@ +'\" +'\" 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 \fR +.sp +Tcl_InterpState +\fBTcl_SaveInterpState\fR(\fIinterp, status\fR) +.sp +int +\fBTcl_RestoreInterpState\fR(\fIinterp, state\fR) +.sp +\fBTcl_DiscardInterpState\fR(\fIstate\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. +.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 Index: doc/SaveResult.3 ================================================================== --- doc/SaveResult.3 +++ /dev/null @@ -1,85 +0,0 @@ -'\" -'\" 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 \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 Index: doc/SetChanErr.3 ================================================================== --- doc/SetChanErr.3 +++ doc/SetChanErr.3 @@ -33,24 +33,24 @@ .AP Tcl_Interp* interp in Refers to the Tcl interpreter whose bypass area is accessed. .AP Tcl_Obj* msg in Error message put into a bypass area. A list of return options and values, followed by a string message. Both message and the option/value information -are optional. +are optional. This \fImust\fR be a well-formed list. .AP Tcl_Obj** msgPtr out Reference to a place where the message stored in the accessed bypass area can be stored in. .BE .SH DESCRIPTION .PP -The current definition of a Tcl channel driver does not permit the direct +The standard definition of a Tcl channel driver does not permit the direct return of arbitrary error messages, except for the setting and retrieval of channel options. All other functions are restricted to POSIX error codes. .PP The functions described here overcome this limitation. Channel drivers are allowed to use \fBTcl_SetChannelError\fR and \fBTcl_SetChannelErrorInterp\fR -to place arbitrary error messages in \fBbypass areas\fR defined for channels +to place arbitrary error messages in \fIbypass areas\fR defined for channels and interpreters. And the generic I/O layer uses \fBTcl_GetChannelError\fR and \fBTcl_GetChannelErrorInterp\fR to look for messages in the bypass areas and arrange for their return as errors. The POSIX error codes set by a driver are used now if and only if no messages are present. .PP @@ -128,9 +128,18 @@ 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 Index: doc/SetRecLmt.3 ================================================================== --- doc/SetRecLmt.3 +++ doc/SetRecLmt.3 @@ -12,18 +12,18 @@ Tcl_SetRecursionLimit \- set maximum allowable nesting depth in interpreter .SH SYNOPSIS .nf \fB#include \fR .sp -int +Tcl_Size \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 +.AP Tcl_Size depth in New limit for nested calls to \fBTcl_Eval\fR for \fIinterp\fR. .BE .SH DESCRIPTION .PP Index: doc/SetResult.3 ================================================================== --- doc/SetResult.3 +++ doc/SetResult.3 @@ -22,200 +22,119 @@ \fBTcl_SetResult\fR(\fIinterp, result, freeProc\fR) .sp const char * \fBTcl_GetStringResult\fR(\fIinterp\fR) .sp -\fBTcl_AppendResult\fR(\fIinterp, result, result, ... , \fB(char *) NULL\fR) +\fBTcl_AppendResult\fR(\fIinterp, result, result, ... , \fBNULL\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. +The interpreter get or set the result for. .AP Tcl_Obj *objPtr in -Tcl value to become result for \fIinterp\fR. +A value to set the result to. .AP char *result in -String value to become result for \fIinterp\fR or to be -appended to the existing result. +The string value set the result to, or to append to the existing result. .AP "const char" *element in -String value to append as a list element +The 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. +Pointer to a procedure to call to release storage at +\fIresult\fR. .AP Tcl_Interp *sourceInterp in -Interpreter that the result and return options should be transferred from. +The interpreter to transfer the result and return options from. .AP Tcl_Interp *targetInterp in -Interpreter that the result and return options should be transferred to. +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 -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. +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 -arranges for \fIobjPtr\fR to be the result for \fIinterp\fR, +\fBTcl_SetObjResult\fR sets \fIobjPtr\fR as 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 +.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 -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. +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 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 +\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 -\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: +\fIFreeProc\fR has the following type: .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. +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 Index: doc/SetVar.3 ================================================================== --- doc/SetVar.3 +++ doc/SetVar.3 @@ -240,10 +240,31 @@ 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 Index: doc/SourceRCFile.3 ================================================================== --- doc/SourceRCFile.3 +++ doc/SourceRCFile.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH Tcl_SourceRCFile 3 8.3 Tcl "Tcl Library Procedures" .so man.macros .BS Index: doc/SplitList.3 ================================================================== --- doc/SplitList.3 +++ doc/SplitList.3 @@ -18,46 +18,46 @@ \fBTcl_SplitList\fR(\fIinterp, list, argcPtr, argvPtr\fR) .sp char * \fBTcl_Merge\fR(\fIargc, argv\fR) .sp -size_t +Tcl_Size \fBTcl_ScanElement\fR(\fIsrc, flagsPtr\fR) .sp -size_t +Tcl_Size \fBTcl_ScanCountedElement\fR(\fIsrc, length, flagsPtr\fR) .sp -size_t +Tcl_Size \fBTcl_ConvertElement\fR(\fIsrc, dst, flags\fR) .sp -size_t +Tcl_Size \fBTcl_ConvertCountedElement\fR(\fIsrc, length, dst, flags\fR) .SH ARGUMENTS .AS "const char *const" ***argvPtr out .AP Tcl_Interp *interp out Interpreter to use for error reporting. If NULL, then no error message is left. -.AP char *list in +.AP "const char" *list in Pointer to a string with proper list structure. -.AP int *argcPtr out +.AP "Tcl_Size \&| int" *argcPtr out Filled in with number of elements in \fIlist\fR. .AP "const char" ***argvPtr out \fI*argvPtr\fR will be filled in with the address of an array of pointers to the strings that are the extracted elements of \fIlist\fR. There will be \fI*argcPtr\fR valid entries in the array, followed by a NULL entry. -.AP int argc in +.AP Tcl_Size argc in Number of elements in \fIargv\fR. .AP "const char *const" *argv in Array of strings to merge together into a single list. Each string will become a separate element of the list. .AP "const char" *src in String that is to become an element of a list. .AP int *flagsPtr in Pointer to word to fill in with information about \fIsrc\fR. The value of *\fIflagsPtr\fR must be passed to \fBTcl_ConvertElement\fR. -.AP size_t length in +.AP Tcl_Size length in Number of bytes in string \fIsrc\fR. .AP char *dst in Place to copy converted list element. Must contain enough characters to hold converted string. .AP int flags in @@ -79,11 +79,12 @@ 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; +Tcl_Size argc; +int code; char *string; char **argv; \&... code = \fBTcl_SplitList\fR(interp, string, &argc, &argv); .CE @@ -90,16 +91,17 @@ .PP Then you should eventually free the storage with a call like the following: .PP .CS -Tcl_Free((char *) argv); +Tcl_Free(argv); .CE .PP \fBTcl_SplitList\fR normally returns \fBTCL_OK\fR, which means the list was -successfully parsed. -If there was a syntax error in \fIlist\fR, then \fBTCL_ERROR\fR is returned +successfully parsed. If \fIsizePtr\fR points to a variable of type +\fBint\fR and the list contains more than 2**31 key/value pairs, or there was +a syntax error in \fIlist\fR, then \fBTCL_ERROR\fR is returned and the interpreter's result will point to an error message describing the problem (if \fIinterp\fR was not NULL). If \fBTCL_ERROR\fR is returned then no memory is allocated and \fI*argvPtr\fR is not modified. .PP Index: doc/SplitPath.3 ================================================================== --- doc/SplitPath.3 +++ doc/SplitPath.3 @@ -23,18 +23,18 @@ .SH ARGUMENTS .AS "const char *const" ***argvPtr in/out .AP "const char" *path in File path in a form appropriate for the current platform (see the \fBfilename\fR manual entry for acceptable forms for path names). -.AP int *argcPtr out +.AP "Tcl_Size \&| int" *argcPtr out Filled in with number of path elements in \fIpath\fR. .AP "const char" ***argvPtr out \fI*argvPtr\fR will be filled in with the address of an array of pointers to the strings that are the extracted elements of \fIpath\fR. There will be \fI*argcPtr\fR valid entries in the array, followed by a NULL entry. -.AP int argc in +.AP Tcl_Size argc in Number of elements in \fIargv\fR. .AP "const char *const" *argv in Array of path elements to merge together into a single path. .AP Tcl_DString *resultPtr in/out A pointer to an initialized \fBTcl_DString\fR to which the result of @@ -59,11 +59,11 @@ responsibility to free all of this storage. For example, suppose that you have called \fBTcl_SplitPath\fR with the following code: .PP .CS -int argc; +Tcl_Size argc; char *path; char **argv; \&... Tcl_SplitPath(string, &argc, &argv); .CE @@ -70,11 +70,11 @@ .PP Then you should eventually free the storage with a call like the following: .PP .CS -Tcl_Free((char *) argv); +Tcl_Free(argv); .CE .PP \fBTcl_JoinPath\fR is the inverse of \fBTcl_SplitPath\fR: it takes a collection of path elements given by \fIargc\fR and \fIargv\fR and generates a result string that is a properly constructed path. The ADDED doc/StaticLibrary.3 Index: doc/StaticLibrary.3 ================================================================== --- /dev/null +++ doc/StaticLibrary.3 @@ -0,0 +1,77 @@ +'\" +'\" 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 \fR +.sp +\fBTcl_StaticLibrary\fR(\fIinterp, prefix, initProc, safeInitProc\fR) +.sp +\fBTcl_StaticPackage\fR(\fIinterp, prefix, initProc, safeInitProc\fR) +.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 Index: doc/StaticPkg.3 ================================================================== --- doc/StaticPkg.3 +++ /dev/null @@ -1,73 +0,0 @@ -'\" -'\" 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 \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) Index: doc/StdChannels.3 ================================================================== --- doc/StdChannels.3 +++ doc/StdChannels.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 2001 by ActiveState Corporation +'\" Copyright (c) 2001 ActiveState Corporation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH "Standard Channels" 3 7.5 Tcl "Tcl Library Procedures" Index: doc/StringObj.3 ================================================================== --- doc/StringObj.3 +++ doc/StringObj.3 @@ -38,11 +38,11 @@ \fBTcl_GetUnicode\fR(\fIobjPtr\fR) .sp int \fBTcl_GetUniChar\fR(\fIobjPtr, index\fR) .sp -int +Tcl_Size \fBTcl_GetCharLength\fR(\fIobjPtr\fR) .sp Tcl_Obj * \fBTcl_GetRange\fR(\fIobjPtr, first, last\fR) .sp @@ -54,11 +54,11 @@ .sp void \fBTcl_AppendObjToObj\fR(\fIobjPtr, appendObjPtr\fR) .sp void -\fBTcl_AppendStringsToObj\fR(\fIobjPtr, string, string, ... \fB(char *) NULL\fR) +\fBTcl_AppendStringsToObj\fR(\fIobjPtr, string, string, ... \fBNULL\fR) .sp void \fBTcl_AppendLimitedToObj\fR(\fIobjPtr, bytes, length, limit, ellipsis\fR) .sp Tcl_Obj * @@ -85,61 +85,60 @@ .AS "const Tcl_UniChar" *appendObjPtr in/out .AP "const char" *bytes in Points to the first byte of an array of UTF-8-encoded bytes used to set or append to a string value. This byte array may contain embedded null characters -unless \fInumChars\fR is TCL_INDEX_NONE. (Applications needing null bytes +unless \fInumChars\fR is negative. (Applications needing null bytes should represent them as the two-byte sequence \fI\e300\e200\fR, use \fBTcl_ExternalToUtf\fR to convert, or \fBTcl_NewByteArrayObj\fR if the string is a collection of uninterpreted bytes.) -.AP size_t length in +.AP Tcl_Size length in The number of bytes to copy from \fIbytes\fR when initializing, setting, or appending to a string value. -If TCL_INDEX_NONE, all bytes up to the first null are used. +If negative, all bytes up to the first null are used. .AP "const Tcl_UniChar" *unicode in Points to the first byte of an array of Unicode characters used to set or append to a string value. This byte array may contain embedded null characters unless \fInumChars\fR is negative. -.AP size_t numChars in +.AP Tcl_Size numChars in The number of Unicode characters to copy from \fIunicode\fR when initializing, setting, or appending to a string value. -If TCL_INDEX_NONE, all characters up to the first null character are used. -.AP size_t index in +If negative, all characters up to the first null character are used. +.AP Tcl_Size index in The index of the Unicode character to return. -.AP size_t first in +.AP Tcl_Size first in The index of the first Unicode character in the Unicode range to be -returned as a new value. -.AP size_t last in +returned as a new value. If negative, behave the same as if the +value was 0. +.AP Tcl_Size last in The index of the last Unicode character in the Unicode range to be -returned as a new value. +returned as a new value. If negative, take all characters up to +the last one available. .AP Tcl_Obj *objPtr in/out -Points to a value to manipulate. +A pointer to a value to read, or to an unshared value to modify. .AP Tcl_Obj *appendObjPtr in The value to append to \fIobjPtr\fR in \fBTcl_AppendObjToObj\fR. -.AP int *lengthPtr out -If non-NULL, the location where \fBTcl_GetStringFromObj\fR will store -the length of a value's string representation. +.AP "Tcl_Size \&| int" *lengthPtr out +The location where \fBTcl_GetStringFromObj\fR will store the length +of a value's string representation. May be (int *)NULL when not used. .AP "const char" *string in Null-terminated string value to append to \fIobjPtr\fR. -.AP va_list argList in -An argument list which must have been initialized using -\fBva_start\fR, and cleared using \fBva_end\fR. -.AP size_t limit in +.AP Tcl_Size limit in Maximum number of bytes to be appended. .AP "const char" *ellipsis in Suffix to append when the limit leads to string truncation. If NULL is passed then the suffix .QW "..." is used. .AP "const char" *format in Format control string including % conversion specifiers. -.AP int objc in +.AP Tcl_Size objc in The number of elements to format or concatenate. .AP Tcl_Obj *objv[] in The array of values to format or concatenate. -.AP size_t newLength in +.AP Tcl_Size newLength in New length for the string value of \fIobjPtr\fR, not including the final null character. .BE .SH DESCRIPTION .PP @@ -184,11 +183,13 @@ recommended that this pointer be assigned to a (const char *) variable. Even in the limited situations where writing to this pointer is acceptable, one should take care to respect the copy-on-write semantics required by \fBTcl_Obj\fR's, with appropriate calls to \fBTcl_IsShared\fR and \fBTcl_DuplicateObj\fR prior to any -in-place modification of the string representation. +in-place modification of the string representation. If \fIlengthPtr\fR +points to an \fBint\fR variable, and the string has more than 2^31 bytes, +a panic will result. The procedure \fBTcl_GetString\fR is used in the common case where the caller does not need the length of the string representation. .PP \fBTcl_GetUnicodeFromObj\fR and \fBTcl_GetUnicode\fR return a value's @@ -196,21 +197,24 @@ (for \fBTcl_GetUnicodeFromObj\fR) length, which is stored in \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. +representation. If \fIlengthPtr\fR points to an \fBint\fR variable, +and the string has more than 2^31 unicode characters, a panic will result. .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. +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 @@ -254,11 +258,11 @@ than \fIlimit\fR bytes total are to be appended. If the limit prevents all \fIlength\fR bytes that are available from being appended, then the appending is done so that the last bytes appended are from the string \fIellipsis\fR. This allows for an indication of the truncation to be left in the string. -When \fIlength\fR is \fB-1\fR, all bytes up to the first zero byte are appended, +When \fIlength\fR is negative, all bytes up to the first zero byte are appended, subject to the limit. When \fIellipsis\fR is NULL, the default string \fB...\fR is used. When \fIellipsis\fR is non-NULL, it must point to a zero-byte-terminated string in Tcl's internal UTF encoding. The number of bytes appended can be less than the lesser of \fIlength\fR and \fIlimit\fR when appending fewer @@ -372,10 +376,37 @@ 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 Index: doc/SubstObj.3 ================================================================== --- doc/SubstObj.3 +++ doc/SubstObj.3 @@ -22,11 +22,11 @@ an error occurs, the interpreter's result is modified to hold an error message. .AP Tcl_Obj *objPtr in A Tcl value containing the string to perform substitutions on. .AP int flags in -ORed combination of flag bits that specify which substitutions to +OR'ed combination of flag bits that specify which substitutions to perform. The flags \fBTCL_SUBST_COMMANDS\fR, \fBTCL_SUBST_VARIABLES\fR and \fBTCL_SUBST_BACKSLASHES\fR are currently supported, and \fBTCL_SUBST_ALL\fR is provided as a convenience for the common case where all substitutions are desired. .BE @@ -60,9 +60,16 @@ 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 Index: doc/TCL_MEM_DEBUG.3 ================================================================== --- doc/TCL_MEM_DEBUG.3 +++ doc/TCL_MEM_DEBUG.3 @@ -1,8 +1,8 @@ '\" -'\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans. -'\" Copyright (c) 2000 by Scriptics Corporation. +'\" Copyright (c) 1992-1999 Karl Lehenbauer & Mark Diekhans. +'\" Copyright (c) 2000 Scriptics Corporation. '\" All rights reserved. '\" .TH TCL_MEM_DEBUG 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS Index: doc/Tcl.n ================================================================== --- doc/Tcl.n +++ doc/Tcl.n @@ -1,8 +1,9 @@ '\" '\" 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" @@ -14,265 +15,188 @@ 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 +. +.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' -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}}" +, 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 -.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 +.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 [ -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 +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 $ -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: +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 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). +\fIname\fR may not be empty. + .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. +\fIname\fR may be empty. Substitutions are performed on \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). +\fIname\fR may be empty. +.TP 15 +\fB${\fIname(index)\fB}\fR +. +\fIname\fR may be empty. No substitutions are performed. .RE -.IP "[9] \fBBackslash substitution.\fR" -If a backslash +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 -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. +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) (Unicode U+000007). +Audible alert (bell) (U+7). .TP 7 \e\fBb\fR -Backspace (Unicode U+000008). +Backspace (U+8). .TP 7 \e\fBf\fR -Form feed (Unicode U+00000C). +Form feed (U+C). .TP 7 \e\fBn\fR -Newline (Unicode U+00000A). +Newline (U+A). .TP 7 \e\fBr\fR -Carriage-return (Unicode U+00000D). +Carriage-return (U+D). .TP 7 \e\fBt\fR -Tab (Unicode U+000009). +Tab (U+9). .TP 7 \e\fBv\fR -Vertical tab (Unicode U+00000B). +Vertical tab (U+B). .TP 7 \e\fB\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. +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 . -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. +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 . -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). +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 . -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). +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 . -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. +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: Index: doc/TclZlib.3 ================================================================== --- doc/TclZlib.3 +++ doc/TclZlib.3 @@ -86,11 +86,11 @@ .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 +.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. @@ -105,12 +105,12 @@ if the currently compressed data must be made available for access using \fBTcl_ZlibStreamGet\fR, \fBTCL_ZLIB_FULLFLUSH\fR if the stream must be put into a state where the decompressor can recover from on corruption, or \fBTCL_ZLIB_FINALIZE\fR to ensure that the stream is finished and that any trailer demanded by the format is written. -.AP size_t count in -The maximum number of bytes to get from the stream, or TCL_INDEX_NONE to get +.AP Tcl_Size count in +The maximum number of bytes to get from the stream, or -1 to get all remaining bytes from the stream's buffers. .AP Tcl_Obj *compDict in A byte array value that is the compression dictionary to use with the stream. Note that this is \fInot a Tcl dictionary\fR, and it is recommended that this only ever be used with streams that were created with their \fIformat\fR set @@ -186,11 +186,11 @@ array of bytes (such as might be created with \fBTcl_NewByteArrayObj\fR) that is used to initialize the compression engine rather than leaving it to create it on the fly from the data being compressed. Setting a compression dictionary allows for more efficient compression in the case where the start of the data is highly regular, but it does require both the compressor and the -decompressor to agreee on the value to use. Compression dictionaries are only +decompressor to agree on the value to use. Compression dictionaries are only fully supported for zlib-format data; on compression, they must be set before any data is sent in with \fBTcl_ZlibStreamPut\fR, and on decompression they should be set when \fBTcl_ZlibStreamGet\fR produces an \fBerror\fR with its \fB\-errorcode\fR set to .QW "\fBZLIB NEED_DICT\fI code\fR" ; @@ -260,10 +260,35 @@ .TP \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) Index: doc/Tcl_Main.3 ================================================================== --- doc/Tcl_Main.3 +++ doc/Tcl_Main.3 @@ -4,34 +4,42 @@ '\" Copyright (c) 2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -.TH Tcl_Main 3 8.4 Tcl "Tcl Library Procedures" +.TH Tcl_Main 3 9.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_Main, Tcl_SetStartupScript, Tcl_GetStartupScript, Tcl_SetMainLoop \- main program, startup script, and event loop definition for Tcl-based applications +Tcl_Main, Tcl_MainEx, Tcl_MainExW, Tcl_SetStartupScript, Tcl_GetStartupScript, Tcl_SetMainLoop \- main program, startup script, and event loop definition for Tcl-based applications .SH SYNOPSIS .nf \fB#include \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) .SH ARGUMENTS .AS Tcl_MainLoopProc *mainLoopProc -.AP int argc in +.AP Tcl_Size argc in Number of elements in \fIargv\fR. .AP char *argv[] in Array of strings containing command-line arguments. On Windows, when using -DUNICODE, the parameter type changes to wchar_t *. +.AP char *charargv[] in +As argv, but does not change type to wchar_t. +.AP char *wideargv[] in +As argv, but type is always wchar_t. .AP Tcl_AppInitProc *appInitProc in Address of an application-specific initialization procedure. The value for this argument is usually \fBTcl_AppInit\fR. .AP Tcl_Obj *path in Name of file to use as startup script, or NULL. @@ -40,10 +48,12 @@ .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 @@ -73,12 +83,14 @@ \fBTcl_Main\fR then does all the work of creating and running a \fBtclsh\fR-like application. .PP \fBTcl_Main\fR is not provided by the public interface of Tcl's stub library. Programs that call \fBTcl_Main\fR must be linked -against the standard Tcl library. Extensions (stub-enabled or -not) are not intended to call \fBTcl_Main\fR. +against the standard Tcl library. If the standard Tcl library is +a dll (so, not a static .lib/.a) , then the program must be linked +against the stub library as well. Extensions +(stub-enabled or not) are not intended to call \fBTcl_Main\fR. .PP \fBTcl_Main\fR is not thread-safe. It should only be called by a single main thread of a multi-threaded application. This restriction is not a problem with normal use described above. .PP @@ -189,10 +201,24 @@ \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 Index: doc/Thread.3 ================================================================== --- doc/Thread.3 +++ doc/Thread.3 @@ -67,11 +67,11 @@ .AP Tcl_ThreadCreateProc *proc in This procedure will act as the \fBmain()\fR of the newly created thread. The specified \fIclientData\fR will be its sole argument. .AP void *clientData in Arbitrary information. Passed as sole argument to the \fIproc\fR. -.AP int stackSize in +.AP size_t stackSize in The size of the stack given to the new thread. .AP int flags in Bitmask containing flags allowing the caller to modify behavior of the new thread. .AP int *result out Index: doc/ToUpper.3 ================================================================== --- doc/ToUpper.3 +++ doc/ToUpper.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1997 by Sun Microsystems, Inc. +'\" Copyright (c) 1997 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_UtfToUpper 3 "8.1" Tcl "Tcl Library Procedures" @@ -20,17 +20,17 @@ \fBTcl_UniCharToLower\fR(\fIch\fR) .sp int \fBTcl_UniCharToTitle\fR(\fIch\fR) .sp -int +Tcl_Size \fBTcl_UtfToUpper\fR(\fIstr\fR) .sp -int +Tcl_Size \fBTcl_UtfToLower\fR(\fIstr\fR) .sp -int +Tcl_Size \fBTcl_UtfToTitle\fR(\fIstr\fR) .SH ARGUMENTS .AS char *str in/out .AP int ch in The Unicode character to be converted. Index: doc/TraceVar.3 ================================================================== --- doc/TraceVar.3 +++ doc/TraceVar.3 @@ -124,24 +124,26 @@ .PP .CS typedef char *\fBTcl_VarTraceProc\fR( void *\fIclientData\fR, Tcl_Interp *\fIinterp\fR, - char *\fIname1\fR, - char *\fIname2\fR, + const char *\fIname1\fR, + const char *\fIname2\fR, int \fIflags\fR); .CE .PP The \fIclientData\fR and \fIinterp\fR parameters will have the same values as those passed to \fBTcl_TraceVar\fR when the trace was created. \fIclientData\fR typically points to an application-specific data structure that describes what to do when \fIproc\fR is invoked. -\fIName1\fR and \fIname2\fR give the name of the traced variable -in the normal two-part form (see the description of \fBTcl_TraceVar2\fR -below for details). +\fIName1\fR and \fIname2\fR give the name of the variable that +triggered the callback in the normal two-part form (see the description +of \fBTcl_TraceVar2\fR below for details). In case \fIname1\fR is an +alias to an array element (created through facilities such as \fBupvar\fR), +\fIname2\fR holds the index of the array element, rather than NULL. \fIFlags\fR is an OR-ed combination of bits providing several pieces of information. One of the bits \fBTCL_TRACE_READS\fR, \fBTCL_TRACE_WRITES\fR, \fBTCL_TRACE_ARRAY\fR, or \fBTCL_TRACE_UNSETS\fR will be set in \fIflags\fR to indicate which operation is being performed @@ -358,13 +360,21 @@ 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 Index: doc/Translate.3 ================================================================== --- doc/Translate.3 +++ doc/Translate.3 @@ -7,11 +7,11 @@ '\" .TH Tcl_TranslateFileName 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_TranslateFileName \- convert file name to native form and replace tilde with home directory +Tcl_TranslateFileName \- convert file name to native form .SH SYNOPSIS .nf \fB#include \fR .sp char * @@ -19,12 +19,11 @@ .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 ~ . +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. @@ -32,11 +31,11 @@ .SH DESCRIPTION .PP This utility procedure translates a file name to a platform-specific form which, after being converted to the appropriate encoding, is suitable for passing to the local operating system. In particular, it converts -network names into native form and does tilde substitution. +network names into native form. .PP However, with the advent of the newer \fBTcl_FSGetNormalizedPath\fR and \fBTcl_FSGetNativePath\fR, there is no longer any need to use this procedure. In particular, \fBTcl_FSGetNativePath\fR performs all the necessary translation and encoding conversion, is virtual-filesystem @@ -43,11 +42,11 @@ aware, and caches the native result for faster repeated calls. Finally \fBTcl_FSGetNativePath\fR does not require you to free anything afterwards. .PP If -\fBTcl_TranslateFileName\fR has to do tilde substitution or translate +\fBTcl_TranslateFileName\fR has to translate the name then it uses the dynamic string at \fI*bufferPtr\fR to hold the new string it generates. After \fBTcl_TranslateFileName\fR returns a non-NULL result, the caller must eventually invoke \fBTcl_DStringFree\fR to free any information @@ -66,6 +65,6 @@ The caller is responsible for making sure that the interpreter's result has its default empty value when \fBTcl_TranslateFileName\fR is invoked. .SH "SEE ALSO" filename(n) .SH KEYWORDS -file name, home directory, tilde, translate, user +file name, home directory, translate, user Index: doc/UniCharIsAlpha.3 ================================================================== --- doc/UniCharIsAlpha.3 +++ doc/UniCharIsAlpha.3 @@ -6,11 +6,11 @@ '\" .TH Tcl_UniCharIsAlpha 3 "8.1" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_UniCharIsAlnum, Tcl_UniCharIsAlpha, Tcl_UniCharIsControl, Tcl_UniCharIsDigit, Tcl_UniCharIsGraph, Tcl_UniCharIsLower, Tcl_UniCharIsPrint, Tcl_UniCharIsPunct, Tcl_UniCharIsSpace, Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar \- routines for classification of Tcl_UniChar characters +Tcl_UniCharIsAlnum, Tcl_UniCharIsAlpha, Tcl_UniCharIsControl, Tcl_UniCharIsDigit, Tcl_UniCharIsGraph, Tcl_UniCharIsLower, Tcl_UniCharIsPrint, Tcl_UniCharIsPunct, Tcl_UniCharIsSpace, Tcl_UniCharIsUpper, Tcl_UniCharIsUnicode, Tcl_UniCharIsWordChar \- routines for classification of Tcl_UniChar characters .SH SYNOPSIS .nf \fB#include \fR .sp int @@ -41,10 +41,13 @@ \fBTcl_UniCharIsSpace\fR(\fIch\fR) .sp int \fBTcl_UniCharIsUpper\fR(\fIch\fR) .sp +int +\fBTcl_UniCharIsUnicode\fR(\fIch\fR) +.sp int \fBTcl_UniCharIsWordChar\fR(\fIch\fR) .SH ARGUMENTS .AS int ch .AP int ch in @@ -78,11 +81,14 @@ \fBTcl_UniCharIsPunct\fR tests if the character is a Unicode punctuation character. .PP \fBTcl_UniCharIsSpace\fR tests if the character is a whitespace Unicode character. .PP \fBTcl_UniCharIsUpper\fR tests if the character is an uppercase Unicode character. +.PP +\fBTcl_UniCharIsUnicode\fR tests if the character is a Unicode character, not being +a surrogate or noncharacter. .PP \fBTcl_UniCharIsWordChar\fR tests if the character is alphanumeric or a connector punctuation mark. .SH KEYWORDS unicode, classification Index: doc/Utf.3 ================================================================== --- doc/Utf.3 +++ doc/Utf.3 @@ -6,46 +6,52 @@ '\" .TH Utf 3 "8.1" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME -Tcl_UniChar, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UtfToChar16, Tcl_UtfToWChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_Char16ToUtfDString, Tcl_UtfToWCharDString, Tcl_UtfToChar16DString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharNcasecmp, Tcl_UniCharCaseMatch, Tcl_UtfNcmp, Tcl_UtfNcasecmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings +Tcl_UniChar, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UtfToChar16, Tcl_UtfToWChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_Char16ToUtfDString, Tcl_UtfToWCharDString, Tcl_UtfToChar16DString, Tcl_WCharToUtfDString, Tcl_WCharLen, Tcl_Char16Len, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharNcasecmp, Tcl_UniCharCaseMatch, Tcl_UtfNcmp, Tcl_UtfNcasecmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings .SH SYNOPSIS .nf \fB#include \fR .sp typedef ... \fBTcl_UniChar\fR; .sp -int +Tcl_Size \fBTcl_UniCharToUtf\fR(\fIch, buf\fR) .sp -int +Tcl_Size \fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR) .sp -int +Tcl_Size \fBTcl_UtfToChar16\fR(\fIsrc, uPtr\fR) .sp -int +Tcl_Size \fBTcl_UtfToWChar\fR(\fIsrc, wPtr\fR) .sp char * -\fBTcl_UniCharToUtfDString\fR(\fIuniStr, uniLength, dsPtr\fR) +\fBTcl_UniCharToUtfDString\fR(\fIuniStr, numUniChars, dsPtr\fR) .sp char * -\fBTcl_Char16ToUtfDString\fR(\fIuStr, uniLength, dsPtr\fR) +\fBTcl_Char16ToUtfDString\fR(\fIutf16, numUtf16, dsPtr\fR) .sp char * -\fBTcl_WCharToUtfDString\fR(\fIwStr, uniLength, dsPtr\fR) +\fBTcl_WCharToUtfDString\fR(\fIwcharStr, numWChars, dsPtr\fR) .sp Tcl_UniChar * -\fBTcl_UtfToUniCharDString\fR(\fIsrc, length, dsPtr\fR) +\fBTcl_UtfToUniCharDString\fR(\fIsrc, numBytes, dsPtr\fR) .sp unsigned short * -\fBTcl_UtfToChar16DString\fR(\fIsrc, length, dsPtr\fR) +\fBTcl_UtfToChar16DString\fR(\fIsrc, numBytes, dsPtr\fR) .sp wchar_t * -\fBTcl_UtfToWCharDString\fR(\fIsrc, length, dsPtr\fR) +\fBTcl_UtfToWCharDString\fR(\fIsrc, numBytes, dsPtr\fR) +.sp +int +\fBTcl_Char16Len\fR(\fIutf16\fR) +.sp +int +\fBTcl_WCharLen\fR(\fIwcharStr\fR) .sp int \fBTcl_UniCharLen\fR(\fIuniStr\fR) .sp int @@ -62,14 +68,14 @@ .sp int \fBTcl_UtfNcasecmp\fR(\fIcs, ct, length\fR) .sp int -\fBTcl_UtfCharComplete\fR(\fIsrc, length\fR) +\fBTcl_UtfCharComplete\fR(\fIsrc, numBytes\fR) .sp int -\fBTcl_NumUtfChars\fR(\fIsrc, length\fR) +\fBTcl_NumUtfChars\fR(\fIsrc, numBytes\fR) .sp const char * \fBTcl_UtfFindFirst\fR(\fIsrc, ch\fR) .sp const char * @@ -85,11 +91,11 @@ \fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR) .sp const char * \fBTcl_UtfAtIndex\fR(\fIsrc, index\fR) .sp -size_t +Tcl_Size \fBTcl_UtfBackslash\fR(\fIsrc, readPtr, dst\fR) .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 @@ -107,37 +113,41 @@ .AP "const char" *cs in Pointer to a UTF-8 string. .AP "const char" *ct in Pointer to a UTF-8 string. .AP "const Tcl_UniChar" *uniStr in -A null-terminated Unicode string. +A sequence of \fBTcl_UniChar\fR units with null-termination optional +depending on function. .AP "const Tcl_UniChar" *ucs in -A null-terminated Unicode string. +A null-terminated sequence of \fBTcl_UniChar\fR. .AP "const Tcl_UniChar" *uct in -A null-terminated Unicode string. +A null-terminated sequence of \fBTcl_UniChar\fR. .AP "const Tcl_UniChar" *uniPattern in -A null-terminated Unicode string. -.AP "const unsigned short" *uStr in -A null-terminated UTF-16 string. -.AP "const wchar_t" *wStr in -A null-terminated wchar_t string. -.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. +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 size_t index in +.AP Tcl_Size index in The index of a character (not byte) in the UTF-8 string. .AP int *readPtr out If non-NULL, filled with the number of bytes in the backslash sequence, including the backslash character. .AP char *dst out @@ -158,15 +168,16 @@ \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. +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 @@ -177,26 +188,36 @@ 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. +\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_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. +\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 @@ -228,15 +249,15 @@ strings. It is similar to \fBTcl_UtfNcmp\fR except comparisons ignore differences in case when comparing upper, lower or title case characters. .PP \fBTcl_UtfCharComplete\fR returns 1 if the source UTF-8 string \fIsrc\fR -of \fIlength\fR bytes is long enough to be decoded by -\fBTcl_UtfToUniChar\fR, or 0 otherwise. This function does not guarantee -that the UTF-8 string is properly formed. This routine is used by -procedures that are operating on a byte at a time and need to know if a -full Unicode character has been seen. +of \fInumBytes\fR bytes is long enough to be decoded by +\fBTcl_UtfToUniChar\fR/\fBTcl_UtfNext\fR, or 0 otherwise. This function +does not guarantee that the UTF-8 string is properly formed. This routine +is used by procedures that are operating on a byte at a time and need to +know if a full Unicode character has been seen. .PP \fBTcl_NumUtfChars\fR corresponds to \fBstrlen\fR for UTF-8 strings. It returns the number of Tcl_UniChars that are represented by the UTF-8 string \fIsrc\fR. The length of the source string is \fIlength\fR bytes. If the length is negative, all bytes up to the first null byte are used. @@ -253,11 +274,12 @@ .PP Given \fIsrc\fR, a pointer to some location in a UTF-8 string, \fBTcl_UtfNext\fR returns a pointer to the next UTF-8 character in the string. The caller must not ask for the next character after the last character in the string if the string is not terminated by a null -character. +character. \fBTcl_UtfCharComplete\fR can be used in that case to +make sure enough bytes are available before calling \fBTcl_UtfNext\fR. .PP \fBTcl_UtfPrev\fR is used to step backward through but not beyond the UTF-8 string that begins at \fIstart\fR. If the UTF-8 string is made up entirely of complete and well-formed characters, and \fIsrc\fR points to the lead byte of one of those characters (or to the location one byte @@ -270,28 +292,28 @@ It always returns a pointer greater than or equal to \fIstart\fR; that is, always a pointer to a location in the string. It always returns a pointer to a byte that begins a character when scanning for characters beginning from \fIstart\fR. When \fIsrc\fR is greater than \fIstart\fR, it always returns a pointer less than \fIsrc\fR and greater than or -equal to (\fIsrc\fR - \fBTCL_UTF_MAX\fR). The character that begins +equal to (\fIsrc\fR - 4). The character that begins at the returned pointer is the first one that either includes the byte \fIsrc[-1]\fR, or might include it if the right trail bytes are present at \fIsrc\fR and greater. \fBTcl_UtfPrev\fR never reads the byte \fIsrc[0]\fR nor the byte \fIstart[-1]\fR nor the byte -\fIsrc[-\fBTCL_UTF_MAX\fI-1]\fR. +\fIsrc[-5]\fR. .PP \fBTcl_UniCharAtIndex\fR corresponds to a C string array dereference or the Pascal Ord() function. It returns the Unicode character represented at the specified character (not byte) \fIindex\fR in the UTF-8 string \fIsrc\fR. The source string must contain at least \fIindex\fR -characters. If \fIindex\fR is TCL_INDEX_NONE or \fIindex\fR points +characters. If \fIindex\fR is negative 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, +\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 Index: doc/WrongNumArgs.3 ================================================================== --- doc/WrongNumArgs.3 +++ doc/WrongNumArgs.3 @@ -17,11 +17,11 @@ .SH ARGUMENTS .AS "Tcl_Obj *const" *message .AP Tcl_Interp interp in Interpreter in which error will be reported: error message gets stored in its result value. -.AP int objc in +.AP Tcl_Size objc in Number of leading arguments from \fIobjv\fR to include in error message. .AP "Tcl_Obj *const" objv[] in Arguments to command that had the wrong number of arguments. .AP "const char" *message in @@ -71,9 +71,15 @@ \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 Index: doc/abstract.n ================================================================== --- doc/abstract.n +++ doc/abstract.n @@ -10,11 +10,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME oo::abstract \- a class that does not allow direct instances of itself .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBoo::abstract\fI method \fR?\fIarg ...\fR? .fi .SH "CLASS HIERARCHY" .nf Index: doc/after.n ================================================================== --- doc/after.n +++ doc/after.n @@ -31,10 +31,11 @@ depending on the first argument to the command: .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. .TP \fBafter \fIms \fR?\fIscript script script ...\fR? @@ -50,10 +51,13 @@ 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 withn an event proc, +which will wait for next round of events). .TP \fBafter cancel \fIid\fR . Cancels the execution of a delayed command that was previously scheduled. Index: doc/binary.n ================================================================== --- doc/binary.n +++ doc/binary.n @@ -1,8 +1,8 @@ '\" -'\" Copyright (c) 1997 by Sun Microsystems, Inc. -'\" Copyright (c) 2008 by Donal K. Fellows +'\" Copyright (c) 1997 Sun Microsystems, Inc. +'\" Copyright (c) 2008 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH binary n 8.0 Tcl "Tcl Built-In Commands" @@ -42,12 +42,13 @@ .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. +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 @@ -79,11 +80,13 @@ .RE .TP \fBhex\fR . The \fBhex\fR binary encoding converts each byte to a pair of hexadecimal -digits in big-endian form. +digits that represent the byte value as a hexadecimal integer. +When encoding, lower characters are used. +When decoding, upper and lower characters are accepted. .RS .PP No options are supported during encoding. During decoding, the following options are supported: .TP @@ -236,11 +239,11 @@ .PP .CS \fB\e254\fR .CE .PP -(i.e. \fB\exac\fR) by +(i.e. \fB\exAC\fR) by truncating the high-bits of the character, and which is probably not what is desired. .RE .IP \fBA\fR 5 This form is the same as \fBa\fR except that spaces are used for @@ -294,11 +297,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\exe0\exe1\exa0\fR +\fB\exE0\exE1\exA0\fR .CE .RE .IP \fBH\fR 5 Stores a string of \fIcount\fR hexadecimal digits in high-to-low within each byte in the output binary string. \fIArg\fR must contain a @@ -321,11 +324,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\exab\ex00\exde\exf0\ex98\fR +\fB\exAB\ex00\exDE\exF0\ex98\fR .CE .RE .IP \fBh\fR 5 This form is the same as \fBH\fR except that the digits are stored in low-to-high order within each byte. This is seldom required. For example, @@ -336,11 +339,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\exba\ex00\exed\ex0f\ex89\fR +\fB\exBA\ex00\exED\ex0F\ex89\fR .CE .RE .IP \fBc\fR 5 Stores one or more 8-bit integer values in the output string. If no \fIcount\fR is specified, then \fIarg\fR must consist of an integer @@ -358,11 +361,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\ex03\exfd\ex80\ex04\ex02\ex05\fR +\fB\ex03\exFD\ex80\ex04\ex02\ex05\fR .CE .PP whereas: .PP .CS @@ -384,11 +387,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\ex03\ex00\exfd\exff\ex02\ex01\fR +\fB\ex03\ex00\exFD\exFF\ex02\ex01\fR .CE .RE .IP \fBS\fR 5 This form is the same as \fBs\fR except that it stores one or more 16-bit integers in big-endian byte order in the output string. For @@ -400,11 +403,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\ex00\ex03\exff\exfd\ex01\ex02\fR +\fB\ex00\ex03\exFF\exFD\ex01\ex02\fR .CE .RE .IP \fBt\fR 5 This form (mnemonically \fItiny\fR) is the same as \fBs\fR and \fBS\fR except that it stores the 16-bit integers in the output string in the @@ -424,11 +427,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\ex03\ex00\ex00\ex00\exfd\exff\exff\exff\ex00\ex00\ex01\ex00\fR +\fB\ex03\ex00\ex00\ex00\exFD\exFF\exFF\exFF\ex00\ex00\ex01\ex00\fR .CE .RE .IP \fBI\fR 5 This form is the same as \fBi\fR except that it stores one or more one or more 32-bit integers in big-endian byte order in the output string. @@ -440,11 +443,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\ex00\ex00\ex00\ex03\exff\exff\exff\exfd\ex00\ex01\ex00\ex00\fR +\fB\ex00\ex00\ex00\ex03\exFF\exFF\exFF\exFD\ex00\ex01\ex00\ex00\fR .CE .RE .IP \fBn\fR 5 This form (mnemonically \fInumber\fR or \fInormal\fR) is the same as \fBi\fR and \fBI\fR except that it stores the 32-bit integers in the @@ -505,11 +508,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\excd\excc\excc\ex3f\ex9a\ex99\ex59\ex40\fR +\fB\exCD\exCC\exCC\ex3F\ex9A\ex99\ex59\ex40\fR .CE .RE .IP \fBr\fR 5 This form (mnemonically \fIreal\fR) is the same as \fBf\fR except that it stores the single-precision floating point numbers in little-endian @@ -531,11 +534,11 @@ .CE .PP will return a binary string equivalent to: .PP .CS -\fB\ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f\fR +\fB\ex9A\ex99\ex99\ex99\ex99\ex99\exF9\ex3F\fR .CE .RE .IP \fBq\fR 5 This form (mnemonically the mirror of \fBd\fR) is the same as \fBd\fR except that it stores the double-precision floating point numbers in @@ -605,13 +608,13 @@ .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. +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 @@ -760,10 +763,19 @@ .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 @@ -774,11 +786,11 @@ scanned. If \fIcount\fR is omitted, then one hex digit will be scanned. For example, .RS .PP .CS -\fBbinary scan\fR \ex07\exC6\ex05\ex1f\ex34 H3H* var1 var2 +\fBbinary scan\fR \ex07\exC6\ex05\ex1F\ex34 H3H* var1 var2 .CE .PP will return \fB2\fR with \fB07c\fR stored in \fIvar1\fR and \fB051f34\fR stored in \fIvar2\fR. .RE @@ -825,11 +837,11 @@ \fIcount\fR is omitted, then one 16-bit integer will be scanned. For example, .RS .PP .CS -\fBbinary scan\fR \ex05\ex00\ex07\ex00\exf0\exff s2s* var1 var2 +\fBbinary scan\fR \ex05\ex00\ex07\ex00\exF0\exFF s2s* var1 var2 .CE .PP will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. Note that the integers returned are signed unless \fBsu\fR is used in place of \fBs\fR. @@ -839,11 +851,11 @@ as \fIcount\fR 16-bit integers represented in big-endian byte order. For example, .RS .PP .CS -\fBbinary scan\fR \ex00\ex05\ex00\ex07\exff\exf0 S2S* var1 var2 +\fBbinary scan\fR \ex00\ex05\ex00\ex07\exFF\exF0 S2S* var1 var2 .CE .PP will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. .RE @@ -864,11 +876,11 @@ \fIcount\fR is omitted, then one 32-bit integer will be scanned. For example, .RS .PP .CS -set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff +set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exF0\exFF\exFF\exFF \fBbinary scan\fR $str i2i* var1 var2 .CE .PP will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. Note that the integers returned are signed unless @@ -880,11 +892,11 @@ order, or as unsigned if \fBu\fR is placed immediately after the \fBI\fR. For example, .RS .PP .CS -set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0 +set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exFF\exFF\exFF\exF0 \fBbinary scan\fR $str I2I* var1 var2 .CE .PP will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. @@ -906,11 +918,11 @@ \fIcount\fR is omitted, then one 64-bit integer will be scanned. For example, .RS .PP .CS -set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff +set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exF0\exFF\exFF\exFF \fBbinary scan\fR $str wi* var1 var2 .CE .PP will return \fB2\fR with \fB30064771077\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. @@ -921,11 +933,11 @@ order, or as unsigned if \fBu\fR is placed immediately after the \fBW\fR. For example, .RS .PP .CS -set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0 +set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exFF\exFF\exFF\exF0 \fBbinary scan\fR $str WI* var1 var2 .CE .PP will return \fB2\fR with \fB21474836487\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. @@ -952,11 +964,11 @@ compiler dependent. For example, on a Windows system running on an Intel Pentium processor, .RS .PP .CS -\fBbinary scan\fR \ex3f\excc\excc\excd f var1 +\fBbinary scan\fR \ex3F\exCC\exCC\exCD f var1 .CE .PP will return \fB1\fR with \fB1.6000000238418579\fR stored in \fIvar1\fR. .RE @@ -976,11 +988,11 @@ machine's native representation. For example, on a Windows system running on an Intel Pentium processor, .RS .PP .CS -\fBbinary scan\fR \ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f d var1 +\fBbinary scan\fR \ex9A\ex99\ex99\ex99\ex99\ex99\exF9\ex3F d var1 .CE .PP will return \fB1\fR with \fB1.6000000000000001\fR stored in \fIvar1\fR. .RE Index: doc/callback.n ================================================================== --- doc/callback.n +++ doc/callback.n @@ -10,11 +10,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME callback, mymethod \- generate callbacks to methods .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBcallback\fR \fImethodName\fR ?\fIarg ...\fR? \fBmymethod\fR \fImethodName\fR ?\fIarg ...\fR? .fi .BE Index: doc/cd.n ================================================================== --- doc/cd.n +++ doc/cd.n @@ -26,11 +26,11 @@ .SH EXAMPLES .PP Change to the home directory of the user \fBfred\fR: .PP .CS -\fBcd\fR ~fred +\fBcd\fR [file home fred] .CE .PP Change to the directory \fBlib\fR that is a sibling directory of the current one: .PP Index: doc/chan.n ================================================================== --- doc/chan.n +++ doc/chan.n @@ -1,770 +1,678 @@ '\" '\" 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 \- Read, write and manipulate channels +chan \- Reads, writes and manipulates channels. .SH SYNOPSIS -\fBchan \fIoption\fR ?\fIarg arg ...\fR? +\fBchan \fIoperation\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. +\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: +.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. +.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 -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. +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 .TP -\fBchan configure \fIchannelId\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?... +\fBchan configure \fIchannelName\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?... . -Query or set the configuration options of the channel named -\fIchannelId\fR. +Configures or reports the configuration of \fIchannelName\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. +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. 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. +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. .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). +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. .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. +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. .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. +\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. +.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 -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. +\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 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. +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 .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. +. +\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. + +The default value is the empty string. The acceptable range is \ex01 - +\ex7F. A value outside this range results in an error. +.VS "TCL8.7 TIP656" +.TP +\fB\-profile\fR \fIprofile\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" +.TP +\fB\-translation\fR \fItranslation\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 -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: +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: .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. +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. .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. +Like \fBlf\fR, no end-of-line translation is performed, but in addition, sets +\fB\-eofchar\fR to the empty string to disable it, sets \fB\-encoding\fR to +\fBiso8859-1\fR, and sets \fB-profile\fR to \fBstrict\fR so the the 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. + .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. +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. .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. +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. .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. +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 .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. +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 -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 +\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 \fBfileevent\fR handler or otherwise) results +in a .QW "channel busy" error. .PP -\fBChan copy\fR translates end-of-line sequences in \fIinputChan\fR -and \fIoutputChan\fR according to the \fB\-translation\fR option for -these channels (see \fBchan configure\fR above). The translations -mean that the number of bytes read from \fIinputChan\fR can be -different than the number of bytes written to \fIoutputChan\fR. Only -the number of bytes written to \fIoutputChan\fR is reported, either as -the return value of a synchronous \fBchan copy\fR or as the argument -to the callback for an asynchronous \fBchan copy\fR. +.PP +.IP \fBEXAMPLES\fR +.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 +fconfigure $in -translation binary +fconfigure $out -translation binary +\fBfcopy\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 + close $in + close $out + if {[string length $error] != 0} { + # error occurred during the copy + } +} +set in [open $file1] +set out [socket $server $port] +\fBfcopy\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 {([string length $error] != 0) || [eof $in]} { + set done $total + close $in + close $out + } else { + \fBfcopy\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 +\fBfcopy\fR $in $out -size $chunk \e + -command [list CopyMore $in $out $chunk] +vwait done +.CE +.PP +The fourth example starts an asynchronous, bidirectional fcopy between +two sockets. Those could also be pipes from two [open "|hal 9000" r+] +(though their conversation would remain secret to the script, since +all four fileevent slots are busy). .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. +.CS +set flows 2 +proc Done {dir args} { + global flows done + puts "$dir is over." + incr flows -1 + if {$flows<=0} {set done 1} +} +\fBfcopy\fR $sok1 $sok2 -command [list Done UP] +\fBfcopy\fR $sok2 $sok1 -command [list Done DOWN] +vwait done +.CE .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. +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 +.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. +.TP +\fBchan event \fIchannelName event\fR ?\fIscript\fR? +. +Arranges for the given script, called a \fBchannel event hndler\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 +.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. +.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 .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, +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. +.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. +.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 +.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. +.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 +.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. +.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 -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 +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 +.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 +.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 +.PP .TP 10 \fBstart\fR . -The new access position will be \fIoffset\fR bytes from the start -of the underlying file or device. +The origin is the start of the data. This is the default. .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. +The origin is the current position. .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. +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 .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. +\fBchan tell \fIchannelName\fR +. +Returns the offset in bytes of the current position in the underlying data, or +-1 if the channel does not suport seeking. The value can be passed to \fBchan +seek\fR to set current position to that offset. .TP -\fBchan truncate \fIchannelId\fR ?\fIlength\fR? +\fBchan truncate \fIchannelName\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. +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 .PP -This opens a file using a known encoding (CP1252, a very common encoding -on Windows), searches for a string, rewrites that part, and truncates the -file after a further two lines. +In the following example a file is opened using the encoding CP1252, which is +common on Windows, searches for a string, rewrites that part, and truncates the +file two lines later. .PP .CS set f [open somefile.txt r+] \fBchan configure\fR $f -encoding cp1252 set offset 0 @@ -791,16 +699,16 @@ 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. +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} { +proc log message { \fBchan puts\fR stdout $message } # This is called whenever a new client connects to the server proc connect {chan host port} { Index: doc/class.n ================================================================== --- doc/class.n +++ doc/class.n @@ -10,11 +10,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME oo::class \- class of all classes .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBoo::class\fI method \fR?\fIarg ...\fR? .fi .SH "CLASS HIERARCHY" .nf Index: doc/classvariable.n ================================================================== --- doc/classvariable.n +++ doc/classvariable.n @@ -11,11 +11,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME classvariable \- create link from local variable to variable in class .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBclassvariable\fR \fIvariableName\fR ?\fI...\fR? .fi .BE .SH DESCRIPTION Index: doc/clock.n ================================================================== --- doc/clock.n +++ doc/clock.n @@ -6,11 +6,11 @@ .so man.macros .BS .SH NAME clock \- Obtain and manipulate dates and times .SH "SYNOPSIS" -package require \fBTcl 8.5\fR +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 @@ -184,13 +184,13 @@ .PP Surprising results may be obtained when crossing a point at which a leap second is inserted or removed; the \fBclock add\fR command simply ignores leap seconds and therefore assumes that times come in sequence, -23:59:58, 23:59:59, 00:00:00. (This assumption is handled by +23:59:58, 23:59:59, 00:00:00. This assumption is handled by the fact that Tcl's model of time reacts to leap seconds by speeding -or slowing the clock by a minuscule amount until Tcl's time +or slowing the clock by a miniscule amount until Tcl's time is back in step with the world. .PP The fact that adding and subtracting hours is defined in terms of absolute time means that it will add fixed amounts of time in time zones that observe summer time (Daylight Saving Time). For example, @@ -821,11 +821,11 @@ the minus sign one west of Greenwich. .PP A time zone string conforming to the Posix specification of the \fBTZ\fR environment variable will be recognized. The specification may be found at -\fIhttp://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html\fR. +\fIhttps://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html\fR. .PP If the Posix time zone string contains a DST (Daylight Savings Time) part, but doesn't contain a rule stating when DST starts or ends, then default rules are used. For Timezones with an offset between 0 and +12, the current European/Russian rules are used, otherwise the @@ -845,11 +845,11 @@ Any other time zone string is processed by prefixing a colon and attempting to use it as a location name, as above. .SH "LOCALIZATION" .PP Developers wishing to localize the date and time formatting and parsing -are referred to \fIhttp://tip.tcl.tk/173\fR for a +are referred to \fIhttps://tip.tcl-lang.org/173\fR for a specification. .SH "FREE FORM SCAN" .PP If the \fBclock scan\fR command is invoked without a \fB\-format\fR option, then it requests a \fIfree-form scan.\fR \fI @@ -949,9 +949,9 @@ .SH "SEE ALSO" msgcat(n) .SH KEYWORDS clock, date, time .SH "COPYRIGHT" -Copyright (c) 2004 Kevin B. Kenny . All rights reserved. +Copyright \(co 2004 Kevin B. Kenny . All rights reserved. '\" Local Variables: '\" mode: nroff '\" End: Index: doc/close.n ================================================================== --- doc/close.n +++ doc/close.n @@ -10,15 +10,16 @@ .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME close \- Close an open channel .SH SYNOPSIS -\fBclose \fIchannelId\fR ?r(ead)|w(rite)? +\fBclose \fIchannelId\fR ?\fBr\fR(\fBead\fR)|\fBw\fR(\fBrite\fR)? .BE .SH DESCRIPTION .PP -Closes or half-closes the channel given by \fIchannelId\fR. +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. @@ -47,16 +48,24 @@ \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. +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, \fBclose\fR -generates an error (similar to the \fBexec\fR 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 @@ -93,12 +102,12 @@ \fBclose\fR $chan return -options $options $result } .CE .SH "SEE ALSO" -file(n), open(n), socket(n), eof(n), Tcl_StandardChannels(3) +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: ADDED doc/configurable.n Index: doc/configurable.n ================================================================== --- /dev/null +++ doc/configurable.n @@ -0,0 +1,333 @@ +'\" +'\" 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\fR \fI\-prop\fR +\fIobjectName \fBconfigure\fR \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" +.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" +.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: +.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\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 +being created). +.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 +.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\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 +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: +.TP +\fBoo::configuresupport::configurable\fR +. +This is a class that provides the implementation of the \fBconfigure\fR method +(described above in \fBCONFIGURE METHOD\fR). +.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. +.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: +.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. +.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. +.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. +.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: Index: doc/cookiejar.n ================================================================== --- doc/cookiejar.n +++ doc/cookiejar.n @@ -176,15 +176,15 @@ .PP .CS package require http \fBpackage require cookiejar\fR -set cookiedb ~/.tclcookies.db +set cookiedb [file join [file home] cookiejar] http::configure -cookiejar [\fBhttp::cookiejar new\fR $cookiedb] # No further explicit steps are required to use cookies -set tok [http::geturl http://core.tcl.tk/] +set tok [http::geturl http://core.tcl-lang.org/] .CE .PP To only allow a particular domain to use cookies, perhaps because you only want to enable a particular host to create and manipulate sessions, create a subclass that imposes that policy. @@ -199,19 +199,19 @@ method \fBpolicyAllow\fR {operation domain path} { return [expr {$domain eq "my.example.com"}] } } -set cookiedb ~/.tclcookies.db +set cookiedb [file join [file home] cookiejar] http::configure -cookiejar [MyCookieJar new $cookiedb] # No further explicit steps are required to use cookies -set tok [http::geturl http://core.tcl.tk/] +set tok [http::geturl http://core.tcl-lang.org/] .CE .SH "SEE ALSO" http(n), oo::class(n), sqlite3(n) .SH KEYWORDS cookie, internet, security policy, www '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: Index: doc/copy.n ================================================================== --- doc/copy.n +++ doc/copy.n @@ -10,11 +10,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME oo::copy \- create copies of objects and classes .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBoo::copy\fI sourceObject \fR?\fItargetObject\fR? ?\fItargetNamespace\fR? .fi .BE .SH DESCRIPTION Index: doc/dde.n ================================================================== --- doc/dde.n +++ doc/dde.n @@ -170,11 +170,11 @@ This asks Internet Explorer (which must already be running) to go to a particularly important website: .PP .CS package require dde -\fBdde execute\fR -async iexplore WWW_OpenURL http://www.tcl.tk/ +\fBdde execute\fR -async iexplore WWW_OpenURL http://www.tcl-lang.org/ .CE .SH "SEE ALSO" tk(n), winfo(n), send(n) .SH KEYWORDS application, dde, name, remote execution Index: doc/define.n ================================================================== --- doc/define.n +++ doc/define.n @@ -10,11 +10,11 @@ '\" 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 +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? @@ -490,10 +490,16 @@ 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\-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 .TP \fIslot\fR \fB\-clear\fR . This sets the slot definition to the empty list. .TP Index: doc/dict.n ================================================================== --- doc/dict.n +++ doc/dict.n @@ -59,11 +59,11 @@ .TP \fBdict filter \fIdictionaryValue \fBscript {\fIkeyVariable valueVariable\fB} \fIscript\fR . The script rule tests for matching by assigning the key to the \fIkeyVariable\fR and the value to the \fIvalueVariable\fR, and then evaluating -the given script which should return a boolean value (with the +the given script which should result in a boolean value (with the key/value pair only being included in the result of the \fBdict filter\fR when a true value is returned.) Note that the first argument after the rule selection word is a two-element list. If the \fIscript\fR returns with a condition of \fBTCL_BREAK\fR, no further key/value pairs are considered for inclusion in the resulting Index: doc/encoding.n ================================================================== --- doc/encoding.n +++ doc/encoding.n @@ -1,115 +1,209 @@ '\" -'\" Copyright (c) 1998 by Scriptics Corporation. +'\" 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 \- Manipulate encodings +encoding \- Work with encodings .SH SYNOPSIS -\fBencoding \fIoption\fR ?\fIarg arg ...\fR? +\fBencoding \fIoperation\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. +In Tcl every string is composed of Unicode values. Text may be encoded into an +encoding such as cp1252, iso8859-1, Shitf\-JIS, utf-8, utf-16, etc. Not every +Unicode vealue 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. iso8859-1 an +encoding for a subset of Unicode in which each byte is a Unicode value of 255 +or less. Thus, 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 -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. +For example, the following is true: +.CS +set text {In Tcl binary data is treated as Unicode text and it just works.} +set encoded [encoding convertto iso8859-1 $text] +expr {$text eq $encoded}; #-> 1 +.CE +The following is also true: +.CS +set decoded [encoding convertfrom iso8859-1 $text] +expr {$text eq $decoded}; #-> 1 +.CE .SH DESCRIPTION .PP -Performs one of several encoding related operations, depending on -\fIoption\fR. The legal \fIoption\fRs are: +Performs one of the following encoding \fIoperations\fR: .TP \fBencoding convertfrom\fR ?\fIencoding\fR? \fIdata\fR +.TP +\fBencoding convertfrom\fR ?\fB-profile \fIprofile\fR? ?\fB-failindex var\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. +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" +.TP +\fBencoding convertto\fR ?\fIencoding\fR? \fIdata\fR .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. +\fBencoding convertto\fR ?\fB-profile \fIprofile\fR? ?\fB-failindex var\fR? \fIencoding\fR \fIdata\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" .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. +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. .TP \fBencoding names\fR . -Returns a list containing the names of all of the encodings that are -currently available. +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. +.VS "TCL8.7 TIP656" +.TP +\fBencoding profiles\fR +Returns a list of names of available encoding profiles. See \fBPROFILES\fR +below. +.VE "TCL8.7 TIP656" .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 +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. +.VS "TCL8.7 TIP656" +.TP +\fBtcl8\fR +. +The default profile. 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. + +When encoding, each character that cannot be represented in the encoding is +replaced by an encoding-dependent character, usually the question mark \fB?\fR. +.TP +\fBstrict\fR +. +The operation fails when invalid data for the encoding are encountered. +.TP +\fBreplace\fR +. +When decoding, invalid bytes are replaced by U+FFFD, the Unicode REPLACEMENT +CHARACTER. + +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. +.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 -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, +Example 1: Convert from euc-jp: .PP .CS -set s [\fBencoding convertfrom\fR euc-jp "\exA4\exCF"] +% codepoints [\fBencoding convertfrom\fR euc-jp \exA4\exCF] +U+00306F .CE .PP -would return the Unicode string +The result is the Unicode 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 [encoding convertfrom -profile tcl8 ascii A\ex80] +U+000041 U+000080 +% codepoints [encoding convertfrom -profile replace ascii A\ex80] +U+000041 U+00FFFD +% codepoints [encoding convertfrom -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 [encoding convertfrom -profile strict -failindex idx ascii AB\ex80] +U+000041 U+000042 +% set idx +2 +.CE +.PP +Example 4: Encode a character that is not representable in ISO8859-1: +.PP +.CS +% encoding convertto iso8859-1 A\eu0141 +A? +% encoding convertto -profile strict iso8859-1 A\eu0141 +unexpected character at index 1: 'U+000141' +% encoding convertto -profile strict -failindex idx iso8859-1 A\eu0141 +A +% set idx +1 +.CE +.VE "TCL8.7 TIP607, TIP656" +.PP .SH "SEE ALSO" -Tcl_GetEncoding(3) +Tcl_GetEncoding(3), fconfigure(n) .SH KEYWORDS encoding, unicode .\" Local Variables: .\" mode: nroff .\" End: Index: doc/exec.n ================================================================== --- doc/exec.n +++ doc/exec.n @@ -20,10 +20,14 @@ 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: @@ -192,11 +196,11 @@ redirected, and error output from all of the commands in the pipeline will go to the application's standard error file unless redirected. .PP The first word in each command is taken as the command name; -tilde-substitution is performed on it, and if the result contains +if the result contains no slashes then the directories in the PATH environment variable are searched for an executable by the given name. If the name contains a slash then it must refer to an executable reachable from the current directory. @@ -244,19 +248,10 @@ 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 @@ -293,15 +288,13 @@ .IP \(bu 3 The directory from which the Tcl executable was loaded. .IP \(bu 3 The current directory. .IP \(bu 3 -The Windows NT 32-bit system directory. +The Windows 32-bit system directory. .IP \(bu 3 -The Windows NT 16-bit system directory. -.IP \(bu 3 -The Windows NT home directory. +The Windows home directory. .IP \(bu 3 The directories listed in the path. .PP In order to execute shell built-in commands like \fBdir\fR and \fBcopy\fR, the caller must prepend the desired command with @@ -420,11 +413,13 @@ 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 @@ -452,11 +447,11 @@ \fBfile nativename\fR command. For example, to make a directory (on NTFS) encrypted so that only the current user can access it requires use of the \fICIPHER\fR command, like this: .PP .CS -set secureDir "~/Desktop/Secure Directory" +set secureDir [file join [file home] Desktop/SecureDirectory] file mkdir $secureDir \fBexec\fR CIPHER /e /s:[file nativename $secureDir] .CE .SH "SEE ALSO" error(n), file(n), open(n) Index: doc/expr.n ================================================================== --- doc/expr.n +++ doc/expr.n @@ -1,9 +1,9 @@ '\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-2000 Sun Microsystems, Inc. -'\" Copyright (c) 2005 by Kevin B. Kenny . All rights reserved +'\" Copyright (c) 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. '\" .TH expr n 8.5 Tcl "Tcl Built-In Commands" @@ -15,11 +15,11 @@ .SH SYNOPSIS \fBexpr \fIarg \fR?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP -The \fIexpr\fR command concatenates \fIarg\fRs, separated by a space, into an expression, and evaluates +Concatenates \fIarg\fRs, separated by a space, into an expression, and evaluates that expression, returning its value. The operators permitted in an expression include a subset of the operators permitted in C expressions. For those operators common to both Tcl and C, Tcl applies the same meaning and precedence as the corresponding C operators. @@ -35,43 +35,91 @@ Expressions differ from C expressions in the way that operands are specified. Expressions also support non-numeric operands, string comparisons, and some additional operators not found in C. .PP -When an expression evaluates to an integer, the value is the decimal form of -the integer, and when an expression evaluates to a floating-point number, the -value is the form produced by the \fB%g\fR format specifier of Tcl's -\fBformat\fR command. +When the result of expression is an integer, it is in decimal form, and when +the result is a floating-point number, it is in the form produced by the +\fB%g\fR format specifier of \fBformat\fR. +.PP +.VS "TIP 582" +At any point in the expression except within double quotes or braces, \fB#\fR +is the beginning of a comment, which lasts to the end of the line or +the end of the expression, whichever comes first. +.VE "TIP 582" .SS OPERANDS .PP An expression consists of a combination of operands, operators, parentheses and commas, possibly with whitespace between any of these elements, which is -ignored. +ignored. Each operand is interpreted as a numeric value if at all possible. .PP -An operand may be specified in any of the following ways: -.IP [1] -As a numeric value, either integer or floating-point. -.IP [2] -As a boolean value, using any form understood by \fBstring is\fR +Each operand has one of the following forms: +.RS +.PP +.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 hexadicimal. +.PP +A floating-point number may be take any of several +common decimal formats, and may use the decimal point \fB.\fR, +\fBe\fR or \fBE\fR for scientific notation, and +the sign characters \fB+\fR and \fB\-\fR. The +following are all valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16. +The strings \fBInf\fR +and \fBNaN\fR, in any combination of case, are also recognized as floating point +values. An operand that doesn't have a numeric interpretation must be quoted +with either braces or with double quotes. +.PP +Digits in any numeric value may be separated with one or more underscore +characters, "\fB_\fR". A separator may only +appear between digits, not appear at the start of a +numeric value, between the leading 0 and radix specifier, or at the +end of a numeric value. Here are some examples: +.PP +.CS +.ta 9c +\fBexpr\fR 100_000_000 \fI100000000\fR +\fBexpr\fR 0xffff_ffff \fI4294967295\fR +\fBformat\fR 0x%x 0b1111_1110_1101_1011 \fI0xfedb\fR +\fBexpr\fR 3_141_592_653_589e-1_2 \fI3.141592653589\fR +.CE +.RE + +.TP +A \fBboolean value\fR +. +Using any form understood by \fBstring is\fR \fBboolean\fR. -.IP [3] -As a variable, using standard \fB$\fR notation. -The value of the variable is then the value of the operand. -.IP [4] -As a string enclosed in double-quotes. -Backslash, variable, and command substitution are performed as described in +.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. -.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 +.TP +A Tcl command enclosed in \fBbrackets\fR +. +Command substitution is performed as according to the command substitution rule +for \fBTcl\fR. +.TP +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. +.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. @@ -80,55 +128,15 @@ and the value of \fBb\fR is 6. The command on the left side of each line produces the value on the right side. .PP .CS .ta 9c -\fBexpr\fR 3.1 + $a \fI6.1\fR -\fBexpr\fR 2 + "$a.$b" \fI5.6\fR -\fBexpr\fR 4*[llength "6 2"] \fI8\fR +\fBexpr\fR {3.1 + $a} \fI6.1\fR +\fBexpr\fR {2 + "$a.$b"} \fI5.6\fR +\fBexpr\fR {4*[llength {6 2}]} \fI8\fR \fBexpr\fR {{word one} < "word $a"} \fI0\fR .CE -.PP -\fBInteger value\fR -.PP -An integer operand may be specified in decimal (the normal case, the optional -first two characters are \fB0d\fR), binary -(the first two characters are \fB0b\fR), octal -(the first two characters are \fB0o\fR), or hexadecimal -(the first two characters are \fB0x\fR) form. For -.PP -\fBFloating-point value\fR -.PP -A floating-point number may be specified in any of several -common decimal formats, and may use the decimal point \fB.\fR, -\fBe\fR or \fBE\fR for scientific notation, and -the sign characters \fB+\fR and \fB\-\fR. The -following are all valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16. -The strings \fBInf\fR -and \fBNaN\fR, in any combination of case, are also recognized as floating point -values. An operand that doesn't have a numeric interpretation must be quoted -with either braces or with double quotes. -.PP -\fBBoolean value\fR -.PP -A boolean value may be represented by any of the values \fB0\fR, \fBfalse\fR, \fBno\fR, -or \fBoff\fR and any of the values \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR. -.PP -\fBDigit Separator\fR -.PP -Digits in any numeric value may be separated with one or more underscore -characters, "\fB_\fR", to improve readability. These separators may only -appear between digits. The separator may not appear at the start of a -numeric value, between the leading 0 and radix specifier, or at the -end of a numeric value. Here are some examples: -.PP -.CS -.ta 9c -\fBexpr\fR 100_000_000 \fI100000000\fR -\fBexpr\fR 0xffff_ffff \fI4294967295\fR -\fBformat\fR 0x%x 0b1111_1110_1101_1011 \fI0xfedb\fR -.CE .PP .SS OPERATORS .PP For operators having both a numeric mode and a string mode, the numeric mode is chosen when all operands have a numeric interpretation. The integer @@ -266,11 +274,11 @@ .QW "lazy evaluation" , which means that operands are not evaluated if they are not needed to determine the outcome. For example, in .PP .CS -\fBexpr\fR {$v ? [a] : [b]} +\fBexpr\fR {$v?[a]:[b]} .CE .PP only one of \fB[a]\fR or \fB[b]\fR is evaluated, depending on the value of \fB$v\fR. This is not true of the normal Tcl parser, so it is normally recommended to enclose the arguments to \fBexpr\fR in braces. @@ -483,11 +491,13 @@ 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: @@ -502,10 +512,11 @@ 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 . All rights reserved. +Copyright \(co 2005 Kevin B. Kenny . All rights reserved. .fi '\" Local Variables: '\" mode: nroff +'\" fill-column: 78 '\" End: Index: doc/fconfigure.n ================================================================== --- doc/fconfigure.n +++ doc/fconfigure.n @@ -100,30 +100,30 @@ 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 +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. +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. 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; +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" +.TP +\fB\-profile\fR \fIprofile\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" .TP \fB\-translation\fR \fImode\fR .TP \fB\-translation\fR \fB{\fIinMode outMode\fB}\fR . @@ -276,14 +276,14 @@ 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), +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, flushing, linemode, -newline, nonblocking, platform, translation, encoding, filter, byte array, +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: Index: doc/fcopy.n ================================================================== --- doc/fcopy.n +++ doc/fcopy.n @@ -10,94 +10,48 @@ .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fcopy \- Copy data from one channel to another .SH SYNOPSIS -\fBfcopy \fIinchan\fR \fIoutchan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR? +\fBfcopy \fIinputChan\fR \fIoutputChan\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 -error string associated with the error. -With a background copy, -it is not necessary to put \fIinchan\fR or \fIoutchan\fR into -non-blocking mode; the \fBfcopy\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 input operations with \fIinchan\fR, or -output operations with \fIoutchan\fR, during a background -\fBfcopy\fR. The converse is entirely legitimate, as exhibited by the -bidirectional fcopy example below. -.PP -If either \fIinchan\fR or \fIoutchan\fR get closed -while the copy is in progress, the current copy is stopped -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 +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. +.PP +\fB\-size\fR limits the number of characters copied. +.PP +\fB\-command\fR makes \fBfcopy\fR return immediately, work in the background, +and call \fIcallback\fR when the copy completes, providing as an additional +argument the number of characters written to \fIoutputChan\fR. If an error +occurres during the background copy, another argument provides the 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 other 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 \fBfileevent\fR handler or otherwise) results +in 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 @@ -142,19 +96,19 @@ set done $total close $in close $out } else { \fBfcopy\fR $in $out -size $chunk \e - -command [list CopyMore $in $out $chunk] + -command [list CopyMore $in $out $chunk] } } set in [open $file1] set out [socket $server $port] set chunk 1024 set total 0 \fBfcopy\fR $in $out -size $chunk \e - -command [list CopyMore $in $out $chunk] + -command [list CopyMore $in $out $chunk] vwait done .CE .PP The fourth example starts an asynchronous, bidirectional fcopy between two sockets. Those could also be pipes from two [open "|hal 9000" r+] Index: doc/file.n ================================================================== --- doc/file.n +++ doc/file.n @@ -14,54 +14,57 @@ .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: +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: .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. .TP \fBfile attributes \fIname\fR .TP \fBfile attributes \fIname\fR ?\fIoption\fR? .TP \fBfile attributes \fIname\fR ?\fIoption value option value...\fR? . -This subcommand returns or sets platform specific values associated -with a file. The first form returns a list of the platform specific -flags and their values. The second form returns the value for the -specific option. The third form sets one or more of the values. The -values are as follows: +This subcommand returns or sets platform-specific values associated +with a file. The first form returns a list of the platform-specific +options and their values. The second form returns the value for the +given option. The third form sets one or more of the values. The values +are as follows: .RS .PP -On Unix, \fB\-group\fR gets or sets the group name for the file. A group id -can be given to the command, but it returns a group name. \fB\-owner\fR gets -or sets the user name of the owner of the file. The command returns the -owner name, but the numerical id can be passed when setting the -owner. \fB\-permissions\fR sets or retrieves the octal code that chmod(1) -uses. This command does also has limited support for setting using the -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). +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 @@ -76,10 +79,23 @@ 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. +\fB-archive\fR gives the path of the mounted ZIP archive containing the file. +\fB-compsize\fR gives the compressed size of the file within the archive. +This is \fB0\fR for directories. +\fB-crc\fR gives the CRC of the file if present, else \fB0\fR. +\fB-mount\fR gives the path where the containing archive is mounted. +\fB-offset\fR gives the offset of the file within the archive. +\fB-uncompsize\fR gives the uncompressed size of the file. +This is \fB0\fR for directories. +Other attributes may be present in the returned list. These should +be ignored. .RE .TP \fBfile channels\fR ?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of names of all @@ -140,25 +156,10 @@ .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, @@ -174,10 +175,28 @@ \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 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" .TP \fBfile isdirectory \fIname\fR . Returns \fB1\fR if file \fIname\fR is a directory, \fB0\fR otherwise. .TP @@ -236,28 +255,25 @@ On Unix, symbolic links can be made to relative paths, and those paths must be relative to the actual \fIlinkName\fR's location (not to the cwd), but on all other platforms where relative links are not supported, target paths will always be converted to absolute, normalized form before the link is created (and therefore relative paths are interpreted -as relative to the cwd). Furthermore, -.QW ~user -paths are always expanded -to absolute form. When creating links on filesystems that either do not +as relative to the cwd). When creating links on filesystems that either do not support any links, or do not support the specific type requested, an error message will be returned. Most Unix platforms support both symbolic and hard links (the latter for files only). Windows supports symbolic directory links and hard file links on NTFS drives. .RE .TP -\fBfile lstat \fIname varName\fR +\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. +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. .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 @@ -272,10 +288,11 @@ 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. .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 @@ -374,37 +391,25 @@ . 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. +\fBfile stat \fIname ?varName?\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. .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 @@ -477,10 +482,26 @@ .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 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" .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, @@ -561,11 +582,11 @@ easily enough (equivalent to double-clicking on it in the Explorer interface) but the name passed to the operating system must be in native format: .PP .CS -exec {*}[auto_execok start] {} [\fBfile nativename\fR ~/example.txt] +exec {*}[auto_execok start] {} [\fBfile nativename\fR C:/Users/fred/example.txt] .CE .SH "SEE ALSO" filename(n), open(n), close(n), eof(n), gets(n), tell(n), seek(n), fblocked(n), flush(n) .SH KEYWORDS Index: doc/filename.n ================================================================== --- doc/filename.n +++ doc/filename.n @@ -45,11 +45,12 @@ 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 +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 @@ -116,30 +117,32 @@ \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 +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 -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). +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 -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. +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 @@ -148,13 +151,11 @@ '\""\" 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. +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 @@ -170,13 +171,13 @@ .QW ......... or dots with trailing characters .QW .....abc is illegal. .SH "SEE ALSO" -file(n), glob(n) +file(n), glob(n), zipfs(n) .SH KEYWORDS current directory, absolute file name, relative file name, volume-relative file name, portability '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: Index: doc/fpclassify.n ================================================================== --- doc/fpclassify.n +++ doc/fpclassify.n @@ -1,8 +1,8 @@ '\" -'\" Copyright (c) 2018 by Kevin B. Kenny . All rights reserved -'\" Copyright (c) 2019 by Donal Fellows +'\" Copyright (c) 2018 Kevin B. Kenny . 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" @@ -10,11 +10,11 @@ .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fpclassify \- Floating point number classification of Tcl values .SH SYNOPSIS -package require \fBTcl 8.7\fR +package require \fBtcl 8.7\fR .sp \fBfpclassify \fIvalue\fR .BE .SH DESCRIPTION The \fBfpclassify\fR command takes a floating point number, \fIvalue\fR, and @@ -74,10 +74,10 @@ 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 . All rights reserved +Copyright \(co 2018 Kevin B. Kenny . All rights reserved .fi '\" Local Variables: '\" mode: nroff '\" End: Index: doc/glob.n ================================================================== --- doc/glob.n +++ doc/glob.n @@ -44,12 +44,12 @@ 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. +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. .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 @@ -70,11 +70,11 @@ .QW "\fBglob \-tails \-directory $dir *\fR" is equivalent to .QW "\fBset pwd [pwd]; cd $dir; glob *; cd $pwd\fR" . For \fB\-path\fR specifications, the returned names will include the last path segment, so -.QW "\fBglob \-tails \-path [file rootname ~/foo.tex] .*\fR" +.QW "\fBglob \-tails \-path [file rootname /home/fred/foo.tex] .*\fR" will return paths like \fBfoo.aux foo.bib foo.tex\fR etc. .TP \fB\-types\fR \fItypeList\fR . Only list files or directories which match \fItypeList\fR, where the items @@ -166,47 +166,21 @@ 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. +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 @@ -237,11 +211,11 @@ .PP Find all the Tcl files in the user's home directory, irrespective of what the current directory is: .PP .CS -\fBglob\fR \-directory ~ *.tcl +\fBglob\fR \-directory [file home] *.tcl .CE .PP Find all subdirectories of the current directory: .PP .CS Index: doc/http.n ================================================================== --- doc/http.n +++ doc/http.n @@ -1,21 +1,21 @@ '\" '\" Copyright (c) 1995-1997 Sun Microsystems, Inc. -'\" Copyright (c) 1998-2000 by Ajuba Solutions. +'\" Copyright (c) 1998-2000 Ajuba Solutions. '\" Copyright (c) 2004 ActiveState Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -.TH "http" n 2.9 http "Tcl Bundled Packages" +.TH "http" n 2.10 http "Tcl Bundled Packages" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME http \- Client-side implementation of the HTTP/1.1 protocol .SH SYNOPSIS -\fBpackage require http\fI ?\fB2.9\fR? +\fBpackage require http\fR ?\fB2.10\fR? .\" See Also -useragent option documentation in body! .sp \fB::http::config\fR ?\fI\-option value\fR ...? .sp \fB::http::geturl \fIurl\fR ?\fI\-option value\fR ...? @@ -30,32 +30,71 @@ .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::postError \fItoken\fR .sp \fB::http::cleanup \fItoken\fR .sp +\fB::http::requestLine\fR \fItoken\fR +.sp +\fB::http::requestHeaders\fR \fItoken\fR ?\fIheaderName\fR? +.sp +\fB::http::requestHeaderValue\fR \fItoken\fR \fIheaderName\fR +.sp +\fB::http::responseLine\fR \fItoken\fR +.sp +\fB::http::responseCode\fR \fItoken\fR +.sp +\fB::http::reasonPhrase\fR \fIcode\fR +.sp +\fB::http::responseHeaders\fR \fItoken\fR ?\fIheaderName\fR? +.sp +\fB::http::responseHeaderValue\fR \fItoken\fR \fIheaderName\fR +.sp +\fB::http::responseInfo\fR \fItoken\fR +.sp +\fB::http::responseBody\fR \fItoken\fR +.sp \fB::http::register \fIproto port command\fR .sp \fB::http::registerError \fIport\fR ?\fImessage\fR? .sp \fB::http::unregister \fIproto\fR +.sp +\fB::http::code \fItoken\fR +.sp +\fB::http::data \fItoken\fR +.sp +\fB::http::meta \fItoken\fR ?\fIheaderName\fR? +.sp +\fB::http::metaValue\fR \fItoken\fR \fIheaderName\fR +.sp +\fB::http::ncode \fItoken\fR +.SH "EXPORTED COMMANDS" +.PP +Namespace \fBhttp\fR exports the commands \fBconfig\fR, \fBformatQuery\fR, +\fBgeturl\fR, \fBpostError\fR, \fBquoteString\fR, \fBreasonPhrase\fR, +\fBregister\fR, +\fBregisterError\fR, \fBrequestHeaders\fR, \fBrequestHeaderValue\fR, +\fBrequestLine\fR, \fBresponseBody\fR, \fBresponseCode\fR, +\fBresponseHeaders\fR, \fBresponseHeaderValue\fR, \fBresponseInfo\fR, +\fBresponseLine\fR, +\fBreset\fR, \fBunregister\fR, and \fBwait\fR. +.PP +It does not export the commands \fBcleanup\fR, \fBcode\fR, \fBdata\fR, +\fBerror\fR, \fBmeta\fR, \fBmetaValue\fR, \fBncode\fR, +\fBsize\fR, or \fBstatus\fR. .BE .SH DESCRIPTION .PP The \fBhttp\fR package provides the client side of the HTTP/1.1 -protocol, as defined in RFC 7230 to RFC 7235, which supersede RFC 2616. +protocol, as defined in RFC 9110 to 9112, which supersede RFC 7230 +to RFC 7235, which in turn supersede RFC 2616. The package implements the GET, POST, and HEAD operations of HTTP/1.1. It allows configuration of a proxy host to get through firewalls. The package is compatible with the \fBSafesock\fR security policy, so it can be used by untrusted applets to do URL fetching from a restricted set of hosts. This package can be extended to support @@ -64,22 +103,34 @@ .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. +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 callback is invoked +HTTP request and the \fB\-command\fR callback is invoked when the transaction completes. For this to work, the Tcl event loop must be active. In Tk applications this is always true. For pure-Tcl applications, the caller can use \fB::http::wait\fR after calling \fB::http::geturl\fR to start the event loop. +.PP +\fBNote:\fR The event queue is even used without the \fB\-command\fR option. +As a side effect, arbitrary commands may be processed while \fBhttp::geturl\fR +is running. +.PP +When the HTTP server has replied to the request, call the command +\fB::http::responseInfo\fR, which +returns a \fBdict\fR of metadata that is essential for identifying a +successful transaction and making use of the response. See +section \fBMETADATA\fR for details of the information returned. +The response itself is returned by command \fB::http::responseBody\fR, +unless it has been redirected to a file by the \fI\-channel\fR option +of \fB::http::geturl\fR. .SH COMMANDS .TP \fB::http::config\fR ?\fIoptions\fR? . The \fB::http::config\fR command is used to set and query the name of the @@ -115,34 +166,70 @@ 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. +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\-proxyauth\fR \fIstring\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. .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. +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 +.TP +\fB\-proxyhost\fR \fIhostname\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. +.TP +\fB\-proxynot\fR \fIlist\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. +.TP +\fB\-proxyport\fR \fInumber\fR +. +The port number of the proxy server. See \fB\-proxyfilter\fR for how the +value is used. .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 @@ -151,21 +238,34 @@ 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\-threadlevel\fR \fIlevel\fR +. +Specifies whether and how to use the \fBThread\fR package. Possible values +of \fIlevel\fR are 0, 1 or 2. +.RS +.PP +.DS +0 - (the default) do not use Thread +1 - use Thread if it is available, do not use it if it is unavailable +2 - use Thread if it is available, raise an error if it is unavailable +.DE +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 .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. +The default is \fButf-8\fR, as specified by RFC 2718. .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 @@ -176,25 +276,26 @@ 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. +.QW "\fBAccept-Encoding: gzip,deflate\fR" . +If the value is boolean \fBfalse\fR, then by default requests will send a header +.QW "\fBAccept-Encoding: identity\fR" . In either case the default can be overridden for an individual request by -supplying a custom \fBAccept-Encoding\fR header in the \fB-headers\fR option -of \fBhttp::geturl\fR. The default is 1. +supplying a custom \fBAccept-Encoding\fR header in the \fB\-headers\fR option +of \fBhttp::geturl\fR. The default value is 1. .RE .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\-query\fR or \fB\-querychannel\fR option causes a POST operation and the \fB\-validate\fR option causes a HEAD operation; otherwise, a GET operation is performed. The \fB::http::geturl\fR command -returns a \fItoken\fR value that can be used to get -information about the transaction. See the \fBSTATE ARRAY\fR and +returns a \fItoken\fR value that can be passed as an argument to other commands +to get information about the transaction. See the \fBMETADATA\fR and \fBERRORS\fR section for details. The \fB::http::geturl\fR command blocks until the operation completes, unless the \fB\-command\fR option specifies a callback that is invoked when the HTTP transaction completes. \fB::http::geturl\fR takes several options: @@ -202,11 +303,11 @@ .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 +type or whose content encoding is \fBgzip\fR or \fBdeflate\fR is considered binary data). .TP \fB\-blocksize\fR \fIsize\fR . The block size used when reading the URL. @@ -214,57 +315,97 @@ \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. +a Tcl variable for retrieval by \fB::http::responseBody\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 +The presence of this option causes \fB::http::geturl\fR to return immediately. +After the HTTP transaction completes, the value of \fIcallback\fR is expanded, +an additional argument is added, and the resulting command is evaluated. +The additional argument is the \fItoken\fR returned from \fB::http::geturl\fR. This token is the name of an array that is described in the \fBSTATE ARRAY\fR section. Here is a template for the callback: .RS .PP .CS proc httpCallback {token} { - upvar #0 $token state - # Access state as a Tcl array + upvar 0 $token state + # Access state as a Tcl array defined in this proc + ... + return } .CE +.PP +The \fB::http::geturl\fR command runs the \fB\-command\fR callback inside +a \fBcatch\fR command. Therefore an error in the callback command does +not call the \fBbgerror\fR handler. See the \fBERRORS\fR section for +details. .RE .TP +\fB\-guesstype\fR \fIboolean\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 \fI\-channel\fR is specified. +.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 +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 + 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 not send the header "\fBAccept-Encoding: gzip,deflate,compress\fR"). +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. +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 .TP \fB\-headers\fR \fIkeyvaluelist\fR . This option is used to add headers not already specified @@ -288,32 +429,51 @@ 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. +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\fR \fIPOST\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 .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 +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 meta-data, and the current number of bytes -transferred so far. The expected total size may be unknown, in which +\fBContent-Length\fR response header, and the current number of bytes +transferred so far. The token is the name of a global array that is +described in the \fBSTATE ARRAY\fR section. The expected total size may +be unknown, in which case zero is passed to the callback. Here is a template for the progress callback: .RS .PP .CS proc httpProgress {token total current} { - upvar #0 $token state + upvar 0 $token state + # Access state as a Tcl array defined in this proc + ... + return } .CE .RE .TP \fB\-protocol\fR \fIversion\fR @@ -322,14 +482,25 @@ 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. +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 .TP \fB\-queryblocksize\fR \fIsize\fR . The block size used when posting query data to the URL. At most @@ -342,32 +513,37 @@ . This flag causes \fB::http::geturl\fR to do a POST request that passes the data contained in \fIchannelID\fR to the server. The data contained in \fIchannelID\fR must be an x-url-encoding formatted query unless the \fB\-type\fR option below is used. -If a Content-Length header is not specified via the \fB\-headers\fR options, -\fB::http::geturl\fR attempts to determine the size of the post data +If a \fBContent-Length\fR header is not specified via the \fB\-headers\fR +options, \fB::http::geturl\fR attempts to determine the size of the post data in order to create that header. If it is unable to determine the size, it returns an error. .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). +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). .TP \fB\-strict\fR \fIboolean\fR . -Whether to enforce RFC 3986 URL validation on the request. Default is 1. +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. .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 +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. .TP \fB\-type\fR \fImime-type\fR . Use \fImime-type\fR as the \fBContent-Type\fR value, instead of the @@ -375,14 +551,15 @@ 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. +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 .TP \fB::http::formatQuery\fR \fIkey value\fR ?\fIkey value\fR ...? . This procedure does x-url-encoding of query data. It takes an even @@ -402,65 +579,217 @@ 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 +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. .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. +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 .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. +This command returns the number of bytes +received so far from the URL in the \fB::http::geturl\fR call. .TP -\fB::http::meta\fR \fItoken\fR +\fB::http::error\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. +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. +.TP +\fB::http::postError\fR \fItoken\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. .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 +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. +.TP +\fB::http::requestLine\fR \fItoken\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 +.TP +\fB::http::requestHeaders\fR \fItoken\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. +.TP +\fB::http::requestHeaderValue\fR \fItoken\fR \fIheaderName\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. +.TP +\fB::http::responseLine\fR \fItoken\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 +.TP +\fB::http::responseCode\fR \fItoken\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". +.TP +\fB::http::reasonPhrase\fR \fIcode\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 +.TP +\fB::http::responseHeaders\fR \fItoken\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. +.TP +\fB::http::responseHeaderValue\fR \fItoken\fR \fIheaderName\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\fR \fItoken\fR \fBSet-Cookie\fR. +.TP +\fB::http::responseInfo\fR \fItoken\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 +.TP +\fB::http::responseBody\fR \fItoken\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 .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 @@ -493,22 +822,38 @@ 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. +.TP +\fB::http::code\fR \fItoken\fR +. +An alternative name for the command \fB::http::responseLine\fR +.TP +\fB::http::data\fR \fItoken\fR +. +An alternative name for the command \fB::http::responseBody\fR. +.TP +\fB::http::meta\fR \fItoken\fR ?\fIheaderName\fR? +. +An alternative name for the command \fB::http::responseHeaders\fR +.TP +\fB::http::ncode\fR \fItoken\fR +. +An alternative name for the command \fB::http::responseCode\fR .SH ERRORS The \fB::http::geturl\fR procedure will raise errors in the following cases: invalid command line options, -an invalid URL, -a URL on a non-existent host, -or a URL at a bad port on an existing host. +or an invalid URL. These errors mean that it cannot even start the network transaction. -It will also raise an error if it gets an I/O error while -writing out the HTTP request header. For synchronous \fB::http::geturl\fR calls (where \fB\-command\fR is -not specified), it will raise an error if it gets an I/O error while +not specified), it will raise an error if +the URL is on a non-existent host +or at a bad port on an existing host. +It will also raise an error for any I/O errors while +writing out the HTTP request line and headers, or reading the HTTP reply headers or data. Because \fB::http::geturl\fR does not return a token in these cases, it does all the required cleanup and there is no issue of your app having to call \fB::http::cleanup\fR. .PP @@ -516,31 +861,40 @@ 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. +\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 -callback does. +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. +determined by examining the status from \fB::http::status\fR (or the value +of the \fIstatus\fR key in the dictionary returned +by \fB::http::responseInfo\fR). These are described below. .TP \fBok\fR . If the HTTP transaction completes entirely, then status will be \fBok\fR. -However, you should still check the \fB::http::code\fR value to get -the HTTP status. The \fB::http::ncode\fR procedure provides just -the numeric error (e.g., 200, 404 or 500) while the \fB::http::code\fR +However, you should still check the \fB::http::responseLine\fR value to get +the HTTP status. The \fB::http::responseCode\fR procedure provides just +the numeric error (e.g., 200, 404 or 500) while the \fB::http::responseLine\fR procedure returns a value like .QW "HTTP 404 File not found" . .TP \fBeof\fR . @@ -547,143 +901,451 @@ 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. +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. +.TP +\fBtimeout\fR +. +A timeout occurred before the transaction could complete. +.TP +\fBreset\fR +. +The user has called \fB::http::reset\fR. +.TP +\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 +\fB===== Essential Values =====\fR +.RE +.RE +.TP +\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". +.TP +\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). +.TP +\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. +.TP +\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. +.TP +\fBcontentType\fR +. +The value of the \fBContent-Type\fR response header or, if the header was not +supplied, the default value "application/octet-stream". +.TP +\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 \fI\-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 +.TP +\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). +.TP +\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. +.TP +\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. +.TP +\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 +.TP +\fBmethod\fR +. +The HTTP method used in the request. +.TP +\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. +.TP +\fBcompression\fR +. +A copy of the \fBContent-Encoding\fR response-header value. +.TP +\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. +.TP +\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. +.TP +\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 "#"). +.TP +\fBconnectionRequest\fR +. +The value, if any, sent to the server in \fBConnection\fR request header(s). +.TP +\fBconnectionResponse\fR +. +The value, if any, received from the server in \fBConnection\fR response +header(s). +.TP +\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"). +.TP +\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. +.TP +\fBtotalPost\fR +. +The total length of the request body in a POST request. +.TP +\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. +.TP +\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. +.TP +\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. +.TP +\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. +.TP +\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. +.TP +\fBContent-Encoding\fR +. +The compression algorithm used for the contents. +Examples include \fBgzip\fR, \fBdeflate\fR. +Dictionary key \fIcontent\fR. +.TP +\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. +.TP +\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 \fI\-cookiejar\fR, and so +the \fBSet-Cookie\fR headers need not be parsed by user scripts. +See section \fBCOOKIE JAR PROTOCOL\fR. +.TP +\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. +.TP +\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" +.PP +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. .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. +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 to -get to the state of the HTTP transaction in the form of a Tcl array. -Use this construct to create an easy-to-use array variable: +The \fB::http::geturl\fR procedure returns a \fItoken\fR that can be used +as an argument to other \fB::http::*\fR commands, which examine and manage +the state of the HTTP transaction. For most purposes these commands are +sufficient. The \fItoken\fR can also be used to access +the internal state of the transaction, which is stored in a Tcl array. +This facility is most useful when writing callback commands for the +options \fB\-command\fR, \fB\-handler\fR, \fB\-progress\fR, +or \fB\-queryprogress\fR. +Use the following command inside the proc to define an easy-to-use +array \fIstate\fR as a local variable within the proc .PP .CS -upvar #0 $token state +upvar 0 $token state .CE .PP Once the data associated with the URL is no longer needed, the state array should be unset to free up storage. The \fB::http::cleanup\fR procedure is provided for that purpose. -The following elements of -the array are supported: +.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 .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. +For dictionary key \fIbinary\fR. .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. +For command \fB::http::responseBody\fR. .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. +For dictionary key \fIcharset\fR. .TP \fBcoding\fR . -A copy of the \fBContent-Encoding\fR meta-data value. +For dictionary key \fIcompression\fR. +.TP +\fBconnection\fR +. +For dictionary key \fIconnectionActual\fR. .TP \fBcurrentsize\fR . -The current number of bytes fetched from the URL. -This value is returned by the \fB::http::size\fR command. +For command \fB::http::size\fR; and for dictionary key \fIcurrentSize\fR. .TP \fBerror\fR . -If defined, this is the error string seen when the HTTP transaction -was aborted. +For command \fB::http::error\fR; part is used in dictionary key \fIerror\fR. .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 +For command \fB::http::responseLine\fR. +.TP +\fBhttpResponse\fR +. +For dictionary key \fIhttpResponse\fR. .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 +For command \fB::http::responseHeaders\fR. Further discussion above in the +section \fBMORE METADATA\fR. +.TP +\fBmethod\fR +. +For dictionary key \fImethod\fR. .TP \fBposterror\fR . -The error, if any, that occurred while writing -the post query data to the server. +For dictionary key \fIpostError\fR. +.TP +\fBpostErrorFull\fR +. +For command \fB::http::postError\fR. +.TP +\fB\-protocol\fR +. +For dictionary key \fIhttpRequest\fR. +.TP +\fBquerylength\fR +. +For dictionary key \fItotalPost\fR. +.TP +\fBqueryoffset\fR +. +For dictionary key \fIcurrentPost\fR. +.TP +\fBreasonPhrase\fR +. +For dictionary key \fIreasonPhrase\fR. +.TP +\fBrequestHeaders\fR +. +For command \fB::http::requestHeaders\fR. +.TP +\fBrequestLine\fR +. +For command \fB::http::requestLine\fR. +.TP +\fBresponseCode\fR +. +For dictionary key \fIresponseCode\fR. +.TP +\fBstate\fR +. +For dictionary key \fIstage\fR. .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. +For command \fB::http::status\fR; and for dictionary key \fIstatus\fR. .TP \fBtotalsize\fR . -A copy of the \fBContent-Length\fR meta-data value. +For dictionary key \fItotalSize\fR. +.TP +\fBtransfer\fR +. +For dictionary key \fItransferEncoding\fR. .TP \fBtype\fR . -A copy of the \fBContent-Type\fR meta-data value. +For dictionary key \fIcontentType\fR. +.TP +\fBupgrade\fR +. +For dictionary key \fIupgrade\fR. .TP \fBurl\fR . -The requested URL. +For dictionary key \fIurl\fR. .RE .SH "PERSISTENT CONNECTIONS" .PP .SS "BASICS" .PP @@ -699,13 +1361,13 @@ needed before sending the request again. The user may wish to verify whether the server was modified by the failed POST request, before sending the same request again. .PP A HTTP request will use a persistent socket if the call to -\fBhttp::geturl\fR has the option \fB-keepalive true\fR. It will use +\fBhttp::geturl\fR has the option \fB\-keepalive true\fR. It will use pipelining where permitted if the \fBhttp::config\fR option -\fB-pipeline\fR is boolean \fBtrue\fR (its default value). +\fB\-pipeline\fR is boolean \fBtrue\fR (its default value). .PP The http package maintains no more than one persistent connection to each server (i.e. each value of .QW "domain:port" ). If \fBhttp::geturl\fR is called to make a request over a persistent @@ -723,12 +1385,12 @@ .PP In accordance with RFC 7230, \fBhttp::geturl\fR does not pipeline requests that use the POST method. If a POST uses a persistent connection and is not the first request on that connection, \fBhttp::geturl\fR waits until it has received the response for the previous -request; or (if \fBhttp::config\fR option \fB-postfresh\fR is boolean \fBtrue\fR) it -uses a new connection for each POST. +request; or (if \fBhttp::config\fR option \fB\-postfresh\fR is boolean +\fBtrue\fR) it uses a new connection for each POST. .PP If the server is processing a number of pipelined requests, and sends a response header .QW "\fBConnection: close\fR" with one of the responses (other than the last), then subsequent responses @@ -744,47 +1406,48 @@ be certain whether the POST modified the state of the server. For HEAD or GET requests, \fBhttp::geturl\fR opens another connection and retransmits the failed request. However, if the request was a POST, RFC 7230 forbids automatic retry by default, suggesting either user confirmation, or confirmation by user-agent software that has semantic understanding of -the application. The \fBhttp::config\fR option \fB-repost\fR allows for +the application. The \fBhttp::config\fR option \fB\-repost\fR allows for either possibility. .PP Asynchronous close events can occur only in a short interval of time. The \fBhttp\fR package monitors each persistent connection for closure by the server. Upon detection, the connection is also closed at the client end, and subsequent requests will use a fresh connection. .PP -If the \fBhttp::geturl\fR command is called with option \fB-keepalive true\fR, +If the \fBhttp::geturl\fR command is called with option \fB\-keepalive true\fR, then it will both try to use an existing persistent connection (if one is available), and it will send the server a .QW "\fBConnection: keep-alive\fR" request header asking to keep the connection open for future requests. .PP -The \fBhttp::config\fR options \fB-pipeline\fR, \fB-postfresh\fR, and -\fB-repost\fR relate to persistent connections. +The \fBhttp::config\fR options \fB\-pipeline\fR, \fB\-postfresh\fR, and +\fB\-repost\fR relate to persistent connections. .PP -Option \fB-pipeline\fR, if boolean \fBtrue\fR, will pipeline GET and HEAD requests -made -over a persistent connection. POST requests will not be pipelined - if the +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. +Option \fB\-postfresh\fR, if boolean \fBtrue\fR, will override the +\fBhttp::geturl\fR option \fB\-keepalive\fR, and always open a fresh connection +for a POST request. .PP -Option \fB-repost\fR, if \fBtrue\fR, permits automatic retry of a POST request +Option \fB\-repost\fR, if \fBtrue\fR, permits automatic retry of a POST request that fails because it uses a persistent connection that the server has half-closed (an .QW "asynchronous close event" ). Subsequent GET and HEAD requests in a failed pipeline will also be retried. -\fIThe -repost option should be used only if the application understands +\fIThe \fB\-repost\fI option should be used only if the application understands that the retry is appropriate\fR - specifically, the application must know -that if the failed POST successfully modified the state of the server, a repeat POST -would have no adverse effect. +that if the failed POST successfully modified the state of the server, a repeat +POST would have no adverse effect. .VS TIP406 .SH "COOKIE JAR PROTOCOL" .PP Cookies are short key-value pairs used to implement sessions within the otherwise-stateless HTTP protocol. (See RFC 6265 for details; Tcl does not @@ -883,14 +1546,94 @@ 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 \fI\-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 \fI\-threadlevel\fR and the availability +of package Thread. +.PP +.SS "WITH TLS (HTTPS)" +.PP +The same \fI\-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 \fI\-threadlevel\fR values only if the script runs in the main +interpreter. A child interpreter must use \fI\-threadlevel 0\fR unless the +parent interpreter has provided alternative facilities. The main parent +interpreter may grant full \fI\-threadlevel\fR facilities to a child +interpreter, for example by aliasing, to \fB::http::socket\fR in the child, +a command that runs \fBhttp::socket\fR in the parent, and then transfers +the socket to the child. +.PP .SH EXAMPLE .PP This example creates a procedure to copy a URL to a file while printing a -progress meter, and prints the meta-data associated with the URL. +progress meter, and prints the response headers associated with the URL. .PP .CS proc httpcopy { url file {chunk 4096} } { set out [open $file w] set token [\fB::http::geturl\fR $url -channel $out \e @@ -898,11 +1641,11 @@ close $out # This ends the line started by httpCopyProgress puts stderr "" - upvar #0 $token state + upvar 0 $token state set max 0 foreach {name value} $state(meta) { if {[string length $name] > $max} { set max [string length $name] } @@ -918,11 +1661,11 @@ } return $token } proc httpCopyProgress {args} { - puts -nonewline stderr . + puts \-nonewline stderr . flush stderr } .CE .SH "SEE ALSO" safe(n), socket(n), safesock(n) Index: doc/info.n ================================================================== --- doc/info.n +++ doc/info.n @@ -66,12 +66,10 @@ \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? . @@ -172,11 +170,11 @@ . 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 +A precompiled script (loadable by the package \fBtbcload\fR), and no further information is available. .RE .TP \fBline\fR . @@ -489,10 +487,33 @@ .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 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 +.TP +\fB\-all\fR +. +With this option, the properties from the superclasses and mixins of the class +are also returned. +.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. +.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" .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 @@ -678,10 +699,34 @@ .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 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 +.TP +\fB\-all\fR +. +With this option, the properties from the class, superclasses and mixins of +the object are also returned. +.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. +.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" .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 Index: doc/interp.n ================================================================== --- doc/interp.n +++ doc/interp.n @@ -585,20 +585,20 @@ \fBdict\fR \fBeof\fR \fBerror\fR \fBeval\fR \fBexpr\fR \fBfblocked\fR \fBfcopy\fR \fBfileevent\fR \fBflush\fR \fBfor\fR \fBforeach\fR \fBformat\fR \fBgets\fR \fBglobal\fR \fBif\fR \fBincr\fR \fBinfo\fR \fBinterp\fR \fBjoin\fR \fBlappend\fR -\fBlassign\fR \fBlindex\fR \fBlinsert\fR \fBlist\fR -\fBllength\fR \fBlrange\fR \fBlrepeat\fR \fBlreplace\fR -\fBlsearch\fR \fBlset\fR \fBlsort\fR \fBnamespace\fR -\fBpackage\fR \fBpid\fR \fBproc\fR \fBputs\fR -\fBread\fR \fBregexp\fR \fBregsub\fR \fBrename\fR -\fBreturn\fR \fBscan\fR \fBseek\fR \fBset\fR -\fBsplit\fR \fBstring\fR \fBsubst\fR \fBswitch\fR -\fBtell\fR \fBtime\fR \fBtrace\fR \fBunset\fR -\fBupdate\fR \fBuplevel\fR \fBupvar\fR \fBvariable\fR -\fBvwait\fR \fBwhile\fR +\fBlassign\fR \fBledit\fR \fBlindex\fR \fBlinsert\fR +\fBlist\fR \fBllength\fR \fBlrange\fR \fBlrepeat\fR +\fBlreplace\fR \fBlsearch\fR \fBlseq\fR \fBlset\fR +\fBlsort\fR \fBnamespace\fR \fBpackage\fR \fBpid\fR +\fBproc\fR \fBputs\fR \fBread\fR \fBregexp\fR +\fBregsub\fR \fBrename\fR \fBreturn\fR \fBscan\fR +\fBseek\fR \fBset\fR \fBsplit\fR \fBstring\fR +\fBsubst\fR \fBswitch\fR \fBtell\fR \fBtime\fR +\fBtrace\fR \fBunset\fR \fBupdate\fR \fBuplevel\fR +\fBupvar\fR \fBvariable\fR \fBvwait\fR \fBwhile\fR .DE The following commands are hidden by \fBinterp create\fR when it creates a safe interpreter: .DS .ta 1.2i 2.4i 3.6i Index: doc/lappend.n ================================================================== --- doc/lappend.n +++ doc/lappend.n @@ -47,13 +47,13 @@ 1 2 % \fBlappend\fR var 3 4 5 1 2 3 4 5 .CE .SH "SEE ALSO" -list(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n) +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n) .SH KEYWORDS append, element, list, variable .\" Local variables: .\" mode: nroff .\" fill-column: 78 Index: doc/lassign.n ================================================================== --- doc/lassign.n +++ doc/lassign.n @@ -50,13 +50,13 @@ .PP .CS set ::argv [\fBlassign\fR $::argv argumentToReadOff] .CE .SH "SEE ALSO" -list(n), lappend(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n) +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n) .SH KEYWORDS assign, element, list, multiple, set, variable '\"Local Variables: '\"mode: nroff '\"End: ADDED doc/ledit.n Index: doc/ledit.n ================================================================== --- /dev/null +++ doc/ledit.n @@ -0,0 +1,91 @@ +'\" +'\" Copyright (c) 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. +'\" +.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. +.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, then 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: Index: doc/library.n ================================================================== --- doc/library.n +++ doc/library.n @@ -56,10 +56,11 @@ .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 @@ -68,26 +69,53 @@ 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 .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 .TP \fBauto_load \fIcmd\fR +. This command attempts to load the definition for a Tcl command named \fIcmd\fR. To do this, it searches an \fIauto-load path\fR, which is a list of one or more directories. The auto-load path is given by the global variable \fBauto_path\fR if it exists. If there is no -\fBauto_path\fR variable, then the TCLLIBPATH environment variable is +\fBauto_path\fR variable, then the \fBTCLLIBPATH\fR environment variable is used, if it exists. Otherwise the auto-load path consists of just the Tcl library directory. Within each directory in the auto-load path there must be a file \fBtclIndex\fR that describes one or more commands defined in that directory and a script to evaluate to load each of the commands. The \fBtclIndex\fR file should be generated @@ -102,10 +130,15 @@ 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 .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 @@ -154,10 +187,11 @@ 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 @@ -173,10 +207,11 @@ 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 @@ -195,18 +230,32 @@ 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. +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. .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 @@ -213,30 +262,47 @@ 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. +.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 .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. @@ -246,22 +312,34 @@ 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. +.RS +.PP +Not normally usefully accessed directly by user code. +.RE .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 .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 . @@ -273,43 +351,76 @@ 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 .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 .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. .TP \fBtcl_nonwordchars\fR +. This variable contains a regular expression that is used by routines like \fBtcl_endOfWord\fR to identify whether a character is part of a word or not. If the pattern matches a character, the character is -considered to be a non-word character. The default is "\\W". +considered to be a non-word character. The default value is +.QW "\\W" . .TP \fBtcl_wordchars\fR +. This variable contains a regular expression that is used by routines like \fBtcl_endOfWord\fR to identify whether a character is part of a word or not. If the pattern matches a character, the character is -considered to be a word character. The default is "\\w". +considered to be a word character. The default value is +.QW "\\w" . .SH "SEE ALSO" env(n), info(n), re_syntax(n) .SH KEYWORDS auto-exec, auto-load, library, unknown, word, whitespace '\"Local Variables: '\"mode: nroff '\"End: Index: doc/lindex.n ================================================================== --- doc/lindex.n +++ doc/lindex.n @@ -1,9 +1,9 @@ '\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. -'\" Copyright (c) 2001 by Kevin B. Kenny . All rights reserved. +'\" Copyright (c) 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. '\" .TH lindex n 8.4 Tcl "Tcl Built-In Commands" @@ -113,14 +113,14 @@ set idx 3 \fBlindex\fR {a b c d e f} $idx+2 \fI\(-> f\fR .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n), +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n), string(n) .SH KEYWORDS element, index, list '\"Local Variables: '\"mode: nroff '\"End: Index: doc/link.n ================================================================== --- doc/link.n +++ doc/link.n @@ -11,11 +11,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME link \- create link from command to method of object .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBlink\fR \fImethodName\fR ?\fI...\fR? \fBlink\fR \fB{\fIcommandName methodName\fB}\fR ?\fI...\fR? .fi .BE @@ -50,15 +50,15 @@ puts "This is Foo in [self]" } constructor {} { \fBlink\fR Foo - # The method foo is now directly accessible as foo here + # The method Foo is now directly accessible as Foo here \fBlink\fR {bar Foo} - # The method foo is now directly accessible as bar + # The method Foo is now directly accessible as bar \fBlink\fR {::ExternalCall Foo} - # The method foo is now directly accessible in the global + # The method Foo is now directly accessible in the global # namespace as ExternalCall } method grill {} { puts "Step 1:" @@ -69,17 +69,17 @@ } ABC create abc abc grill \fI\(-> Step 1:\fR - \fI\(-> This is foo in ::abc\fR + \fI\(-> This is Foo in ::abc\fR \fI\(-> Step 2:\fR - \fI\(-> This is foo in ::abc\fR + \fI\(-> This is Foo in ::abc\fR # Direct access via the linked command puts "Step 3:"; ExternalCall \fI\(-> Step 3:\fR - \fI\(-> This is foo in ::abc\fR + \fI\(-> This is Foo in ::abc\fR .CE .PP This example shows that multiple linked commands can be made in a call to \fBlink\fR, and that they can handle arguments. .PP @@ -86,11 +86,11 @@ .CS oo::class create Ex { constructor {} { \fBlink\fR a b c # The methods a, b, and c (defined below) are all now - # directly acessible within methods under their own names. + # directly accessible within methods under their own names. } method a {} { puts "This is a" } Index: doc/linsert.n ================================================================== --- doc/linsert.n +++ doc/linsert.n @@ -43,13 +43,13 @@ set newList [\fBlinsert\fR $midList end-1 lazy] # The old lists still exist though... set newerList [\fBlinsert\fR [\fBlinsert\fR $oldList end-1 quick] 1 lazy] .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n), +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n), string(n) .SH KEYWORDS element, insert, list '\" Local Variables: '\" mode: nroff Index: doc/list.n ================================================================== --- doc/list.n +++ doc/list.n @@ -44,13 +44,13 @@ .PP .CS \fBa b c d e f {g h}\fR .CE .SH "SEE ALSO" -lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n) +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n) .SH KEYWORDS element, list, quoting '\"Local Variables: '\"mode: nroff '\"End: Index: doc/llength.n ================================================================== --- doc/llength.n +++ doc/llength.n @@ -47,13 +47,13 @@ .CS % set var { }; puts "[string length $var],[\fBllength\fR $var]" 1,0 .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), linsert(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n) +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n) .SH KEYWORDS element, list, length '\" Local Variables: '\" mode: nroff '\" fill-column: 78 Index: doc/lmap.n ================================================================== --- doc/lmap.n +++ doc/lmap.n @@ -76,13 +76,13 @@ }}] # The value of prefix is "8 7 6 5 4" .CE .SH "SEE ALSO" break(n), continue(n), for(n), foreach(n), while(n), -list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n) +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n) .SH KEYWORDS foreach, iteration, list, loop, map '\" Local Variables: '\" mode: nroff '\" End: Index: doc/load.n ================================================================== --- doc/load.n +++ doc/load.n @@ -11,60 +11,56 @@ .SH NAME load \- Load machine code and initialize new commands .SH SYNOPSIS \fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName\fR .br -\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName packageName\fR +\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName prefix\fR .br -\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName packageName interp\fR +\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName prefix interp\fR .BE .SH DESCRIPTION .PP This command loads binary code from a file into the application's address space and calls an initialization procedure -in the package to incorporate it into an interpreter. \fIfileName\fR +in the library to incorporate it into an interpreter. \fIfileName\fR is the name of the file containing the code; its exact form varies from system to system but on most systems it is a shared library, such as a \fB.so\fR file under Solaris or a DLL under Windows. -\fIpackageName\fR is the name of the package, and is used to -compute the name of an initialization procedure. +\fIprefix\fR is used to compute the name of an initialization procedure. \fIinterp\fR is the path name of the interpreter into which to load -the package (see the \fBinterp\fR manual entry for details); +the library (see the \fBinterp\fR manual entry for details); if \fIinterp\fR is omitted, it defaults to the interpreter in which the \fBload\fR command was invoked. .PP Once the file has been loaded into the application's address space, one of two initialization procedures will be invoked in the new code. Typically the initialization procedure will add new commands to a Tcl interpreter. The name of the initialization procedure is determined by -\fIpackageName\fR and whether or not the target interpreter +\fIprefix\fR and whether or not the target interpreter is a safe one. For normal interpreters the name of the initialization -procedure will have the form \fIpkg\fB_Init\fR, where \fIpkg\fR -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 +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 \fIpkg\fB_SafeInit\fR -instead of \fIpkg\fB_Init\fR. -The \fIpkg\fB_SafeInit\fR function should be written carefully, so that it +of the initialization procedure will be \fIprefix\fB_SafeInit\fR +instead of \fIprefix\fB_Init\fR. +The \fIprefix\fB_SafeInit\fR function should be written carefully, so that it initializes the safe interpreter only with partial functionality provided -by the package that is safe for use by untrusted code. For more information +by the library that is safe for use by untrusted code. For more information on Safe\-Tcl, see the \fBsafe\fR manual entry. .PP The initialization procedure must match the following prototype: .PP .CS -typedef int \fBTcl_PackageInitProc\fR( +typedef int \fBTcl_LibraryInitProc\fR( Tcl_Interp *\fIinterp\fR); .CE .PP The \fIinterp\fR argument identifies the interpreter in which the -package is to be loaded. The initialization procedure must return +library is to be loaded. The initialization procedure must return \fBTCL_OK\fR or \fBTCL_ERROR\fR to indicate whether or not it completed successfully; in the event of an error it should set the interpreter's result to point to an error message. The result of the \fBload\fR command will be the result returned by the initialization procedure. .PP @@ -72,48 +68,47 @@ in an application. If a given \fIfileName\fR is loaded into multiple interpreters, then the first \fBload\fR will load the code and call the initialization procedure; subsequent \fBload\fRs will call the initialization procedure without loading the code again. For Tcl versions lower than 8.5, it is not possible to unload or reload a -package. From version 8.5 however, the \fBunload\fR command allows the unloading +library. From version 8.5 however, the \fBunload\fR command allows the unloading of libraries loaded with \fBload\fR, for libraries that are aware of the Tcl's unloading mechanism. .PP -The \fBload\fR command also supports packages that are statically -linked with the application, if those packages have been registered -by calling the \fBTcl_StaticPackage\fR procedure. -If \fIfileName\fR is an empty string, then \fIpackageName\fR must -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 +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 -package by that name, and uses it if it is found. If several +library by that name, and uses it if it is found. If several different files have been \fBload\fRed with different versions of -the package, Tcl picks the file that was loaded first. +the library, Tcl picks the file that was loaded first. .PP If \fB\-global\fR is specified preceding the filename, all symbols found in the shared library are exported for global use by other libraries. The option \fB\-lazy\fR delays the actual loading of symbols until their first actual use. The options may be abbreviated. The option \fB\-\-\fR indicates the end of the options, and should be used if you wish to use a filename which starts with \fB\-\fR -and you provide a packageName to the \fBload\fR command. +and you provide a prefix to the \fBload\fR command. .PP On platforms which do not support the \fB\-global\fR or \fB\-lazy\fR options, the options still exist but have no effect. Note that use of the \fB\-global\fR or \fB\-lazy\fR option may lead to crashes in your application later (in case of symbol conflicts resp. missing @@ -186,11 +181,11 @@ # Now execute the command defined by the extension foo .CE .SH "SEE ALSO" -info sharedlibextension, package(n), Tcl_StaticPackage(3), safe(n) +info sharedlibextension, package(n), Tcl_StaticLibrary(3), safe(n) .SH KEYWORDS binary code, dynamic library, load, safe interpreter, shared library '\"Local Variables: '\"mode: nroff '\"End: Index: doc/lpop.n ================================================================== --- doc/lpop.n +++ doc/lpop.n @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 2018 by Peter Spjuth. All rights reserved. +'\" Copyright (c) 2018 Peter Spjuth. All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lpop n 8.7 Tcl "Tcl Built-In Commands" @@ -84,14 +84,14 @@ .CS \fBlpop\fR x 1 1 0 \fI\(-> {{a b} {c d}} {{e f} h}\fR .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n), +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n), string(n) .SH KEYWORDS element, index, list, remove, pop, stack, queue '\"Local Variables: '\"mode: nroff '\"End: Index: doc/lrange.n ================================================================== --- doc/lrange.n +++ doc/lrange.n @@ -69,13 +69,13 @@ elements to % \fBlrange\fR $var 1 1 {elements to} .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n), +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n), string(n) .SH KEYWORDS element, list, range, sublist '\" Local Variables: '\" mode: nroff Index: doc/lremove.n ================================================================== --- doc/lremove.n +++ doc/lremove.n @@ -14,11 +14,11 @@ \fBlremove \fIlist\fR ?\fIindex ...\fR? .BE .SH DESCRIPTION .PP \fBlremove\fR returns a new list formed by simultaneously removing zero or -more elements of \fIlist\fR at each of the indices given by an arbirary number +more elements of \fIlist\fR at each of the indices given by an arbitrary number of \fIindex\fR arguments. The indices may be in any order and may be repeated; the element at index will only be removed once. The index values are interpreted the same as index values for the command \fBstring index\fR, supporting simple index arithmetic and indices relative to the end of the list. 0 refers to the first element of the list, and \fBend\fR refers to the @@ -44,14 +44,14 @@ .CS % \fBlremove\fR {a b c d e} 2 end-2 a b d e .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n) +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n) .SH KEYWORDS element, list, remove .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: Index: doc/lrepeat.n ================================================================== --- doc/lrepeat.n +++ doc/lrepeat.n @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 2003 by Simon Geard. All rights reserved. +'\" Copyright (c) 2003 Simon Geard. All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lrepeat n 8.5 Tcl "Tcl Built-In Commands" @@ -30,14 +30,14 @@ \fI\(-> a b c a b c a b c\fR \fBlrepeat\fR 3 [\fBlrepeat\fR 2 a] b c \fI\(-> {a a} b c {a a} b c {a a} b c\fR .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lreplace(n), -lreverse(n), lsearch(n), lset(n), lsort(n) +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n) .SH KEYWORDS element, index, list '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: Index: doc/lreplace.n ================================================================== --- doc/lreplace.n +++ doc/lreplace.n @@ -93,13 +93,13 @@ % set var [\fBlreplace\fR $var 12345 end+2 f g h i] a b c d e f g h i .CE .VE TIP505 .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), -lreverse(n), lsearch(n), lset(n), lsort(n), +lreverse(n), lsearch(n), lseq(n), lset(n), lsort(n), string(n) .SH KEYWORDS element, list, replace .\" Local variables: .\" mode: nroff Index: doc/lreverse.n ================================================================== --- doc/lreverse.n +++ doc/lreverse.n @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 2006 by Donal K. Fellows. All rights reserved. +'\" Copyright (c) 2006 Donal K. Fellows. All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lreverse n 8.5 Tcl "Tcl Built-In Commands" @@ -23,13 +23,13 @@ \fI\(-> c b a a\fR \fBlreverse\fR {a b {c d} e f} \fI\(-> f e {c d} b a\fR .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lsearch(n), lset(n), lsort(n) +lsearch(n), lseq(n), lset(n), lsort(n) .SH KEYWORDS element, list, reverse '\" Local Variables: '\" mode: nroff '\" End: Index: doc/lsearch.n ================================================================== --- doc/lsearch.n +++ doc/lsearch.n @@ -227,13 +227,13 @@ \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), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lset(n), lsort(n), +lreverse(n), lseq(n), lset(n), lsort(n), string(n) .SH KEYWORDS binary search, linear search, list, match, pattern, regular expression, search, string '\" Local Variables: ADDED doc/lseq.n Index: doc/lseq.n ================================================================== --- /dev/null +++ doc/lseq.n @@ -0,0 +1,128 @@ +'\" +'\" 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 +\fBlseq \fIstart \fR?(\fB..\fR|\fBto\fR)? \fIend\fR ??\fBby\fR? \fIstep\fR? + +\fBlseq \fIstart \fBcount\fR \fIcount\fR ??\fBby\fR? \fIstep\fR? + +\fBlseq \fIcount\fR ?\fBby \fIstep\fR? +.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 +count-1. + +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: + +.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 + +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 + +.CS \" + \fIcount\fR = int( (\fIend\fR - \fIstart\fR + \fIstep\fR) / \fIstep\fR ) +.\" +.CE + +.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: Index: doc/lset.n ================================================================== --- doc/lset.n +++ doc/lset.n @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 2001 by Kevin B. Kenny . All rights reserved. +'\" Copyright (c) 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. '\" .TH lset n 8.4 Tcl "Tcl Built-In Commands" @@ -136,14 +136,14 @@ \fI\(-> {{a b} {c d}} {{e f} {j h}}\fR \fBlset\fR x {1 1 0} j \fI\(-> {{a b} {c d}} {{e f} {j h}}\fR .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lsort(n) +lreverse(n), lsearch(n), lseq(n), lsort(n) string(n) .SH KEYWORDS element, index, list, replace, set '\"Local Variables: '\"mode: nroff '\"End: Index: doc/lsort.n ================================================================== --- doc/lsort.n +++ doc/lsort.n @@ -262,13 +262,13 @@ \fI%\fR \fBlsort\fR -command compare \e {{3 apple} {0x2 carrot} {1 dingo} {2 banana}} {1 dingo} {2 banana} {0x2 carrot} {3 apple} .CE .SH "SEE ALSO" -list(n), lappend(n), lassign(n), lindex(n), linsert(n), llength(n), +list(n), lappend(n), lassign(n), ledit(n), lindex(n), linsert(n), llength(n), lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n), -lreverse(n), lsearch(n), lset(n) +lreverse(n), lsearch(n), lseq(n), lset(n) .SH KEYWORDS element, list, order, sort '\" Local Variables: '\" mode: nroff '\" End: Index: doc/mathfunc.n ================================================================== --- doc/mathfunc.n +++ doc/mathfunc.n @@ -1,9 +1,9 @@ '\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-2000 Sun Microsystems, Inc. -'\" Copyright (c) 2005 by Kevin B. Kenny . All rights reserved +'\" Copyright (c) 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. '\" .TH mathfunc n 8.5 Tcl "Tcl Mathematical Functions" @@ -11,11 +11,11 @@ .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 +package require \fBTcl 8.5-\fR .sp \fB::tcl::mathfunc::abs\fR \fIarg\fR .br \fB::tcl::mathfunc::acos\fR \fIarg\fR .br @@ -355,11 +355,11 @@ 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 . +Copyright \(co 2005-2006 Kevin B. Kenny . .fi '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: Index: doc/mathop.n ================================================================== --- doc/mathop.n +++ doc/mathop.n @@ -9,11 +9,11 @@ .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 +package require \fBTcl 8.5-\fR .sp \fB::tcl::mathop::!\fR \fInumber\fR .br \fB::tcl::mathop::~\fR \fInumber\fR .br Index: doc/memory.n ================================================================== --- doc/memory.n +++ doc/memory.n @@ -1,8 +1,8 @@ '\" -'\" Copyright (c) 1992-1999 by Karl Lehenbauer and Mark Diekhans -'\" Copyright (c) 2000 by Scriptics Corporation. +'\" Copyright (c) 1992-1999 Karl Lehenbauer & Mark Diekhans +'\" Copyright (c) 2000 Scriptics Corporation. '\" All rights reserved. '\" .TH memory n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS @@ -39,11 +39,11 @@ 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 +Turn on or off the preinitialization of all allocated memory with bogus bytes. Useful for detecting the use of uninitialized values. .TP \fBmemory objs \fIfile\fR . Index: doc/msgcat.n ================================================================== --- doc/msgcat.n +++ doc/msgcat.n @@ -9,11 +9,11 @@ .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 +\fBpackage require tcl 8.7\fR .sp \fBpackage require msgcat 1.7\fR .sp \fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR? .sp @@ -71,11 +71,11 @@ 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. +\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. @@ -217,27 +217,25 @@ .CE .RE .PP .VS "TIP 499" .TP -\fB::msgcat:mcloadedlocales subcommand\fR ?\fIlocale\fR? +\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. +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 .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 +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 @@ -733,11 +731,11 @@ To register to a callback, use: .CS namespace eval gui { msgcat::mcpackageconfig changecmd updateGUI - proc updateGui args { + proc updateGUI args { puts "New locale is '[lindex $args 0]'." } } % msgcat::mclocale fr fr @@ -767,11 +765,11 @@ msgcat::mcpackagelocale set msgcat::mcpackageconfig unknowncmd "" .CE As an example, the user requires the week day in a certain locale as follows: .CS -clock format clock seconds -format %A -locale fr +clock format [clock seconds] -format %A -locale fr .CE \fBclock\fR sets the package locale to \fBfr\fR and looks for the day name as follows: .CS msgcat::mcpackagelocale set $locale return [lindex [msgcat::mc DAYS_OF_WEEK_FULL] $day] Index: doc/my.n ================================================================== --- doc/my.n +++ doc/my.n @@ -10,11 +10,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME my, myclass \- invoke any method of current object or its class .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBmy\fI methodName\fR ?\fIarg ...\fR? \fBmyclass\fI methodName\fR ?\fIarg ...\fR? .fi .BE Index: doc/namespace.n ================================================================== --- doc/namespace.n +++ doc/namespace.n @@ -159,11 +159,11 @@ .QW "qualified patterns" , this command first finds the matching exported commands. It then checks whether any of those commands were previously imported by the current namespace. If so, this command deletes the corresponding imported commands. -In effect, this un-does the action of a \fBnamespace import\fR command. +In effect, this undoes the action of a \fBnamespace import\fR command. .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, Index: doc/next.n ================================================================== --- doc/next.n +++ doc/next.n @@ -10,11 +10,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME next, nextto \- invoke superclass method implementations .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBnext\fR ?\fIarg ...\fR? \fBnextto\fI class\fR ?\fIarg ...\fR? .fi .BE @@ -94,11 +94,11 @@ Each filter should decide for itself whether to permit the execution to go forward to the proper implementation of the method (which it does by invoking the \fBnext\fR command as filters are inserted into the front of the method call chain) and is responsible for returning the result of \fBnext\fR. .PP -Filters are invoked when processing an invokation of the \fBunknown\fR +Filters are invoked when processing an invocation of the \fBunknown\fR method because of a failure to locate a method implementation, but \fInot\fR when invoking either constructors or destructors. (Note however that the \fBdestroy\fR method is a conventional method, and filters are invoked as normal when it is called.) .SH EXAMPLES Index: doc/object.n ================================================================== --- doc/object.n +++ doc/object.n @@ -10,11 +10,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME oo::object \- root class of the class hierarchy .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBoo::object\fI method \fR?\fIarg ...\fR? .fi .SH "CLASS HIERARCHY" .nf Index: doc/open.n ================================================================== --- doc/open.n +++ doc/open.n @@ -70,11 +70,11 @@ indicate that the opened channel should be configured as if with the \fBfconfigure\fR \fB\-translation binary\fR option, making the channel suitable for reading or writing of binary data. .PP In the second form, \fIaccess\fR consists of a list of any of the -following flags, all of which have the standard POSIX meanings. +following flags, most of which have the standard POSIX meanings. One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR. .TP 15 \fBRDONLY\fR . Open the file for reading only. @@ -126,10 +126,32 @@ .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: +.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 @@ -451,10 +473,16 @@ pipe is closed. These problems only occur because both Tcl and the child application are competing for the console at the same time. If the command pipeline is started from a script, so that Tcl is not accessing the console, or if the command pipeline does not use standard input or output, but is redirected from or to a file, then the above problems do not occur. +.PP +Files opened in the +.QW \fBa\fR +mode or with the \fBAPPEND\fR flag set are implemented by seeking immediately +before each write, which is not an atomic operation and does not carry the +guarantee of strict appending that is present on POSIX platforms. .RE .TP \fBUnix\fR\0\0\0\0\0\0\0 . Valid values for \fIfileName\fR to open a serial port are generally of the @@ -525,10 +553,23 @@ .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"] @@ -535,10 +576,22 @@ 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 Index: doc/packagens.n ================================================================== --- doc/packagens.n +++ doc/packagens.n @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH pkg::create n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS @@ -27,11 +27,11 @@ .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 +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 Index: doc/pkgMkIndex.n ================================================================== --- doc/pkgMkIndex.n +++ doc/pkgMkIndex.n @@ -106,11 +106,11 @@ 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 +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. .TP 15 Index: doc/re_syntax.n ================================================================== --- doc/re_syntax.n +++ doc/re_syntax.n @@ -135,15 +135,30 @@ later, under \fBESCAPES\fR. .RS 2 .TP 8 \fB^\fR . -matches at the beginning of a line +matches at the beginning of the string or a line (according to whether +matching is newline-sensitive or not, as described in \fBMATCHING\fR, +below). .TP \fB$\fR . -matches at the end of a line +matches at the end of the string or a line (according to whether +matching is newline-sensitive or not, as described in \fBMATCHING\fR, +below). +.RS +.PP +The difference between string and line matching modes is immaterial +when the string does not contain a newline character. The \fB\eA\fR +and \fB\eZ\fR constraint escapes have a similar purpose but are +always constraints for the overall string. +.PP +The default newline-sensitivity depends on the command that uses the +regular expression, and can be overridden as described in +\fBMETASYNTAX\fR, below. +.RE .TP \fB(?=\fIre\fB)\fR . \fIpositive lookahead\fR (AREs only), matches at any point where a substring matching \fIre\fR begins @@ -291,16 +306,16 @@ itself. (If there are no other equivalent collating elements, the treatment is as if the enclosing delimiters were .QW \fB[.\fR \& and .QW \fB.]\fR .) -For example, if \fBo\fR and \fB\[^o]\fR are the members of an +For example, if \fBo\fR and \fB\(^o\fR are the members of an equivalence class, then .QW \fB[[=o=]]\fR , -.QW \fB[[=\[^o]=]]\fR , +.QW \fB[[=\(^o=]]\fR , and -.QW \fB[o\[^o]]\fR \& +.QW \fB[o\(^o]\fR \& are all synonymous. An equivalence class may not be an endpoint of a range. .RS .PP (\fINote:\fR Tcl implements only the Unicode locale. It does not define any equivalence classes. The examples above are just illustrations.) @@ -429,11 +444,11 @@ . \fB[[:space:]]\fR .TP \fB\ew\fR . -\fB[[:alnum:]_]\fR (note underscore) +\fB[[:alnum:]_\eu203F\eu2040\eu2054\euFE33\euFE34\euFE4D\euFE4E\euFE4F\euFF3F]\fR (including punctuation connector characters) .TP \fB\eD\fR . \fB[^[:digit:]]\fR .TP @@ -441,11 +456,11 @@ . \fB[^[:space:]]\fR .TP \fB\eW\fR . -\fB[^[:alnum:]_]\fR (note underscore) +\fB[^[:alnum:]_\eu203F\eu2040\eu2054\euFE33\euFE34\euFE4D\euFE4E\euFE4F\euFF3F]\fR (including punctuation connector characters) .RE .PP Within bracket expressions, .QW \fB\ed\fR , .QW \fB\es\fR , Index: doc/refchan.n ================================================================== --- doc/refchan.n +++ doc/refchan.n @@ -9,11 +9,24 @@ .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? +.nf +\fBchan create \fImode cmdPrefix\fR + +\fIcmdPrefix \fBblocking\fR \fIchannelId mode\fR +\fIcmdPrefix \fBcget\fR \fIchannelId option\fR +\fIcmdPrefix \fBcgetall\fR \fIchannelId\fR +\fIcmdPrefix \fBconfigure\fR \fIchannelId option value\fR +\fIcmdPrefix \fBfinalize\fR \fIchannelId\fR +\fIcmdPrefix \fBinitialize\fR \fIchannelId mode\fR +\fIcmdPrefix \fBread\fR \fIchannelId count\fR +\fIcmdPrefix \fBseek\fR \fIchannelId offset base\fR +\fIcmdPrefix \fBwatch\fR \fIchannelId eventspec\fR +\fIcmdPrefix \fBwrite\fR \fIchannelId 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 @@ -51,12 +64,12 @@ \fBNote:\fR If the creation of the channel was aborted due to failures here, then the \fBfinalize\fR subcommand will not be called. .PP The \fImode\fR argument tells the handler whether the channel was opened for reading, writing, or both. It is a list containing any of -the strings \fBread\fR or \fBwrite\fR. The list will always -contain at least one element. +the strings \fBread\fR or \fBwrite\fR. The list may be empty, but +will usually contain at least one element. .PP The subcommand must throw an error if the chosen mode is not supported by the \fIcmdPrefix\fR. .RE .TP @@ -320,10 +333,23 @@ 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 +.TP +\fIcmdPrefix \fBtruncate\fR \fIchannelId 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; Index: doc/safe.n ================================================================== --- doc/safe.n +++ doc/safe.n @@ -21,14 +21,17 @@ .sp \fB::safe::interpAddToAccessPath\fR \fIchild\fR \fIdirectory\fR .sp \fB::safe::interpFindInAccessPath\fR \fIchild\fR \fIdirectory\fR .sp +\fB::safe::setSyncMode\fR ?\fInewValue\fR? +.sp \fB::safe::setLogCmd\fR ?\fIcmd arg...\fR? .SS OPTIONS .PP ?\fB\-accessPath\fR \fIpathList\fR? +?\fB\-autoPath\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 @@ -146,10 +149,19 @@ $child eval [list set tk_library \e [::safe::interpAddToAccessPath $name $tk_library]] .CE .RE .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. +.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 @@ -197,10 +209,17 @@ 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\-autoPath\fR \fIdirectoryList\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. +.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. @@ -329,11 +348,12 @@ Each element of the initial access path list will be assigned a token that will be set in the child \fBauto_path\fR and the first element of that list will be set as the \fBtcl_library\fR for that child. .PP -If the access path argument is not given or is the empty list, +If the access path argument is not given to \fB::safe::interpCreate\fR or +\fB::safe::interpInit\fR or is the empty list, the default behavior is to let the child access the same packages as the parent has access to (Or to be more precise: only packages written in Tcl (which by definition cannot be dangerous as they run in the child interpreter) and C extensions that provides a _SafeInit entry point). For that purpose, the parent's @@ -355,13 +375,157 @@ .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. + +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), source(n), unknown(n) +interp(n), library(n), load(n), package(n), pkg_mkIndex(n), source(n), +tm(n), unknown(n) .SH KEYWORDS alias, auto\-loading, auto_mkindex, load, parent interpreter, safe interpreter, child interpreter, source '\" Local Variables: '\" mode: nroff '\" End: Index: doc/self.n ================================================================== --- doc/self.n +++ doc/self.n @@ -10,11 +10,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME self \- method call internal introspection .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBself\fR ?\fIsubcommand\fR? .fi .BE .SH DESCRIPTION Index: doc/singleton.n ================================================================== --- doc/singleton.n +++ doc/singleton.n @@ -10,11 +10,11 @@ '\" Note: do not modify the .SH NAME line immediately below! .SH NAME oo::singleton \- a class that does only allows one instance of itself .SH SYNOPSIS .nf -package require TclOO +package require tcl::oo \fBoo::singleton\fI method \fR?\fIarg ...\fR? .fi .SH "CLASS HIERARCHY" .nf Index: doc/socket.n ================================================================== --- doc/socket.n +++ doc/socket.n @@ -1,8 +1,8 @@ '\" '\" Copyright (c) 1996 Sun Microsystems, Inc. -'\" Copyright (c) 1998-1999 by Scriptics Corporation. +'\" Copyright (c) 1998-1999 Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH socket n 8.6 Tcl "Tcl Built-In Commands" @@ -160,11 +160,12 @@ \fBchan configure\fR command to retrieve the \fB\-sockname\fR option as described below. .SH "CONFIGURATION OPTIONS" .PP The \fBchan configure\fR command can be used to query several readonly -configuration options for socket channels: +configuration options for socket channels or in some cases to set +alternative properties on socket channels: .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 @@ -202,10 +203,20 @@ 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. +.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. +.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 Index: doc/source.n ================================================================== --- doc/source.n +++ doc/source.n @@ -35,13 +35,11 @@ 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 , +.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 Index: doc/string.n ================================================================== --- doc/string.n +++ doc/string.n @@ -317,13 +317,14 @@ first character of the string. \fIFirst\fR and \fIlast\fR may be specified as for the \fBindex\fR method. If \fInewstring\fR is specified, then it is placed in the removed character range. If \fIfirst\fR is less than zero then it is treated as if it were zero, and if \fIlast\fR is greater than or equal to the length of the string -then it is treated as if it were \fBend\fR. If \fIfirst\fR is greater -than \fIlast\fR or the length of the initial string, or \fIlast\fR is -less than 0, then the initial string is returned untouched. +then it is treated as if it were \fBend\fR. The initial string is +returned untouched, if \fIfirst\fR is greater than \fIlast\fR, or if +\fIfirst\fR is equal to or greater than the length of the initial string, +or \fIlast\fR is less than 0. .TP \fBstring reverse \fIstring\fR . Returns a string that is the same length as \fIstring\fR but with its characters in the reverse order. @@ -380,46 +381,12 @@ .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 Index: doc/tclsh.1 ================================================================== --- doc/tclsh.1 +++ doc/tclsh.1 @@ -36,19 +36,15 @@ Instead of reading commands from standard input \fBtclsh\fR will read Tcl commands from the named file; \fBtclsh\fR will exit when it reaches the end of the file. The end of the file may be marked either by the physical end of the medium, or by the character, -.QW \e032 -.PQ \eu001a ", control-Z" . +.PQ \ex1A ", control-Z" . If this character is present in the file, the \fBtclsh\fR application will read text up to but not including the character. An application that requires this character in the file may safely encode it as -.QW \e032 , -.QW \ex1a , -or -.QW \eu001a ; +.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 Index: doc/tcltest.n ================================================================== --- doc/tcltest.n +++ doc/tcltest.n @@ -623,18 +623,18 @@ will only be run if the constraint \fBunix\fR is true, which indicates the test suite is being run on a Unix platform. .PP Each \fBtest\fR should include whatever \fB\-constraints\fR are required to constrain it to run only where appropriate. Several -constraints are pre-defined in the \fBtcltest\fR package, listed +constraints are predefined in the \fBtcltest\fR package, listed below. The registration of user-defined constraints is performed by the \fBtestConstraint\fR command. User-defined constraints may appear within a test file, or within the script specified by the \fBconfigure \-load\fR or \fBconfigure \-loadfile\fR options. .PP -The following is a list of constraints pre-defined by the +The following is a list of constraints predefined by the \fBtcltest\fR package itself: .TP \fIsingleTestInterp\fR . This test can only be run if all test files are sourced into a single @@ -1177,11 +1177,10 @@ .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 Index: doc/tclvars.n ================================================================== --- doc/tclvars.n +++ doc/tclvars.n @@ -28,10 +28,14 @@ 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. @@ -71,15 +75,15 @@ 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. +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 Index: doc/timerate.n ================================================================== --- doc/timerate.n +++ doc/timerate.n @@ -33,14 +33,14 @@ \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 +If \fImax-count\fR is specified, the evaluation will stop either this count of iterations is reached or the time is exceeded. .sp -It will then return a canonical tcl-list of the form: +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 @@ -83,11 +83,11 @@ 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. +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. Index: doc/tm.n ================================================================== --- doc/tm.n +++ doc/tm.n @@ -293,16 +293,20 @@ \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 http://tip.tcl.tk/189.html), Tcl Improvement Proposal #190 +(online at https://tip.tcl-lang.org/189.html), Tcl Improvement Proposal #190 .QW "\fIImplementation Choices for Tcl Modules\fR" -(online at http://tip.tcl.tk/190.html) +(online at https://tip.tcl-lang.org/190.html) .SH "KEYWORDS" modules, package .\" Local Variables: .\" mode: nroff .\" End: Index: doc/trace.n ================================================================== --- doc/trace.n +++ doc/trace.n @@ -227,22 +227,22 @@ .PP .CS \fIcommandPrefix name1 name2 op\fR .CE .PP -\fIName1\fR and \fIname2\fR give the name(s) for the variable -being accessed: if the variable is a scalar then \fIname1\fR -gives the variable's name and \fIname2\fR is an empty string; -if the variable is an array element then \fIname1\fR gives the -name of the array and name2 gives the index into the array; -if an entire array is being deleted and the trace was registered +\fIName1\fR gives the name for the variable being accessed. +This is not necessarily the same as the name used in the +\fBtrace add variable\fR command: the \fBupvar\fR command allows a +procedure to reference a variable under a different name. +If the trace was originally set on an array or array element, +\fIname2\fR provides which index into the array was affected. +This information is present even when \fIname1\fR refers to a +scalar, which may happen if the \fBupvar\fR command was used to +create a reference to a single array element. +If an entire array is being deleted and the trace was registered on the overall array, rather than a single element, then \fIname1\fR gives the array name and \fIname2\fR is an empty string. -\fIName1\fR and \fIname2\fR are not necessarily the same as the -name used in the \fBtrace variable\fR command: the \fBupvar\fR -command allows a procedure to reference a variable under a -different name. \fIOp\fR indicates what operation is being performed on the variable, and is one of \fBread\fR, \fBwrite\fR, or \fBunset\fR as defined above. .PP \fICommandPrefix\fR executes in the same context as the code that invoked @@ -354,30 +354,10 @@ 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): Index: doc/transchan.n ================================================================== --- doc/transchan.n +++ doc/transchan.n @@ -9,11 +9,22 @@ .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? +.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 Index: doc/try.n ================================================================== --- doc/try.n +++ doc/try.n @@ -85,11 +85,11 @@ .PP Handle different reasons for a file to not be openable for reading: .PP .CS \fBtry\fR { - set f [open /some/file/name w] + set f [open /some/file/name r] } \fBtrap\fR {POSIX EISDIR} {} { puts "failed to open /some/file/name: it's a directory" } \fBtrap\fR {POSIX ENOENT} {} { puts "failed to open /some/file/name: it doesn't exist" } Index: doc/unload.n ================================================================== --- doc/unload.n +++ doc/unload.n @@ -11,22 +11,22 @@ .SH NAME unload \- Unload machine code .SH SYNOPSIS \fBunload \fR?\fIswitches\fR? \fIfileName\fR .br -\fBunload \fR?\fIswitches\fR? \fIfileName packageName\fR +\fBunload \fR?\fIswitches\fR? \fIfileName prefix\fR .br -\fBunload \fR?\fIswitches\fR? \fIfileName packageName interp\fR +\fBunload \fR?\fIswitches\fR? \fIfileName prefix interp\fR .BE .SH DESCRIPTION .PP This command tries to unload shared libraries previously loaded with \fBload\fR from the application's address space. \fIfileName\fR is the name of the file containing the library file to be unload; it must be the same as the filename provided to \fBload\fR for loading the library. -The \fIpackageName\fR argument is the name of the package (as +The \fIprefix\fR argument is the prefix (as determined by or passed to \fBload\fR), and is used to compute the name of the unload procedure; if not supplied, it is computed from \fIfileName\fR in the same manner as \fBload\fR. The \fIinterp\fR argument is the path name of the interpreter from which to unload the package (see the \fBinterp\fR manual entry for @@ -64,16 +64,16 @@ proper reference count. .PP \fBunload\fR works in the opposite direction. As a first step, \fBunload\fR will check whether the library is unloadable: an unloadable library exports a special unload procedure. The name of the unload procedure is determined by -\fIpackageName\fR and whether or not the target interpreter +\fIprefix\fR and whether or not the target interpreter is a safe one. For normal interpreters the name of the initialization -procedure will have the form \fIpkg\fB_Unload\fR, where \fIpkg\fR -is the same as \fIpackageName\fR except that the first letter is +procedure will have the form \fIpfx\fB_Unload\fR, where \fIpfx\fR +is the same as \fIprefix\fR except that the first letter is converted to upper case and all other letters -are converted to lower case. For example, if \fIpackageName\fR is +are converted to lower case. For example, if \fIprefix\fR is \fBfoo\fR or \fBFOo\fR, the initialization procedure's name will be \fBFoo_Unload\fR. If the target interpreter is a safe interpreter, then the name of the initialization procedure will be \fIpkg\fB_SafeUnload\fR instead of \fIpkg\fB_Unload\fR. @@ -88,11 +88,11 @@ .SS "UNLOAD HOOK PROTOTYPE" .PP The unload procedure must match the following prototype: .PP .CS -typedef int \fBTcl_PackageUnloadProc\fR( +typedef int \fBTcl_LibraryUnloadProc\fR( Tcl_Interp *\fIinterp\fR, int \fIflags\fR); .CE .PP The \fIinterp\fR argument identifies the interpreter from which the @@ -112,23 +112,24 @@ the \fIflags\fR argument will be set to \fBTCL_UNLOAD_DETACH_FROM_PROCESS\fR. .SS NOTES .PP The \fBunload\fR command cannot unload libraries that are statically linked with the application. -If \fIfileName\fR is an empty string, then the \fIpackageName\fR argument must +If \fIfileName\fR is an empty string, then the \fIprefix\fR argument must be specified. .PP -If \fIpackageName\fR is omitted or specified as an empty string, -Tcl tries to guess the name of the package. -This may be done differently on different platforms. -The default guess, which is used on most UNIX platforms, is to -take the last element of \fIfileName\fR, strip off the first -three characters if they are \fBlib\fR, and use any following -alphabetic and underline characters as the module name. -For example, the command \fBunload libxyz4.2.so\fR uses the module -name \fBxyz\fR and the command \fBunload bin/last.so {}\fR uses the -module name \fBlast\fR. +If \fIprefix\fR is omitted or specified as an empty string, +Tcl tries to guess the prefix. This may be done differently on +different platforms. The default guess, which is used on most +UNIX platforms, is to take the last element of +\fIfileName\fR, strip off the first three characters if they +are \fBlib\fR, then strip off the next three characters if they +are \fBtcl9\fR, and use any following wordchars but not digits, +converted to titlecase as the prefix. +For example, the command \fBunload libxyz4.2.so\fR uses the prefix +\fBXyz\fR and the command \fBunload bin/last.so {}\fR uses the +prefix \fBLast\fR. .SH "PORTABILITY ISSUES" .TP \fBUnix\fR\0\0\0\0\0 . Not all unix operating systems support library unloading. Under such Index: doc/upvar.n ================================================================== --- doc/upvar.n +++ doc/upvar.n @@ -92,19 +92,17 @@ proc \fIsetByUpvar\fR { name value } { \fBupvar\fR $name localVar set localVar $value } set originalVar 1 -trace variable originalVar w \fItraceproc\fR +trace add variable originalVar write \fItraceproc\fR \fIsetByUpvar\fR originalVar 2 .CE .PP -If \fIotherVar\fR refers to an element of an array, then variable -traces set for the entire array will not be invoked when \fImyVar\fR -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. +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 Index: doc/vwait.n ================================================================== --- doc/vwait.n +++ doc/vwait.n @@ -10,10 +10,12 @@ '\" 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 +.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 @@ -21,13 +23,80 @@ \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 +.TP +\fB\-\-\fR +. +Marks the end of options. All following arguments are handled as +variable names. +.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. +.TP +\fB\-extended\fR +. +An extended result in list form is returned, see below for explanation. +.TP +\fB\-nofileevents\fR +. +File events are not handled in the wait operation. +.TP +\fB\-noidleevents\fR +. +Idle handlers are not invoked during the wait operation. +.TP +\fB\-notimerevents\fR +. +Timer handlers are not serviced during the wait operation. +.TP +\fB\-nowindowevents\fR +. +Events of the windowing system are not handled during the wait operation. +.TP +\fB\-readable\fR \fIchannel\fR +. +\fIChannel\fR must name a Tcl channel open for reading. If \fIchannel\fR +is or becomes readable the wait operation completes. +.TP +\fB\-timeout\fR \fImilliseconds\fR +. +The wait operation is constrained to \fImilliseconds\fR. +.TP +\fB\-variable\fR \fIvarName\fR +. +\fIVarName\fR must be the name of a global variable. Writing or +unsetting this variable completes the wait operation. +.TP +\fB\-writable\fR \fIchannel\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 \fI\-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 \fI\-extended\fR option is specified, the result is made up +of a Tcl list with an even number of elements. Odd elements +take the values \fBreadable\fR, \fBtimeleft\fR, \fBvariable\fR, +and \fBwritable\fR. Even elements are the corresponding variable +and channel names or the remaining number of milliseconds. +The list is ordered by the occurrences of the event(s) with the +exception of \fBtimeleft\fR which always comes last. .PP In some cases the \fBvwait\fR command may not return immediately -after \fIvarName\fR is set. This happens if the event handler +after \fIvarName\fR et.al. is set. This happens if the event handler that sets \fIvarName\fR does not complete immediately. For example, if an event handler sets \fIvarName\fR and then itself calls \fBvwait\fR to wait for a different variable, then it may not return for a long time. During this time the top-level \fBvwait\fR is blocked waiting for the event handler to complete, so it cannot Index: doc/zipfs.3 ================================================================== --- doc/zipfs.3 +++ doc/zipfs.3 @@ -8,24 +8,24 @@ '\" .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 +TclZipfs_AppHook, TclZipfs_Mount, TclZipfs_MountBuffer, TclZipfs_Unmount \- handle ZIP files as Tcl virtual filesystems .SH SYNOPSIS .nf -int +const char * \fBTclZipfs_AppHook(\fIargcPtr, argvPtr\fR) .sp int -\fBTclzipfs_Mount\fR(\fIinterp, mountpoint, zipname, password\fR) +\fBTclZipfs_Mount\fR(\fIinterp, zipname, mountpoint, password\fR) .sp int -\fBTclZipfs_MountBuffer\fR(\fIinterp, mountpoint, data, dataLen, copy\fR) +\fBTclZipfs_MountBuffer\fR(\fIinterp, data, dataLen, mountpoint, copy\fR) .sp int -\fBTclzipfs_Unmount\fR(\fIinterp, mountpoint\fR) +\fBTclZipfs_Unmount\fR(\fIinterp, mountpoint\fR) .fi .SH ARGUMENTS .AS Tcl_Interp *mountpoint in .AP "int" *argcPtr in Pointer to a variable holding the number of command line arguments from @@ -41,11 +41,11 @@ .AP "const char" *mountpoint in Name of a mount point, which must be a legal Tcl file or directory name. May be NULL to query current mount points. .AP "const char" *password in An (optional) password. Use NULL if no password is wanted to read the file. -.AP "unsigned char" *data in +.AP "const void" *data in A data buffer to mount. The data buffer must hold the contents of a ZIP archive, and must not be NULL. .AP size_t dataLen in The number of bytes in the supplied data buffer argument, \fIdata\fR. .AP int copy in @@ -58,14 +58,12 @@ \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). +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. @@ -85,36 +83,48 @@ 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. +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 -\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 +If \fImountpoint\fR is not NULL but \fIzipfile\fR +is NULL, the path to the archive mounted at that mount point is stored +as \fIinterp\fR's result. The function returns a standard Tcl result code. .PP -\fBTclzipfs_MountBuffer\fR mounts the ZIP archive in the buffer pointed to by -\fIdata\fR on the mount point given in \fImountpoint\fR. The ZIP archive is -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. +\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 +\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 Index: doc/zipfs.n ================================================================== --- doc/zipfs.n +++ doc/zipfs.n @@ -12,11 +12,11 @@ '\" 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? +\fBpackage require tcl::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 @@ -24,24 +24,33 @@ \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 mount\fR ?\fIzipfile\fR? ?\fImountpoint\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? +'\" \fBzipfs mount_data\fR ?\fIdata\fR ?\fImountpoint\fR?? .BE .SH DESCRIPTION .PP -The \fBzipfs\fR command (the sole public command provided by the built-in -package with the same name) provides Tcl with the ability to mount the -contents of a ZIP archive file as a virtual file system. ZIP archives support +The \fBzipfs\fR command provides Tcl with the ability to mount the +contents of a ZIP archive file as a virtual file system. Tcl's ZIP +archive support is limited to basic features and options. +Supported storage methods include only STORE and DEFLATE with optional simple encryption, sufficient to prevent casual inspection of their contents but not able to prevent access by even a moderately determined attacker. +Strong encryption, multi-part archives, platform metadata, +zip64 formats and other compression methods like bzip2 are not supported. +.PP +Files within mounted archives can be written to but new files or directories +cannot be created. Further, modifications to files are limited to the +mounted archive in memory and are not persisted to disk. +.PP +Paths in mounted archives are case-sensitive on all platforms. .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 @@ -53,14 +62,14 @@ . 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. +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. .TP \fBzipfs info\fR \fIfile\fR . Return information about the given \fIfile\fR in the mounted zipfs. The information consists of: @@ -72,30 +81,56 @@ .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 +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 .TP \fBzipfs list\fR ?(\fB\-glob\fR|\fB\-regexp\fR)? ?\fIpattern\fR? . -Return a list of all files in the mounted zipfs, or just those matching -\fIpattern\fR (optionally controlled by the option parameters). The order of -the names in the list is arbitrary. +If \fIpattern\fR is not specified, the command returns a list of files across +all zipfs mounted archives. If \fIpattern\fR is specified, only those paths +matching the pattern are returned. By default, or with the \fB-glob\fR option, +the pattern is treated as a glob pattern and matching is done as described for +the \fBstring match\fR command. Alternatively, the \fB-regexp\fR option may be +used to specify matching \fBpattern\fR as a regular expression. The file names +are returned in arbitrary order. Note that path separators are treated as +ordinary characters in the matching. Thus forward slashes should be used +as path separators in the pattern. The returned paths only include those +actually in the archive and does not include intermediate directories in +mount paths. +.TP +\fBzipfs mount\fR +.TP +\fBzipfs mount\fR \fImountpoint\fR .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. +\fBzipfs mount\fR \fIzipfile\fR \fImountpoint\fR ?\fIpassword\fR? .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. +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 @@ -104,18 +139,20 @@ .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 . +for the current platform. +This value is +.QW \fB//zipfs:/\fR +on most platforms. .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. .TP \fBzipfs mkzip\fR \fIoutfile indir\fR ?\fIstrip\fR? ?\fIpassword\fR? @@ -144,10 +181,12 @@ (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 @@ -183,17 +222,17 @@ .PP .CS set zip myApp.zip set base [file join [\fBzipfs root\fR] myApp] -\fBzipfs mount\fR $base $zip +\fBzipfs mount\fR $zip $base # $base now has the contents of myApp.zip source [file join $base app.tcl] # use the contents, load libraries from it, etc... -\fBzipfs unmount\fR $zip +\fBzipfs unmount\fR $base .CE .PP Creating a ZIP archive, given that a directory exists containing the content to put in the archive. Note that the source directory is given twice, in order to strip the exterior directory name from each filename in the archive. @@ -216,11 +255,11 @@ # Create with password \fBzipfs mkzip\fR $targetZip $sourceDir $sourceDir $password # Mount with password -\fBzipfs mount\fR $base $zip $password +\fBzipfs mount\fR $zip $base $password .CE .PP 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. Index: generic/regc_color.c ================================================================== --- generic/regc_color.c +++ generic/regc_color.c @@ -1,10 +1,10 @@ /* * colorings of characters * This file is #included by regcomp.c. * - * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. + * Copyright © 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. @@ -757,13 +757,13 @@ { struct colordesc *cd; struct colordesc *end; color co; chr c; - char *has; + const char *has; - fprintf(f, "max %ld\n", (long) cm->max); + fprintf(f, "max %" TCL_Z_MODIFIER "u\n", cm->max); if (NBYTS > 1) { fillcheck(cm, cm->tree, 0, f); } end = CDEND(cm); for (cd=cm->cd+1, co=1 ; cdcv != NULL) && (nchrs <= v->cv->chrspace) && (nranges <= v->cv->rangespace)) { return clearcvec(v->cv); } Index: generic/regc_lex.c ================================================================== --- generic/regc_lex.c +++ generic/regc_lex.c @@ -1,10 +1,10 @@ /* * lexical analyzer * This file is #included by regcomp.c. * - * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. + * Copyright © 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. @@ -425,11 +425,11 @@ break; case CHR('\\'): /* BRE bound ends with \} */ if (INCON(L_BBND) && NEXT1('}')) { v->now++; INTOCON(L_BRE); - RET('}'); + RETV('}', 1); } else { FAILW(REG_BADBR); } break; default: @@ -773,11 +773,11 @@ } NOTE(REG_UNONPOSIX); switch (c) { case CHR('a'): - RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007'))); + RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\x07'))); break; case CHR('A'): RETV(SBEGIN, 0); break; case CHR('b'): @@ -801,11 +801,11 @@ NOTE(REG_ULOCALE); RETV(CCLASS, 'D'); break; case CHR('e'): NOTE(REG_UUNPORT); - RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\033'))); + RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\x1B'))); break; case CHR('f'): RETV(PLAIN, CHR('\f')); break; case CHR('m'): @@ -1003,11 +1003,11 @@ switch (c) { case CHR('*'): if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^')) { RETV(PLAIN, c); } - RET('*'); + RETV('*', 1); break; case CHR('['): if (HAVE(6) && *(v->now+0) == CHR('[') && *(v->now+1) == CHR(':') && (*(v->now+2) == CHR('<') || *(v->now+2) == CHR('>')) && Index: generic/regc_locale.c ================================================================== --- generic/regc_locale.c +++ generic/regc_locale.c @@ -2,11 +2,11 @@ * regc_locale.c -- * * This file contains the Unicode locale specific regexp routines. * This file is #included by regcomp.c. * - * Copyright (c) 1998 by Scriptics Corporation. + * Copyright © 1998 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -14,53 +14,53 @@ static const struct cname { const char *name; const char code; } cnames[] = { - {"NUL", '\0'}, - {"SOH", '\001'}, - {"STX", '\002'}, - {"ETX", '\003'}, - {"EOT", '\004'}, - {"ENQ", '\005'}, - {"ACK", '\006'}, - {"BEL", '\007'}, - {"alert", '\007'}, - {"BS", '\010'}, - {"backspace", '\b'}, - {"HT", '\011'}, - {"tab", '\t'}, - {"LF", '\012'}, - {"newline", '\n'}, - {"VT", '\013'}, - {"vertical-tab", '\v'}, - {"FF", '\014'}, - {"form-feed", '\f'}, - {"CR", '\015'}, - {"carriage-return", '\r'}, - {"SO", '\016'}, - {"SI", '\017'}, - {"DLE", '\020'}, - {"DC1", '\021'}, - {"DC2", '\022'}, - {"DC3", '\023'}, - {"DC4", '\024'}, - {"NAK", '\025'}, - {"SYN", '\026'}, - {"ETB", '\027'}, - {"CAN", '\030'}, - {"EM", '\031'}, - {"SUB", '\032'}, - {"ESC", '\033'}, - {"IS4", '\034'}, - {"FS", '\034'}, - {"IS3", '\035'}, - {"GS", '\035'}, - {"IS2", '\036'}, - {"RS", '\036'}, - {"IS1", '\037'}, - {"US", '\037'}, + {"NUL", '\x00'}, + {"SOH", '\x01'}, + {"STX", '\x02'}, + {"ETX", '\x03'}, + {"EOT", '\x04'}, + {"ENQ", '\x05'}, + {"ACK", '\x06'}, + {"BEL", '\x07'}, + {"alert", '\x07'}, + {"BS", '\x08'}, + {"backspace", '\x08'}, + {"HT", '\x09'}, + {"tab", '\x09'}, + {"LF", '\x0A'}, + {"newline", '\x0A'}, + {"VT", '\x0B'}, + {"vertical-tab", '\x0B'}, + {"FF", '\x0C'}, + {"form-feed", '\x0C'}, + {"CR", '\x0D'}, + {"carriage-return", '\x0D'}, + {"SO", '\x0E'}, + {"SI", '\x0F'}, + {"DLE", '\x10'}, + {"DC1", '\x11'}, + {"DC2", '\x12'}, + {"DC3", '\x13'}, + {"DC4", '\x14'}, + {"NAK", '\x15'}, + {"SYN", '\x16'}, + {"ETB", '\x17'}, + {"CAN", '\x18'}, + {"EM", '\x19'}, + {"SUB", '\x1A'}, + {"ESC", '\x1B'}, + {"IS4", '\x1C'}, + {"FS", '\x1C'}, + {"IS3", '\x1D'}, + {"GS", '\x1D'}, + {"IS2", '\x1E'}, + {"RS", '\x1E'}, + {"IS1", '\x1F'}, + {"US", '\x1F'}, {"space", ' '}, {"exclamation-mark",'!'}, {"quotation-mark", '"'}, {"number-sign", '#'}, {"dollar-sign", '$'}, @@ -108,11 +108,11 @@ {"left-curly-bracket", '{'}, {"vertical-line", '|'}, {"right-brace", '}'}, {"right-curly-bracket", '}'}, {"tilde", '~'}, - {"DEL", '\177'}, + {"DEL", '\x7F'}, {NULL, 0} }; /* * Unicode character-class tables. @@ -138,115 +138,121 @@ {0xF8, 0x2C1}, {0x2C6, 0x2D1}, {0x2E0, 0x2E4}, {0x370, 0x374}, {0x37A, 0x37D}, {0x388, 0x38A}, {0x38E, 0x3A1}, {0x3A3, 0x3F5}, {0x3F7, 0x481}, {0x48A, 0x52F}, {0x531, 0x556}, {0x560, 0x588}, {0x5D0, 0x5EA}, {0x5EF, 0x5F2}, {0x620, 0x64A}, {0x671, 0x6D3}, {0x6FA, 0x6FC}, {0x712, 0x72F}, {0x74D, 0x7A5}, {0x7CA, 0x7EA}, - {0x800, 0x815}, {0x840, 0x858}, {0x860, 0x86A}, {0x8A0, 0x8B4}, - {0x8B6, 0x8C7}, {0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980}, - {0x985, 0x98C}, {0x993, 0x9A8}, {0x9AA, 0x9B0}, {0x9B6, 0x9B9}, - {0x9DF, 0x9E1}, {0xA05, 0xA0A}, {0xA13, 0xA28}, {0xA2A, 0xA30}, - {0xA59, 0xA5C}, {0xA72, 0xA74}, {0xA85, 0xA8D}, {0xA8F, 0xA91}, - {0xA93, 0xAA8}, {0xAAA, 0xAB0}, {0xAB5, 0xAB9}, {0xB05, 0xB0C}, - {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB35, 0xB39}, {0xB5F, 0xB61}, - {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95}, {0xBA8, 0xBAA}, - {0xBAE, 0xBB9}, {0xC05, 0xC0C}, {0xC0E, 0xC10}, {0xC12, 0xC28}, - {0xC2A, 0xC39}, {0xC58, 0xC5A}, {0xC85, 0xC8C}, {0xC8E, 0xC90}, - {0xC92, 0xCA8}, {0xCAA, 0xCB3}, {0xCB5, 0xCB9}, {0xD04, 0xD0C}, - {0xD0E, 0xD10}, {0xD12, 0xD3A}, {0xD54, 0xD56}, {0xD5F, 0xD61}, - {0xD7A, 0xD7F}, {0xD85, 0xD96}, {0xD9A, 0xDB1}, {0xDB3, 0xDBB}, - {0xDC0, 0xDC6}, {0xE01, 0xE30}, {0xE40, 0xE46}, {0xE86, 0xE8A}, - {0xE8C, 0xEA3}, {0xEA7, 0xEB0}, {0xEC0, 0xEC4}, {0xEDC, 0xEDF}, - {0xF40, 0xF47}, {0xF49, 0xF6C}, {0xF88, 0xF8C}, {0x1000, 0x102A}, - {0x1050, 0x1055}, {0x105A, 0x105D}, {0x106E, 0x1070}, {0x1075, 0x1081}, - {0x10A0, 0x10C5}, {0x10D0, 0x10FA}, {0x10FC, 0x1248}, {0x124A, 0x124D}, - {0x1250, 0x1256}, {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D}, - {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, {0x12C2, 0x12C5}, - {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A}, - {0x1380, 0x138F}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1401, 0x166C}, - {0x166F, 0x167F}, {0x1681, 0x169A}, {0x16A0, 0x16EA}, {0x16F1, 0x16F8}, - {0x1700, 0x170C}, {0x170E, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751}, + {0x800, 0x815}, {0x840, 0x858}, {0x860, 0x86A}, {0x870, 0x887}, + {0x889, 0x88E}, {0x8A0, 0x8C9}, {0x904, 0x939}, {0x958, 0x961}, + {0x971, 0x980}, {0x985, 0x98C}, {0x993, 0x9A8}, {0x9AA, 0x9B0}, + {0x9B6, 0x9B9}, {0x9DF, 0x9E1}, {0xA05, 0xA0A}, {0xA13, 0xA28}, + {0xA2A, 0xA30}, {0xA59, 0xA5C}, {0xA72, 0xA74}, {0xA85, 0xA8D}, + {0xA8F, 0xA91}, {0xA93, 0xAA8}, {0xAAA, 0xAB0}, {0xAB5, 0xAB9}, + {0xB05, 0xB0C}, {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB35, 0xB39}, + {0xB5F, 0xB61}, {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95}, + {0xBA8, 0xBAA}, {0xBAE, 0xBB9}, {0xC05, 0xC0C}, {0xC0E, 0xC10}, + {0xC12, 0xC28}, {0xC2A, 0xC39}, {0xC58, 0xC5A}, {0xC85, 0xC8C}, + {0xC8E, 0xC90}, {0xC92, 0xCA8}, {0xCAA, 0xCB3}, {0xCB5, 0xCB9}, + {0xD04, 0xD0C}, {0xD0E, 0xD10}, {0xD12, 0xD3A}, {0xD54, 0xD56}, + {0xD5F, 0xD61}, {0xD7A, 0xD7F}, {0xD85, 0xD96}, {0xD9A, 0xDB1}, + {0xDB3, 0xDBB}, {0xDC0, 0xDC6}, {0xE01, 0xE30}, {0xE40, 0xE46}, + {0xE86, 0xE8A}, {0xE8C, 0xEA3}, {0xEA7, 0xEB0}, {0xEC0, 0xEC4}, + {0xEDC, 0xEDF}, {0xF40, 0xF47}, {0xF49, 0xF6C}, {0xF88, 0xF8C}, + {0x1000, 0x102A}, {0x1050, 0x1055}, {0x105A, 0x105D}, {0x106E, 0x1070}, + {0x1075, 0x1081}, {0x10A0, 0x10C5}, {0x10D0, 0x10FA}, {0x10FC, 0x1248}, + {0x124A, 0x124D}, {0x1250, 0x1256}, {0x125A, 0x125D}, {0x1260, 0x1288}, + {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, + {0x12C2, 0x12C5}, {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, + {0x1318, 0x135A}, {0x1380, 0x138F}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, + {0x1401, 0x166C}, {0x166F, 0x167F}, {0x1681, 0x169A}, {0x16A0, 0x16EA}, + {0x16F1, 0x16F8}, {0x1700, 0x1711}, {0x171F, 0x1731}, {0x1740, 0x1751}, {0x1760, 0x176C}, {0x176E, 0x1770}, {0x1780, 0x17B3}, {0x1820, 0x1878}, {0x1880, 0x1884}, {0x1887, 0x18A8}, {0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1950, 0x196D}, {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, - {0x1A00, 0x1A16}, {0x1A20, 0x1A54}, {0x1B05, 0x1B33}, {0x1B45, 0x1B4B}, + {0x1A00, 0x1A16}, {0x1A20, 0x1A54}, {0x1B05, 0x1B33}, {0x1B45, 0x1B4C}, {0x1B83, 0x1BA0}, {0x1BBA, 0x1BE5}, {0x1C00, 0x1C23}, {0x1C4D, 0x1C4F}, {0x1C5A, 0x1C7D}, {0x1C80, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CBF}, {0x1CE9, 0x1CEC}, {0x1CEE, 0x1CF3}, {0x1D00, 0x1DBF}, {0x1E00, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, {0x1FB6, 0x1FBC}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FCC}, {0x1FD0, 0x1FD3}, {0x1FD6, 0x1FDB}, {0x1FE0, 0x1FEC}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC}, {0x2090, 0x209C}, {0x210A, 0x2113}, {0x2119, 0x211D}, {0x212A, 0x212D}, {0x212F, 0x2139}, {0x213C, 0x213F}, - {0x2145, 0x2149}, {0x2C00, 0x2C2E}, {0x2C30, 0x2C5E}, {0x2C60, 0x2CE4}, - {0x2CEB, 0x2CEE}, {0x2D00, 0x2D25}, {0x2D30, 0x2D67}, {0x2D80, 0x2D96}, - {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, - {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, - {0x3031, 0x3035}, {0x3041, 0x3096}, {0x309D, 0x309F}, {0x30A1, 0x30FA}, - {0x30FC, 0x30FF}, {0x3105, 0x312F}, {0x3131, 0x318E}, {0x31A0, 0x31BF}, - {0x31F0, 0x31FF}, {0x3400, 0x4DBF}, {0x4E00, 0x9FFC}, {0xA000, 0xA48C}, - {0xA4D0, 0xA4FD}, {0xA500, 0xA60C}, {0xA610, 0xA61F}, {0xA640, 0xA66E}, - {0xA67F, 0xA69D}, {0xA6A0, 0xA6E5}, {0xA717, 0xA71F}, {0xA722, 0xA788}, - {0xA78B, 0xA7BF}, {0xA7C2, 0xA7CA}, {0xA7F5, 0xA801}, {0xA803, 0xA805}, - {0xA807, 0xA80A}, {0xA80C, 0xA822}, {0xA840, 0xA873}, {0xA882, 0xA8B3}, - {0xA8F2, 0xA8F7}, {0xA90A, 0xA925}, {0xA930, 0xA946}, {0xA960, 0xA97C}, - {0xA984, 0xA9B2}, {0xA9E0, 0xA9E4}, {0xA9E6, 0xA9EF}, {0xA9FA, 0xA9FE}, - {0xAA00, 0xAA28}, {0xAA40, 0xAA42}, {0xAA44, 0xAA4B}, {0xAA60, 0xAA76}, - {0xAA7E, 0xAAAF}, {0xAAB9, 0xAABD}, {0xAADB, 0xAADD}, {0xAAE0, 0xAAEA}, - {0xAAF2, 0xAAF4}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, {0xAB11, 0xAB16}, - {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, {0xAB30, 0xAB5A}, {0xAB5C, 0xAB69}, - {0xAB70, 0xABE2}, {0xAC00, 0xD7A3}, {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, - {0xF900, 0xFA6D}, {0xFA70, 0xFAD9}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, - {0xFB1F, 0xFB28}, {0xFB2A, 0xFB36}, {0xFB38, 0xFB3C}, {0xFB46, 0xFBB1}, - {0xFBD3, 0xFD3D}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, {0xFDF0, 0xFDFB}, - {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, {0xFF21, 0xFF3A}, {0xFF41, 0xFF5A}, - {0xFF66, 0xFFBE}, {0xFFC2, 0xFFC7}, {0xFFCA, 0xFFCF}, {0xFFD2, 0xFFD7}, - {0xFFDA, 0xFFDC} + {0x2145, 0x2149}, {0x2C00, 0x2CE4}, {0x2CEB, 0x2CEE}, {0x2D00, 0x2D25}, + {0x2D30, 0x2D67}, {0x2D80, 0x2D96}, {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, + {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, + {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x3031, 0x3035}, {0x3041, 0x3096}, + {0x309D, 0x309F}, {0x30A1, 0x30FA}, {0x30FC, 0x30FF}, {0x3105, 0x312F}, + {0x3131, 0x318E}, {0x31A0, 0x31BF}, {0x31F0, 0x31FF}, {0x3400, 0x4DBF}, + {0x4E00, 0xA48C}, {0xA4D0, 0xA4FD}, {0xA500, 0xA60C}, {0xA610, 0xA61F}, + {0xA640, 0xA66E}, {0xA67F, 0xA69D}, {0xA6A0, 0xA6E5}, {0xA717, 0xA71F}, + {0xA722, 0xA788}, {0xA78B, 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}, - {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}, + {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}, {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} + {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 (sizeof(alphaRangeTable)/sizeof(crange)) @@ -257,31 +263,33 @@ 0x93D, 0x950, 0x98F, 0x990, 0x9B2, 0x9BD, 0x9CE, 0x9DC, 0x9DD, 0x9F0, 0x9F1, 0x9FC, 0xA0F, 0xA10, 0xA32, 0xA33, 0xA35, 0xA36, 0xA38, 0xA39, 0xA5E, 0xAB2, 0xAB3, 0xABD, 0xAD0, 0xAE0, 0xAE1, 0xAF9, 0xB0F, 0xB10, 0xB32, 0xB33, 0xB3D, 0xB5C, 0xB5D, 0xB71, 0xB83, 0xB99, 0xB9A, 0xB9C, 0xB9E, 0xB9F, 0xBA3, 0xBA4, 0xBD0, - 0xC3D, 0xC60, 0xC61, 0xC80, 0xCBD, 0xCDE, 0xCE0, 0xCE1, 0xCF1, - 0xCF2, 0xD3D, 0xD4E, 0xDBD, 0xE32, 0xE33, 0xE81, 0xE82, 0xE84, - 0xEA5, 0xEB2, 0xEB3, 0xEBD, 0xEC6, 0xF00, 0x103F, 0x1061, 0x1065, - 0x1066, 0x108E, 0x10C7, 0x10CD, 0x1258, 0x12C0, 0x17D7, 0x17DC, 0x18AA, - 0x1AA7, 0x1BAE, 0x1BAF, 0x1CF5, 0x1CF6, 0x1CFA, 0x1F59, 0x1F5B, 0x1F5D, - 0x1FBE, 0x2071, 0x207F, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, - 0x214E, 0x2183, 0x2184, 0x2CF2, 0x2CF3, 0x2D27, 0x2D2D, 0x2D6F, 0x2E2F, - 0x3005, 0x3006, 0x303B, 0x303C, 0xA62A, 0xA62B, 0xA8FB, 0xA8FD, 0xA8FE, - 0xA9CF, 0xAA7A, 0xAAB1, 0xAAB5, 0xAAB6, 0xAAC0, 0xAAC2, 0xFB1D, 0xFB3E, - 0xFB40, 0xFB41, 0xFB43, 0xFB44 + 0xC3D, 0xC5D, 0xC60, 0xC61, 0xC80, 0xCBD, 0xCDD, 0xCDE, 0xCE0, + 0xCE1, 0xCF1, 0xCF2, 0xD3D, 0xD4E, 0xDBD, 0xE32, 0xE33, 0xE81, + 0xE82, 0xE84, 0xEA5, 0xEB2, 0xEB3, 0xEBD, 0xEC6, 0xF00, 0x103F, + 0x1061, 0x1065, 0x1066, 0x108E, 0x10C7, 0x10CD, 0x1258, 0x12C0, 0x17D7, + 0x17DC, 0x18AA, 0x1AA7, 0x1BAE, 0x1BAF, 0x1CF5, 0x1CF6, 0x1CFA, 0x1F59, + 0x1F5B, 0x1F5D, 0x1FBE, 0x2071, 0x207F, 0x2102, 0x2107, 0x2115, 0x2124, + 0x2126, 0x2128, 0x214E, 0x2183, 0x2184, 0x2CF2, 0x2CF3, 0x2D27, 0x2D2D, + 0x2D6F, 0x2E2F, 0x3005, 0x3006, 0x303B, 0x303C, 0xA62A, 0xA62B, 0xA7D0, + 0xA7D1, 0xA7D3, 0xA8FB, 0xA8FD, 0xA8FE, 0xA9CF, 0xAA7A, 0xAAB1, 0xAAB5, + 0xAAB6, 0xAAC0, 0xAAC2, 0xFB1D, 0xFB3E, 0xFB40, 0xFB41, 0xFB43, 0xFB44 #if CHRBITS > 16 - ,0x1003C, 0x1003D, 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, + ,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, 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 + 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 (sizeof(alphaCharTable)/sizeof(chr)) @@ -292,19 +300,19 @@ 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}, + ,{0x13430, 0x1343F}, {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 + 0xAD, 0x61C, 0x6DD, 0x70F, 0x890, 0x891, 0x8E2, 0x180E, 0xFEFF #if CHRBITS > 16 ,0x110BD, 0x110CD, 0xE0001 #endif }; @@ -328,12 +336,13 @@ #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} + {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 (sizeof(digitRangeTable)/sizeof(crange)) @@ -345,55 +354,57 @@ * 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} + {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}, {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} + {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 (sizeof(punctRangeTable)/sizeof(crange)) static const chr punctCharTable[] = { 0x3A, 0x3B, 0x3F, 0x40, 0x5F, 0x7B, 0x7D, 0xA1, 0xA7, 0xAB, 0xB6, 0xB7, 0xBB, 0xBF, 0x37E, 0x387, 0x589, 0x58A, 0x5BE, 0x5C0, 0x5C3, 0x5C6, 0x5F3, 0x5F4, 0x609, 0x60A, 0x60C, - 0x60D, 0x61B, 0x61E, 0x61F, 0x6D4, 0x85E, 0x964, 0x965, 0x970, - 0x9FD, 0xA76, 0xAF0, 0xC77, 0xC84, 0xDF4, 0xE4F, 0xE5A, 0xE5B, - 0xF14, 0xF85, 0xFD9, 0xFDA, 0x10FB, 0x1400, 0x166E, 0x169B, 0x169C, - 0x1735, 0x1736, 0x1944, 0x1945, 0x1A1E, 0x1A1F, 0x1C7E, 0x1C7F, 0x1CD3, + 0x60D, 0x61B, 0x6D4, 0x85E, 0x964, 0x965, 0x970, 0x9FD, 0xA76, + 0xAF0, 0xC77, 0xC84, 0xDF4, 0xE4F, 0xE5A, 0xE5B, 0xF14, 0xF85, + 0xFD9, 0xFDA, 0x10FB, 0x1400, 0x166E, 0x169B, 0x169C, 0x1735, 0x1736, + 0x1944, 0x1945, 0x1A1E, 0x1A1F, 0x1B7D, 0x1B7E, 0x1C7E, 0x1C7F, 0x1CD3, 0x207D, 0x207E, 0x208D, 0x208E, 0x2329, 0x232A, 0x27C5, 0x27C6, 0x29FC, - 0x29FD, 0x2CFE, 0x2CFF, 0x2D70, 0x2E52, 0x3030, 0x303D, 0x30A0, 0x30FB, - 0xA4FE, 0xA4FF, 0xA673, 0xA67E, 0xA8CE, 0xA8CF, 0xA8FC, 0xA92E, 0xA92F, - 0xA95F, 0xA9DE, 0xA9DF, 0xAADE, 0xAADF, 0xAAF0, 0xAAF1, 0xABEB, 0xFD3E, - 0xFD3F, 0xFE63, 0xFE68, 0xFE6A, 0xFE6B, 0xFF1A, 0xFF1B, 0xFF1F, 0xFF20, - 0xFF3F, 0xFF5B, 0xFF5D + 0x29FD, 0x2CFE, 0x2CFF, 0x2D70, 0x3030, 0x303D, 0x30A0, 0x30FB, 0xA4FE, + 0xA4FF, 0xA673, 0xA67E, 0xA8CE, 0xA8CF, 0xA8FC, 0xA92E, 0xA92F, 0xA95F, + 0xA9DE, 0xA9DF, 0xAADE, 0xAADF, 0xAAF0, 0xAAF1, 0xABEB, 0xFD3E, 0xFD3F, + 0xFE63, 0xFE68, 0xFE6A, 0xFE6B, 0xFF1A, 0xFF1B, 0xFF1F, 0xFF20, 0xFF3F, + 0xFF5B, 0xFF5D #if CHRBITS > 16 ,0x1039F, 0x103D0, 0x1056F, 0x10857, 0x1091F, 0x1093F, 0x10A7F, 0x10EAD, 0x110BB, 0x110BC, 0x11174, 0x11175, 0x111CD, 0x111DB, 0x112A9, 0x1145A, 0x1145B, 0x1145D, - 0x114C6, 0x1183B, 0x119E2, 0x11C70, 0x11C71, 0x11EF7, 0x11EF8, 0x11FFF, 0x16A6E, - 0x16A6F, 0x16AF5, 0x16B44, 0x16FE2, 0x1BC9F, 0x1E95E, 0x1E95F + 0x114C6, 0x116B9, 0x1183B, 0x119E2, 0x11C70, 0x11C71, 0x11EF7, 0x11EF8, 0x11FFF, + 0x12FF1, 0x12FF2, 0x16A6E, 0x16A6F, 0x16AF5, 0x16B44, 0x16FE2, 0x1BC9F, 0x1E95E, + 0x1E95F #endif }; #define NUM_PUNCT_CHAR (sizeof(punctCharTable)/sizeof(chr)) @@ -427,22 +438,24 @@ {0x1D6B, 0x1D77}, {0x1D79, 0x1D9A}, {0x1E95, 0x1E9D}, {0x1EFF, 0x1F07}, {0x1F10, 0x1F15}, {0x1F20, 0x1F27}, {0x1F30, 0x1F37}, {0x1F40, 0x1F45}, {0x1F50, 0x1F57}, {0x1F60, 0x1F67}, {0x1F70, 0x1F7D}, {0x1F80, 0x1F87}, {0x1F90, 0x1F97}, {0x1FA0, 0x1FA7}, {0x1FB0, 0x1FB4}, {0x1FC2, 0x1FC4}, {0x1FD0, 0x1FD3}, {0x1FE0, 0x1FE7}, {0x1FF2, 0x1FF4}, {0x2146, 0x2149}, - {0x2C30, 0x2C5E}, {0x2C76, 0x2C7B}, {0x2D00, 0x2D25}, {0xA72F, 0xA731}, + {0x2C30, 0x2C5F}, {0x2C76, 0x2C7B}, {0x2D00, 0x2D25}, {0xA72F, 0xA731}, {0xA771, 0xA778}, {0xA793, 0xA795}, {0xAB30, 0xAB5A}, {0xAB60, 0xAB68}, {0xAB70, 0xABBF}, {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFF41, 0xFF5A} #if CHRBITS > 16 - ,{0x10428, 0x1044F}, {0x104D8, 0x104FB}, {0x10CC0, 0x10CF2}, {0x118C0, 0x118DF}, - {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} + ,{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 (sizeof(lowerRangeTable)/sizeof(crange)) @@ -508,14 +521,14 @@ 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 + 0xA7AF, 0xA7B5, 0xA7B7, 0xA7B9, 0xA7BB, 0xA7BD, 0xA7BF, 0xA7C1, 0xA7C3, + 0xA7C8, 0xA7CA, 0xA7D1, 0xA7D3, 0xA7D5, 0xA7D7, 0xA7D9, 0xA7F6, 0xA7FA #if CHRBITS > 16 - ,0x1D4BB, 0x1D7CB + ,0x105BB, 0x105BC, 0x1D4BB, 0x1D7CB #endif }; #define NUM_LOWER_CHAR (sizeof(lowerCharTable)/sizeof(chr)) @@ -530,22 +543,22 @@ {0x3D2, 0x3D4}, {0x3FD, 0x42F}, {0x531, 0x556}, {0x10A0, 0x10C5}, {0x13A0, 0x13F5}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CBF}, {0x1F08, 0x1F0F}, {0x1F18, 0x1F1D}, {0x1F28, 0x1F2F}, {0x1F38, 0x1F3F}, {0x1F48, 0x1F4D}, {0x1F68, 0x1F6F}, {0x1FB8, 0x1FBB}, {0x1FC8, 0x1FCB}, {0x1FD8, 0x1FDB}, {0x1FE8, 0x1FEC}, {0x1FF8, 0x1FFB}, {0x210B, 0x210D}, {0x2110, 0x2112}, - {0x2119, 0x211D}, {0x212A, 0x212D}, {0x2130, 0x2133}, {0x2C00, 0x2C2E}, + {0x2119, 0x211D}, {0x212A, 0x212D}, {0x2130, 0x2133}, {0x2C00, 0x2C2F}, {0x2C62, 0x2C64}, {0x2C6D, 0x2C70}, {0x2C7E, 0x2C80}, {0xA7AA, 0xA7AE}, {0xA7B0, 0xA7B4}, {0xA7C4, 0xA7C7}, {0xFF21, 0xFF3A} #if CHRBITS > 16 - ,{0x10400, 0x10427}, {0x104B0, 0x104D3}, {0x10C80, 0x10CB2}, {0x118A0, 0x118BF}, - {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} + ,{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 (sizeof(upperRangeTable)/sizeof(crange)) @@ -611,14 +624,15 @@ 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 + 0xA7B8, 0xA7BA, 0xA7BC, 0xA7BE, 0xA7C0, 0xA7C2, 0xA7C9, 0xA7D0, 0xA7D6, + 0xA7D8, 0xA7F5 #if CHRBITS > 16 - ,0x1D49C, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D504, 0x1D505, 0x1D538, - 0x1D539, 0x1D546, 0x1D7CA + ,0x10594, 0x10595, 0x1D49C, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D504, + 0x1D505, 0x1D538, 0x1D539, 0x1D546, 0x1D7CA #endif }; #define NUM_UPPER_CHAR (sizeof(upperCharTable)/sizeof(chr)) @@ -628,150 +642,156 @@ static const crange graphRangeTable[] = { {0x21, 0x7E}, {0xA1, 0xAC}, {0xAE, 0x377}, {0x37A, 0x37F}, {0x384, 0x38A}, {0x38E, 0x3A1}, {0x3A3, 0x52F}, {0x531, 0x556}, {0x559, 0x58A}, {0x58D, 0x58F}, {0x591, 0x5C7}, {0x5D0, 0x5EA}, - {0x5EF, 0x5F4}, {0x606, 0x61B}, {0x61E, 0x6DC}, {0x6DE, 0x70D}, + {0x5EF, 0x5F4}, {0x606, 0x61B}, {0x61D, 0x6DC}, {0x6DE, 0x70D}, {0x710, 0x74A}, {0x74D, 0x7B1}, {0x7C0, 0x7FA}, {0x7FD, 0x82D}, - {0x830, 0x83E}, {0x840, 0x85B}, {0x860, 0x86A}, {0x8A0, 0x8B4}, - {0x8B6, 0x8C7}, {0x8D3, 0x8E1}, {0x8E3, 0x983}, {0x985, 0x98C}, - {0x993, 0x9A8}, {0x9AA, 0x9B0}, {0x9B6, 0x9B9}, {0x9BC, 0x9C4}, - {0x9CB, 0x9CE}, {0x9DF, 0x9E3}, {0x9E6, 0x9FE}, {0xA01, 0xA03}, - {0xA05, 0xA0A}, {0xA13, 0xA28}, {0xA2A, 0xA30}, {0xA3E, 0xA42}, - {0xA4B, 0xA4D}, {0xA59, 0xA5C}, {0xA66, 0xA76}, {0xA81, 0xA83}, - {0xA85, 0xA8D}, {0xA8F, 0xA91}, {0xA93, 0xAA8}, {0xAAA, 0xAB0}, - {0xAB5, 0xAB9}, {0xABC, 0xAC5}, {0xAC7, 0xAC9}, {0xACB, 0xACD}, - {0xAE0, 0xAE3}, {0xAE6, 0xAF1}, {0xAF9, 0xAFF}, {0xB01, 0xB03}, - {0xB05, 0xB0C}, {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB35, 0xB39}, - {0xB3C, 0xB44}, {0xB4B, 0xB4D}, {0xB55, 0xB57}, {0xB5F, 0xB63}, - {0xB66, 0xB77}, {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95}, - {0xBA8, 0xBAA}, {0xBAE, 0xBB9}, {0xBBE, 0xBC2}, {0xBC6, 0xBC8}, - {0xBCA, 0xBCD}, {0xBE6, 0xBFA}, {0xC00, 0xC0C}, {0xC0E, 0xC10}, - {0xC12, 0xC28}, {0xC2A, 0xC39}, {0xC3D, 0xC44}, {0xC46, 0xC48}, - {0xC4A, 0xC4D}, {0xC58, 0xC5A}, {0xC60, 0xC63}, {0xC66, 0xC6F}, - {0xC77, 0xC8C}, {0xC8E, 0xC90}, {0xC92, 0xCA8}, {0xCAA, 0xCB3}, - {0xCB5, 0xCB9}, {0xCBC, 0xCC4}, {0xCC6, 0xCC8}, {0xCCA, 0xCCD}, - {0xCE0, 0xCE3}, {0xCE6, 0xCEF}, {0xD00, 0xD0C}, {0xD0E, 0xD10}, + {0x830, 0x83E}, {0x840, 0x85B}, {0x860, 0x86A}, {0x870, 0x88E}, + {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, 0xECD}, {0xED0, 0xED9}, {0xEDC, 0xEDF}, {0xF00, 0xF47}, + {0xEC8, 0xECE}, {0xED0, 0xED9}, {0xEDC, 0xEDF}, {0xF00, 0xF47}, {0xF49, 0xF6C}, {0xF71, 0xF97}, {0xF99, 0xFBC}, {0xFBE, 0xFCC}, {0xFCE, 0xFDA}, {0x1000, 0x10C5}, {0x10D0, 0x1248}, {0x124A, 0x124D}, {0x1250, 0x1256}, {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, {0x12C2, 0x12C5}, {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A}, {0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, - {0x1400, 0x167F}, {0x1681, 0x169C}, {0x16A0, 0x16F8}, {0x1700, 0x170C}, - {0x170E, 0x1714}, {0x1720, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176C}, - {0x176E, 0x1770}, {0x1780, 0x17DD}, {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, - {0x1800, 0x180D}, {0x1810, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA}, - {0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1920, 0x192B}, {0x1930, 0x193B}, - {0x1944, 0x196D}, {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, - {0x19D0, 0x19DA}, {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, {0x1A60, 0x1A7C}, - {0x1A7F, 0x1A89}, {0x1A90, 0x1A99}, {0x1AA0, 0x1AAD}, {0x1AB0, 0x1AC0}, - {0x1B00, 0x1B4B}, {0x1B50, 0x1B7C}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, - {0x1C3B, 0x1C49}, {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7}, - {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}, + {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, 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} + {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}, {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}, + {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}, {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D172}, - {0x1D17B, 0x1D1E8}, {0x1D200, 0x1D245}, {0x1D2E0, 0x1D2F3}, {0x1D300, 0x1D356}, + {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}, {0x1E000, 0x1E006}, - {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E026, 0x1E02A}, {0x1E100, 0x1E12C}, - {0x1E130, 0x1E13D}, {0x1E140, 0x1E149}, {0x1E2C0, 0x1E2F9}, {0x1E800, 0x1E8C4}, + {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}, {0x1F6E0, 0x1F6EC}, - {0x1F6F0, 0x1F6FC}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D8}, {0x1F7E0, 0x1F7EB}, + {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, 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} + {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 (sizeof(graphRangeTable)/sizeof(crange)) @@ -779,26 +799,27 @@ 0x38C, 0x85E, 0x98F, 0x990, 0x9B2, 0x9C7, 0x9C8, 0x9D7, 0x9DC, 0x9DD, 0xA0F, 0xA10, 0xA32, 0xA33, 0xA35, 0xA36, 0xA38, 0xA39, 0xA3C, 0xA47, 0xA48, 0xA51, 0xA5E, 0xAB2, 0xAB3, 0xAD0, 0xB0F, 0xB10, 0xB32, 0xB33, 0xB47, 0xB48, 0xB5C, 0xB5D, 0xB82, 0xB83, 0xB99, 0xB9A, 0xB9C, 0xB9E, 0xB9F, 0xBA3, 0xBA4, 0xBD0, 0xBD7, - 0xC55, 0xC56, 0xCD5, 0xCD6, 0xCDE, 0xCF1, 0xCF2, 0xDBD, 0xDCA, + 0xC55, 0xC56, 0xC5D, 0xCD5, 0xCD6, 0xCDD, 0xCDE, 0xDBD, 0xDCA, 0xDD6, 0xE81, 0xE82, 0xE84, 0xEA5, 0xEC6, 0x10C7, 0x10CD, 0x1258, 0x12C0, 0x1772, 0x1773, 0x1940, 0x1F59, 0x1F5B, 0x1F5D, 0x2070, 0x2071, - 0x2D27, 0x2D2D, 0x2D6F, 0x2D70, 0xFB3E, 0xFB40, 0xFB41, 0xFB43, 0xFB44, - 0xFFFC, 0xFFFD + 0x2D27, 0x2D2D, 0x2D6F, 0x2D70, 0xA7D0, 0xA7D1, 0xA7D3, 0xFB3E, 0xFB40, + 0xFB41, 0xFB43, 0xFB44, 0xFDCF, 0xFFFC, 0xFFFD #if CHRBITS > 16 - ,0x1003C, 0x1003D, 0x101A0, 0x1056F, 0x10808, 0x10837, 0x10838, 0x1083C, 0x108F4, - 0x108F5, 0x1093F, 0x10A05, 0x10A06, 0x10EB0, 0x10EB1, 0x11288, 0x1130F, 0x11310, - 0x11332, 0x11333, 0x11347, 0x11348, 0x11350, 0x11357, 0x11909, 0x11915, 0x11916, - 0x11937, 0x11938, 0x11D08, 0x11D09, 0x11D3A, 0x11D3C, 0x11D3D, 0x11D67, 0x11D68, - 0x11D90, 0x11D91, 0x11FB0, 0x16A6E, 0x16A6F, 0x16FF0, 0x16FF1, 0x1D49E, 0x1D49F, - 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D4BB, 0x1D546, 0x1E023, 0x1E024, 0x1E14E, 0x1E14F, - 0x1E2FF, 0x1E95E, 0x1E95F, 0x1EE21, 0x1EE22, 0x1EE24, 0x1EE27, 0x1EE39, 0x1EE3B, - 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59, - 0x1EE5B, 0x1EE5D, 0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE7E, 0x1EEF0, 0x1EEF1, - 0x1F250, 0x1F251, 0x1F8B0, 0x1F8B1 + ,0x1003C, 0x1003D, 0x101A0, 0x10594, 0x10595, 0x105BB, 0x105BC, 0x10808, 0x10837, + 0x10838, 0x1083C, 0x108F4, 0x108F5, 0x1093F, 0x10A05, 0x10A06, 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 (sizeof(graphCharTable)/sizeof(chr)) @@ -980,17 +1001,15 @@ struct vars *v, /* context */ const chr *startp, /* where the name starts */ const chr *endp, /* just past the end of the name */ int cases) /* case-independent? */ { - size_t len; + size_t i, 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. */ @@ -998,13 +1017,14 @@ "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 */ @@ -1015,22 +1035,18 @@ /* * Map the name to the corresponding enumerated value. */ - index = -1; + index = CC_NULL; for (namePtr=classNames,i=0 ; *namePtr!=NULL ; namePtr++,i++) { if ((strlen(*namePtr) == len) && (strncmp(*namePtr, np, len) == 0)) { - index = i; + index = (enum classes)i; break; } } Tcl_DStringFree(&ds); - if (index == -1) { - ERR(REG_ECTYPE); - return NULL; - } /* * Remap lower and upper to alpha if the match is case insensitive. */ @@ -1040,11 +1056,14 @@ /* * Now compute the character class contents. */ - switch((enum classes) index) { + switch (index) { + case CC_NULL: + ERR(REG_ECTYPE); + return NULL; case CC_ALNUM: cv = getcvec(v, NUM_ALPHA_CHAR, NUM_DIGIT_RANGE + NUM_ALPHA_RANGE); if (cv) { for (i=0 ; ifree = s->next; destroystate(nfa, s); } nfa->slast = NULL; - nfa->nstates = -1; + nfa->nstates = FREESTATE; nfa->pre = NULL; nfa->post = NULL; FREE(nfa); } @@ -141,11 +141,11 @@ s->oas.next = NULL; s->free = NULL; s->noas = 0; } - assert(nfa->nstates >= 0); + assert(nfa->nstates != FREESTATE); s->no = nfa->nstates++; s->flag = 0; if (nfa->states == NULL) { nfa->states = s; } @@ -485,11 +485,11 @@ } /* * changearctarget - flip an arc to have a different to state * - * Caller must have verified that there is no pre-existing duplicate arc. + * Caller must have verified that there is no preexisting duplicate arc. * * Note that because we store arcs in their from state, we can't easily have * a similar changearcsource function. */ static void @@ -1513,11 +1513,11 @@ - pull - pull a back constraint backward past its source state * * Returns 1 if successful (which it always is unless the source is the * start state or we have an internal error), 0 if nothing happened. * - * A significant property of this function is that it deletes no pre-existing + * A significant property of this function is that it deletes no preexisting * states, and no outarcs of the constraint's from state other than the given * constraint arc. This makes the loops in pullback() safe, at the cost that * we may leave useless states behind. Therefore, we leave it to pullback() * to delete such states. * @@ -1692,11 +1692,11 @@ - push - push a forward constraint forward past its destination state * * Returns 1 if successful (which it always is unless the destination is the * post state or we have an internal error), 0 if nothing happened. * - * A significant property of this function is that it deletes no pre-existing + * A significant property of this function is that it deletes no preexisting * states, and no inarcs of the constraint's to state other than the given * constraint arc. This makes the loops in pushfwd() safe, at the cost that * we may leave useless states behind. Therefore, we leave it to pushfwd() * to delete such states. * @@ -2465,11 +2465,11 @@ * clone state. This prevents infinite recursion as well as useless repeat * visits to the same state subtree (which can add up fast, since typical NFAs * have multiple redundant arc pathways). Each donemap is a char array * indexed by state number. The donemaps are all of the same size "nstates", * which is nfa->nstates as of the start of the recursion. This is enough to - * have entries for all pre-existing states, but *not* entries for clone + * have entries for all preexisting states, but *not* entries for clone * states created during the recursion. That's okay since we have no need to * mark those. * * curdonemap is NULL when recursing to a new sclone state, or sclone's * donemap when we are recursing without having created a new state (which we @@ -2492,11 +2492,11 @@ struct state * sclone, struct state * spredecessor, struct arc * refarc, char *curdonemap, char *outerdonemap, - int nstates) + size_t nstates) { char *donemap; struct arc *a; /* Since this is recursive, it could be driven to stack overflow */ @@ -2689,11 +2689,11 @@ cleanup( struct nfa *nfa) { struct state *s; struct state *nexts; - int n; + size_t n; /* * Clear out unreachable or dead-end states. Use pre to mark reachable, * then post to mark can-reach-post. */ @@ -2772,11 +2772,11 @@ /* - analyze - ascertain potentially-useful facts about an optimized NFA ^ static long analyze(struct nfa *); */ -static long /* re_info bits to be ORed in */ +static long /* re_info bits to be OR'ed in */ analyze( struct nfa *nfa) { struct arc *a; struct arc *aa; @@ -2845,11 +2845,11 @@ cnfa->ncolors = maxcolor(nfa->cm) + 1; cnfa->flags = 0; ca = cnfa->arcs; for (s = nfa->states; s != NULL; s = s->next) { - assert((size_t) s->no < nstates); + assert(s->no < nstates); cnfa->stflags[s->no] = 0; cnfa->states[s->no] = ca; first = ca; for (a = s->outs; a != NULL; a = a->outchain) { switch (a->type) { @@ -2949,14 +2949,14 @@ struct nfa *nfa, FILE *f) { #ifdef REG_DEBUG struct state *s; - int nstates = 0; - int narcs = 0; + size_t nstates = 0; + size_t narcs = 0; - fprintf(f, "pre %d, post %d", nfa->pre->no, nfa->post->no); + fprintf(f, "pre %" TCL_Z_MODIFIER "u, post %" TCL_Z_MODIFIER "u", nfa->pre->no, nfa->post->no); if (nfa->bos[0] != COLORLESS) { fprintf(f, ", bos [%ld]", (long) nfa->bos[0]); } if (nfa->bos[1] != COLORLESS) { fprintf(f, ", bol [%ld]", (long) nfa->bos[1]); @@ -2971,11 +2971,11 @@ for (s = nfa->states; s != NULL; s = s->next) { dumpstate(s, f); nstates++; narcs += s->nouts; } - fprintf(f, "total of %d states, %d arcs\n", nstates, narcs); + fprintf(f, "total of %" TCL_Z_MODIFIER "u states, %" TCL_Z_MODIFIER "u arcs\n", nstates, narcs); if (nfa->parent == NULL) { dumpcolors(nfa->cm, f); } fflush(f); #else @@ -2998,11 +2998,11 @@ struct state *s, FILE *f) { struct arc *a; - fprintf(f, "%d%s%c", s->no, (s->tmp != NULL) ? "T" : "", + fprintf(f, "%" TCL_Z_MODIFIER "u%s%c", s->no, (s->tmp != NULL) ? "T" : "", (s->flag) ? s->flag : '.'); if (s->prev != NULL && s->prev->next != s) { fprintf(f, "\tstate chain bad\n"); } if (s->nouts == 0) { @@ -3011,11 +3011,11 @@ dumparcs(s, f); } fflush(f); for (a = s->ins; a != NULL; a = a->inchain) { if (a->to != s) { - fprintf(f, "\tlink from %d to %d on %d's in-chain\n", + fprintf(f, "\tlink from %" TCL_Z_MODIFIER "u to %" TCL_Z_MODIFIER "u on %" TCL_Z_MODIFIER "u's in-chain\n", a->from->no, a->to->no, s->no); } } } @@ -3089,11 +3089,11 @@ default: fprintf(f, "0x%x/0%lo", a->type, (long) a->co); break; } if (a->from != s) { - fprintf(f, "?%d?", a->from->no); + fprintf(f, "?%" TCL_Z_MODIFIER "u?", a->from->no); } for (ab = &a->from->oas; ab != NULL; ab = ab->next) { for (aa = &ab->a[0]; aa < &ab->a[ABSIZE]; aa++) { if (aa == a) { break; /* NOTE BREAK OUT */ @@ -3109,11 +3109,11 @@ fprintf(f, "->"); if (a->to == NULL) { fprintf(f, "NULL"); return; } - fprintf(f, "%d", a->to->no); + fprintf(f, "%" TCL_Z_MODIFIER "u", a->to->no); for (aa = a->to->ins; aa != NULL; aa = aa->inchain) { if (aa == a) { break; /* NOTE BREAK OUT */ } } @@ -3135,13 +3135,13 @@ dumpcnfa( struct cnfa *cnfa, FILE *f) { #ifdef REG_DEBUG - int st; + size_t st; - fprintf(f, "pre %d, post %d", cnfa->pre, cnfa->post); + fprintf(f, "pre %" TCL_Z_MODIFIER "u, post %" TCL_Z_MODIFIER "u", cnfa->pre, cnfa->post); if (cnfa->bos[0] != COLORLESS) { fprintf(f, ", bos [%ld]", (long) cnfa->bos[0]); } if (cnfa->bos[1] != COLORLESS) { fprintf(f, ", bol [%ld]", (long) cnfa->bos[1]); @@ -3180,19 +3180,19 @@ int st, struct cnfa *cnfa, FILE *f) { struct carc *ca; - int pos; + size_t pos; fprintf(f, "%d%s", st, (cnfa->stflags[st] & CNFA_NOPROGRESS) ? ":" : "."); pos = 1; for (ca = cnfa->states[st]; ca->co != COLORLESS; ca++) { if (ca->co < cnfa->ncolors) { - fprintf(f, "\t[%ld]->%d", (long) ca->co, ca->to); + fprintf(f, "\t[%d]->%" TCL_Z_MODIFIER "u", ca->co, ca->to); } else { - fprintf(f, "\t:%ld:->%d", (long) (ca->co - cnfa->ncolors), ca->to); + fprintf(f, "\t:%d:->%" TCL_Z_MODIFIER "u", ca->co - cnfa->ncolors, ca->to); } if (pos == 5) { fprintf(f, "\n"); pos = 1; } else { Index: generic/regcomp.c ================================================================== --- generic/regcomp.c +++ generic/regcomp.c @@ -1,10 +1,10 @@ /* * re_*comp and friends - compile REs * This file #includes several others (see the bottom). * - * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. + * Copyright © 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. @@ -154,11 +154,11 @@ static int hasconstraintout(struct state *); static void fixconstraintloops(struct nfa *, FILE *); static int findconstraintloop(struct nfa *, struct state *); static void breakconstraintloop(struct nfa *, struct state *); static void clonesuccessorstates(struct nfa *, struct state *, struct state *, - struct state *, struct arc *, char *, char *, int); + struct state *, struct arc *, char *, char *, size_t); static void cleanup(struct nfa *); static void markreachable(struct nfa *, struct state *, struct state *, struct state *); static void markcanreach(struct nfa *, struct state *, struct state *, struct state *); static long analyze(struct nfa *); static void compact(struct nfa *, struct cnfa *); @@ -177,12 +177,12 @@ #endif /* === regc_cvec.c === */ static struct cvec *clearcvec(struct cvec *); static void addchr(struct cvec *, pchr); static void addrange(struct cvec *, pchr, pchr); -static struct cvec *newcvec(int, int); -static struct cvec *getcvec(struct vars *, int, int); +static struct cvec *newcvec(size_t, size_t); +static struct cvec *getcvec(struct vars *, size_t, size_t); static void freecvec(struct cvec *); /* === regc_locale.c === */ static celt element(struct vars *, const chr *, const chr *); static struct cvec *range(struct vars *, celt, celt, int); static int before(celt, celt); @@ -408,11 +408,11 @@ re->re_info |= nfatree(v, v->tree, debug); CNOERR(); assert(v->nlacons == 0 || v->lacons != NULL); for (i = 1; i < v->nlacons; i++) { if (debug != NULL) { - fprintf(debug, "\n\n\n========= LA%" TCL_Z_MODIFIER "d ==========\n", i); + fprintf(debug, "\n\n\n========= LA%" TCL_Z_MODIFIER "u ==========\n", i); } nfanode(v, &v->lacons[i], debug); } CNOERR(); if (v->tree->flags&SHORTER) { @@ -2045,11 +2045,11 @@ regex_t *re, FILE *f) { #ifdef REG_DEBUG struct guts *g; - int i; + size_t i; if (re->re_magic != REMAGIC) { fprintf(f, "bad magic number (0x%x not 0x%x)\n", re->re_magic, REMAGIC); } @@ -2062,20 +2062,20 @@ fprintf(f, "bad guts magic number (0x%x not 0x%x)\n", g->magic, GUTSMAGIC); } fprintf(f, "\n\n\n========= DUMP ==========\n"); - fprintf(f, "nsub %" TCL_Z_MODIFIER "d, info 0%lo, ntree %d\n", + fprintf(f, "nsub %" TCL_Z_MODIFIER "u, info 0%lo, ntree %" TCL_Z_MODIFIER "u\n", re->re_nsub, re->re_info, g->ntree); dumpcolors(&g->cmap, f); if (!NULLCNFA(g->search)) { fprintf(f, "\nsearch:\n"); dumpcnfa(&g->search, f); } for (i = 1; i < g->nlacons; i++) { - fprintf(f, "\nla%d (%s):\n", i, + fprintf(f, "\nla%" TCL_Z_MODIFIER "u (%s):\n", i, (g->lacons[i].subno) ? "positive" : "negative"); dumpcnfa(&g->lacons[i].cnfa, f); } fprintf(f, "\n"); dumpst(g->tree, f, 0); @@ -2143,11 +2143,11 @@ fprintf(f, "%d", t->max); } fprintf(f, "}"); } if (nfapresent) { - fprintf(f, " %ld-%ld", (long)t->begin->no, (long)t->end->no); + fprintf(f, " %" TCL_Z_MODIFIER "u-%" TCL_Z_MODIFIER "u", t->begin->no, t->end->no); } if (t->left != NULL) { fprintf(f, " L:%s", stid(t->left, idbuf, sizeof(idbuf))); } if (t->right != NULL) { @@ -2182,13 +2182,13 @@ if (bufsize < sizeof(void*)*2 + 3 || bufsize < sizeof(t->id)*3 + 1) { return "unable"; } if (t->id != 0) { - sprintf(buf, "%d", t->id); + snprintf(buf, bufsize, "%d", t->id); } else { - sprintf(buf, "%p", t); + snprintf(buf, bufsize, "%p", t); } return buf; } #include "regc_lex.c" Index: generic/regcustom.h ================================================================== --- generic/regcustom.h +++ generic/regcustom.h @@ -82,19 +82,13 @@ 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. */ Index: generic/rege_dfa.c ================================================================== --- generic/rege_dfa.c +++ generic/rege_dfa.c @@ -1,10 +1,10 @@ /* * DFA routines * This file is #included by regexec.c. * - * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. + * Copyright © 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. @@ -45,11 +45,11 @@ chr *cp; chr *realstop = (stop == v->stop) ? stop : stop + 1; color co; struct sset *css, *ss; chr *post; - int i; + size_t i; struct colormap *cm = d->cm; /* * Initialize. */ @@ -290,11 +290,11 @@ struct vars *const v, struct dfa *const d) { struct sset *ss; chr *nopr = d->lastnopr; - int i; + size_t i; if (nopr == NULL) { nopr = v->start; } for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) { @@ -317,11 +317,11 @@ struct colormap *const cm, struct smalldfa *sml) /* preallocated space, may be NULL */ { struct dfa *d; size_t nss = cnfa->nstates * 2; - int wordsper = (cnfa->nstates + UBITS - 1) / UBITS; + size_t wordsper = (cnfa->nstates + UBITS - 1) / UBITS; struct smalldfa *smallwas = sml; assert(cnfa != NULL && cnfa->nstates != 0); if (nss <= FEWSTATES && cnfa->ncolors <= FEWCOLORS) { @@ -417,11 +417,11 @@ ^ static unsigned hash(unsigned *, int); */ static unsigned hash( unsigned *const uv, - const int n) + int n) { int i; unsigned h; h = 0; @@ -440,11 +440,11 @@ struct vars *const v, /* used only for debug flags */ struct dfa *const d, chr *const start) { struct sset *ss; - int i; + size_t i; /* * Is previous one still there? */ @@ -490,11 +490,12 @@ { struct cnfa *cnfa = d->cnfa; unsigned h; struct carc *ca; struct sset *p; - int i, isPost, noProgress, gotState, doLAConstraints, sawLAConstraints; + size_t i; + int isPost, noProgress, gotState, doLAConstraints, sawLAConstraints; /* * For convenience, we can be called even if it might not be a miss. */ @@ -524,11 +525,11 @@ isPost = 1; } if (!(cnfa->stflags[ca->to] & CNFA_NOPROGRESS)) { noProgress = 0; } - FDEBUG(("%d -> %d\n", i, ca->to)); + FDEBUG(("%" TCL_Z_MODIFIER "u -> %" TCL_Z_MODIFIER "u\n", i, ca->to)); } } } } doLAConstraints = (gotState ? (cnfa->flags&HASLACONS) : 0); @@ -554,11 +555,11 @@ isPost = 1; } if (!(cnfa->stflags[ca->to] & CNFA_NOPROGRESS)) { noProgress = 0; } - FDEBUG(("%d :> %d\n", i, ca->to)); + FDEBUG(("%" TCL_Z_MODIFIER "u :> %" TCL_Z_MODIFIER"u\n", i, ca->to)); } } } } if (!gotState) { @@ -613,28 +614,28 @@ struct vars *const v, struct cnfa *const pcnfa, /* parent cnfa */ chr *const cp, const pcolor co) /* "color" of the lookahead constraint */ { - int n; + size_t n; struct subre *sub; struct dfa *d; struct smalldfa sd; chr *end; n = co - pcnfa->ncolors; assert(n < v->g->nlacons && v->g->lacons != NULL); - FDEBUG(("=== testing lacon %d\n", n)); + FDEBUG(("=== testing lacon %" TCL_Z_MODIFIER "u\n", n)); sub = &v->g->lacons[n]; d = newDFA(v, &sub->cnfa, &v->g->cmap, &sd); if (d == NULL) { ERR(REG_ESPACE); return 0; } end = longest(v, d, cp, v->stop, NULL); freeDFA(d); - FDEBUG(("=== lacon %d match %d\n", n, (end != NULL))); + FDEBUG(("=== lacon %" TCL_Z_MODIFIER "u match %d\n", n, (end != NULL))); return (sub->subno) ? (end != NULL) : (end == NULL); } /* - getVacantSS - get a vacant state set @@ -736,25 +737,25 @@ /* * Shortcut for cases where cache isn't full. */ if (d->nssused < d->nssets) { - i = d->nssused; + size_t j = d->nssused; d->nssused++; - ss = &d->ssets[i]; - FDEBUG(("new c%d\n", i)); + ss = &d->ssets[j]; + FDEBUG(("new c%" TCL_Z_MODIFIER "u\n", j)); /* * Set up innards. */ - ss->states = &d->statesarea[i * d->wordsper]; + ss->states = &d->statesarea[j * d->wordsper]; ss->flags = 0; ss->ins.ss = NULL; ss->ins.co = WHITE; /* give it some value */ - ss->outs = &d->outsarea[i * d->ncolors]; - ss->inchain = &d->incarea[i * d->ncolors]; + ss->outs = &d->outsarea[j * d->ncolors]; + ss->inchain = &d->incarea[j * d->ncolors]; for (i = 0; i < d->ncolors; i++) { ss->outs[i] = NULL; ss->inchain[i].ss = NULL; } return ss; @@ -762,28 +763,28 @@ /* * Look for oldest, or old enough anyway. */ - if (cp - start > d->nssets*2/3) { /* oldest 33% are expendable */ + if ((size_t)(cp - start) > d->nssets*2/3) { /* oldest 33% are expendable */ ancient = cp - d->nssets*2/3; } else { ancient = start; } for (ss = d->search, end = &d->ssets[d->nssets]; ss < end; ss++) { if ((ss->lastseen == NULL || ss->lastseen < ancient) && !(ss->flags&LOCKED)) { d->search = ss + 1; - FDEBUG(("replacing c%d\n", (int) (ss - d->ssets))); + FDEBUG(("replacing c%" TCL_Z_MODIFIER "u\n", (size_t)(ss - d->ssets))); return ss; } } for (ss = d->ssets, end = d->search; ss < end; ss++) { if ((ss->lastseen == NULL || ss->lastseen < ancient) && !(ss->flags&LOCKED)) { d->search = ss + 1; - FDEBUG(("replacing c%d\n", (int) (ss - d->ssets))); + FDEBUG(("replacing c%" TCL_Z_MODIFIER "u\n", (size_t)(ss - d->ssets))); return ss; } } /* Index: generic/regerror.c ================================================================== --- generic/regerror.c +++ generic/regerror.c @@ -1,9 +1,9 @@ /* * regerror - error-code expansion * - * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. + * Copyright © 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. @@ -71,11 +71,11 @@ for (r = rerrs; r->code >= 0; r++) { if (strcmp(r->name, errbuf) == 0) { break; } } - sprintf(convbuf, "%d", r->code); /* -1 for unknown */ + snprintf(convbuf, sizeof(convbuf), "%d", r->code); /* -1 for unknown */ msg = convbuf; break; case REG_ITOA: /* Convert number to name */ icode = atoi(errbuf); /* Not our problem if this fails */ for (r = rerrs; r->code >= 0; r++) { @@ -84,11 +84,11 @@ } } if (r->code >= 0) { msg = r->name; } else { /* Unknown; tell him the number */ - sprintf(convbuf, "REG_%u", icode); + snprintf(convbuf, sizeof(convbuf), "REG_%u", icode); msg = convbuf; } break; default: /* A real, normal error code */ for (r = rerrs; r->code >= 0; r++) { @@ -97,11 +97,11 @@ } } if (r->code >= 0) { msg = r->explain; } else { /* Unknown; say so */ - sprintf(convbuf, unk, code); + snprintf(convbuf, sizeof(convbuf), unk, code); msg = convbuf; } break; } Index: generic/regexec.c ================================================================== --- generic/regexec.c +++ generic/regexec.c @@ -1,9 +1,9 @@ /* * re_*exec and friends - match REs * - * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. + * Copyright © 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. @@ -55,15 +55,16 @@ struct sset **outs; /* outarc vector indexed by color */ struct arcp *inchain; /* chain-pointer vector for outarcs */ }; struct dfa { - int nssets; /* size of cache */ - int nssused; /* how many entries occupied yet */ - int nstates; /* number of states */ + size_t nssets; /* size of cache */ + size_t nssused; /* how many entries occupied yet */ + size_t nstates; /* number of states */ + size_t wordsper; /* length of state-set bitvectors */ int ncolors; /* length of outarc and inchain vectors */ - int wordsper; /* length of state-set bitvectors */ + int cptsmalloced; /* were the areas individually malloced? */ struct sset *ssets; /* state-set cache */ unsigned *statesarea; /* bitvector storage */ unsigned *work; /* pointer to work area within statesarea */ struct sset **outsarea; /* outarc-vector storage */ struct arcp *incarea; /* inchain storage */ @@ -70,11 +71,10 @@ 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 */ @@ -114,11 +114,11 @@ #define ISERR() VISERR(v) #define VERR(vv,e) ((vv)->err = ((vv)->err ? (vv)->err : (e))) #define ERR(e) VERR(v, e) /* record an error */ #define NOERR() {if (ISERR()) return v->err;} /* if error seen, return it */ #define OFF(p) ((p) - v->start) -#define LOFF(p) ((long)OFF(p)) +#define LOFF(p) ((size_t)OFF(p)) /* * forward declarations */ /* =====^!^===== begin forwards =====^!^===== */ @@ -143,11 +143,11 @@ static chr *longest(struct vars *const, struct dfa *const, chr *const, chr *const, int *const); static chr *shortest(struct vars *const, struct dfa *const, chr *const, chr *const, chr *const, chr **const, int *const); static chr *lastCold(struct vars *const, struct dfa *const); static struct dfa *newDFA(struct vars *const, struct cnfa *const, struct colormap *const, struct smalldfa *); static void freeDFA(struct dfa *const); -static unsigned hash(unsigned *const, const int); +static unsigned hash(unsigned *const, int); static struct sset *initialize(struct vars *const, struct dfa *const, chr *const); static struct sset *miss(struct vars *const, struct dfa *const, struct sset *const, const pcolor, chr *const, chr *const); static int checkLAConstraint(struct vars *const, struct cnfa *const, chr *const, const pcolor); static struct sset *getVacantSS(struct vars *const, struct dfa *const, chr *const, chr *const); static struct sset *pickNextSS(struct vars *const, struct dfa *const, chr *const, chr *const); @@ -230,17 +230,19 @@ v->start = (chr *)string; v->stop = (chr *)string + len; v->err = 0; assert(v->g->ntree >= 0); n = v->g->ntree; - if (n <= LOCALDFAS) + if (n <= LOCALDFAS) { v->subdfas = subdfas; - else + } else { v->subdfas = (struct dfa **) MALLOC(n * sizeof(struct dfa *)); + } if (v->subdfas == NULL) { - if (v->pmatch != pmatch && v->pmatch != mat) + if (v->pmatch != pmatch && v->pmatch != mat) { FREE(v->pmatch); + } FreeVars(v); return REG_ESPACE; } for (i = 0; i < n; i++) v->subdfas[i] = NULL; @@ -273,15 +275,17 @@ if (v->pmatch != pmatch && v->pmatch != mat) { FREE(v->pmatch); } n = v->g->ntree; for (i = 0; i < n; i++) { - if (v->subdfas[i] != NULL) + if (v->subdfas[i] != NULL) { freeDFA(v->subdfas[i]); + } } - if (v->subdfas != subdfas) + if (v->subdfas != subdfas) { FREE(v->subdfas); + } FreeVars(v); return st; } /* @@ -293,12 +297,13 @@ getsubdfa(struct vars * v, struct subre * t) { if (v->subdfas[t->id] == NULL) { v->subdfas[t->id] = newDFA(v, &t->cnfa, &v->g->cmap, NULL); - if (ISERR()) + if (ISERR()) { return NULL; + } } return v->subdfas[t->id]; } /* @@ -324,11 +329,11 @@ */ s = newDFA(v, &v->g->search, cm, &v->dfa1); assert(!(ISERR() && s != NULL)); NOERR(); - MDEBUG(("\nsearch at %ld\n", LOFF(v->start))); + MDEBUG(("\nsearch at %" TCL_Z_MODIFIER "u\n", LOFF(v->start))); cold = NULL; close = shortest(v, s, v->start, v->start, v->stop, &cold, NULL); freeDFA(s); NOERR(); if (v->g->cflags®_EXPECT) { @@ -352,16 +357,16 @@ */ assert(cold != NULL); open = cold; cold = NULL; - MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close))); + MDEBUG(("between %" TCL_Z_MODIFIER "u and %" TCL_Z_MODIFIER "u\n", LOFF(open), LOFF(close))); d = newDFA(v, cnfa, cm, &v->dfa1); assert(!(ISERR() && d != NULL)); NOERR(); for (begin = open; begin <= close; begin++) { - MDEBUG(("\nfind trying at %ld\n", LOFF(begin))); + MDEBUG(("\nfind trying at %" TCL_Z_MODIFIER "u\n", LOFF(begin))); if (shorter) { end = shortest(v, d, begin, begin, v->stop, NULL, &hitend); } else { end = longest(v, d, begin, v->stop, &hitend); } @@ -468,21 +473,21 @@ assert(d != NULL && s != NULL); cold = NULL; close = v->start; do { - MDEBUG(("\ncsearch at %ld\n", LOFF(close))); + MDEBUG(("\ncsearch at %" TCL_Z_MODIFIER "u\n", LOFF(close))); close = shortest(v, s, close, close, v->stop, &cold, NULL); if (close == NULL) { break; /* NOTE BREAK */ } assert(cold != NULL); open = cold; cold = NULL; - MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close))); + MDEBUG(("cbetween %" TCL_Z_MODIFIER "u and %" TCL_Z_MODIFIER "u\n", LOFF(open), LOFF(close))); for (begin = open; begin <= close; begin++) { - MDEBUG(("\ncomplicatedFind trying at %ld\n", LOFF(begin))); + MDEBUG(("\ncomplicatedFind trying at %" TCL_Z_MODIFIER "u\n", LOFF(begin))); estart = begin; estop = v->stop; for (;;) { if (shorter) { end = shortest(v, d, begin, estart, estop, NULL, &hitend); @@ -494,11 +499,11 @@ } if (end == NULL) { break; /* NOTE BREAK OUT */ } - MDEBUG(("tentative end %ld\n", LOFF(end))); + MDEBUG(("tentative end %" TCL_Z_MODIFIER "u\n", LOFF(end))); zapallsubs(v->pmatch, v->nmatch); er = cdissect(v, v->g->tree, begin, end); if (er == REG_OKAY) { if (v->nmatch > 0) { v->pmatch[0].rm_so = OFF(begin); @@ -543,12 +548,12 @@ const size_t n) { size_t i; for (i = n-1; i > 0; i--) { - p[i].rm_so = -1; - p[i].rm_eo = -1; + p[i].rm_so = FREESTATE; + p[i].rm_eo = FREESTATE; } } /* - zaptreesubs - initialize subexpressions within subtree to "no match" @@ -558,15 +563,15 @@ zaptreesubs( struct vars *const v, struct subre *const t) { if (t->op == '(') { - int n = t->subno; + size_t n = t->subno; assert(n > 0); - if ((size_t) n < v->nmatch) { - v->pmatch[n].rm_so = -1; - v->pmatch[n].rm_eo = -1; + if (n < v->nmatch) { + v->pmatch[n].rm_so = FREESTATE; + v->pmatch[n].rm_eo = FREESTATE; } } if (t->left != NULL) { zaptreesubs(v, t->left); @@ -621,11 +626,11 @@ chr *end) /* end of same */ { int er; assert(t != NULL); - MDEBUG(("cdissect %ld-%ld %c\n", LOFF(begin), LOFF(end), t->op)); + MDEBUG(("cdissect %" TCL_Z_MODIFIER "u-%" TCL_Z_MODIFIER "u %c\n", LOFF(begin), LOFF(end), t->op)); switch (t->op) { case '=': /* terminal node */ assert(t->left == NULL && t->right == NULL); er = REG_OKAY; /* no action, parent did the work */ @@ -634,25 +639,27 @@ assert(t->left == NULL && t->right == NULL); er = cbrdissect(v, t, begin, end); break; case '.': /* concatenation */ assert(t->left != NULL && t->right != NULL); - if (t->left->flags & SHORTER) /* reverse scan */ + if (t->left->flags & SHORTER) {/* reverse scan */ er = crevcondissect(v, t, begin, end); - else + } else { er = ccondissect(v, t, begin, end); + } break; case '|': /* alternation */ assert(t->left != NULL); er = caltdissect(v, t, begin, end); break; case '*': /* iteration */ assert(t->left != NULL); - if (t->left->flags & SHORTER) /* reverse scan */ + if (t->left->flags & SHORTER) {/* reverse scan */ er = creviterdissect(v, t, begin, end); - else + } else { er = citerdissect(v, t, begin, end); + } break; case '(': /* capturing */ assert(t->left != NULL && t->right == NULL); assert(t->subno > 0); er = cdissect(v, t->left, begin, end); @@ -706,11 +713,11 @@ */ mid = longest(v, d, begin, end, (int *) NULL); if (mid == NULL) { return REG_NOMATCH; } - MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); + MDEBUG(("tentative midpoint %" TCL_Z_MODIFIER "u\n", LOFF(mid))); /* * Iterate until satisfaction or failure. */ @@ -757,11 +764,11 @@ */ MDEBUG(("%d failed midpoint\n", t->id)); return REG_NOMATCH; } - MDEBUG(("%d: new midpoint %ld\n", t->id, LOFF(mid))); + MDEBUG(("%d: new midpoint %" TCL_Z_MODIFIER "u\n", t->id, LOFF(mid))); zaptreesubs(v, t->left); zaptreesubs(v, t->right); } } @@ -797,11 +804,11 @@ mid = shortest(v, d, begin, begin, end, (chr **) NULL, (int *) NULL); if (mid == NULL) { return REG_NOMATCH; } - MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); + MDEBUG(("tentative midpoint %" TCL_Z_MODIFIER "u\n", LOFF(mid))); /* * Iterate until satisfaction or failure. */ @@ -848,11 +855,11 @@ */ MDEBUG(("%d failed midpoint\n", t->id)); return REG_NOMATCH; } - MDEBUG(("%d: new midpoint %ld\n", t->id, LOFF(mid))); + MDEBUG(("%d: new midpoint %" TCL_Z_MODIFIER "u\n", t->id, LOFF(mid))); zaptreesubs(v, t->left); zaptreesubs(v, t->right); } } @@ -880,11 +887,11 @@ assert((size_t)n < v->nmatch); MDEBUG(("cbackref n%d %d{%d-%d}\n", t->id, n, min, max)); /* get the backreferenced string */ - if (v->pmatch[n].rm_so == TCL_INDEX_NONE) { + if (v->pmatch[n].rm_so == FREESTATE) { return REG_NOMATCH; } brstring = v->start + v->pmatch[n].rm_so; brlen = v->pmatch[n].rm_eo - v->pmatch[n].rm_so; @@ -914,21 +921,24 @@ * repetitions of brstring */ assert(end > begin); tlen = end - begin; - if (tlen % brlen != 0) + if (tlen % brlen != 0) { return REG_NOMATCH; + } numreps = tlen / brlen; - if (numreps < (size_t)min || (numreps > (size_t)max && max != DUPINF)) + if (numreps < (size_t)min || (numreps > (size_t)max && max != DUPINF)) { return REG_NOMATCH; + } /* okay, compare the actual string contents */ p = begin; while (numreps-- > 0) { - if ((*v->g->compare) (brstring, p, brlen) != 0) + if ((*v->g->compare) (brstring, p, brlen) != 0) { return REG_NOMATCH; + } p += brlen; } MDEBUG(("cbackref matched\n")); return REG_OKAY; @@ -1001,12 +1011,13 @@ * victory. OTOH, if target string isn't empty, zero matches can't work * so we pretend the min is 1. */ min_matches = t->min; if (min_matches <= 0) { - if (begin == end) + if (begin == end) { return REG_OKAY; + } min_matches = 1; } /* * We need workspace to track the endpoints of each sub-match. Normally @@ -1016,12 +1027,13 @@ * * For convenience, endpts[0] contains the "begin" pointer and we store * sub-match endpoints in endpts[1..max_matches]. */ max_matches = end - begin; - if (max_matches > (size_t)t->max && t->max != DUPINF) + if (max_matches > (size_t)t->max && t->max != DUPINF) { max_matches = t->max; + } if (max_matches < (size_t)min_matches) max_matches = min_matches; endpts = (chr **) MALLOC((max_matches + 1) * sizeof(chr *)); if (endpts == NULL) return REG_ESPACE; @@ -1056,16 +1068,17 @@ if (endpts[k] == NULL) { /* no match possible, so see if we can shorten previous one */ k--; goto backtrack; } - MDEBUG(("%d: working endpoint %d: %ld\n", + MDEBUG(("%d: working endpoint %d: %" TCL_Z_MODIFIER "u\n", t->id, k, LOFF(endpts[k]))); /* k'th sub-match can no longer be considered verified */ - if (nverified >= k) + if (nverified >= k) { nverified = k - 1; + } if (endpts[k] != end) { /* haven't reached end yet, try another iteration if allowed */ if ((size_t)k >= max_matches) { /* must try to shorten some previous match */ @@ -1087,12 +1100,13 @@ * We've identified a way to divide the string into k sub-matches * that works so far as the child DFA can tell. If k is an allowed * number of matches, start the slow part: recurse to verify each * sub-match. We always have k <= max_matches, needn't check that. */ - if (k < min_matches) + if (k < min_matches) { goto backtrack; + } MDEBUG(("%d: verifying %d..%d\n", t->id, nverified + 1, k)); for (i = nverified + 1; i <= k; i++) { zaptreesubs(v, t->left); @@ -1099,12 +1113,13 @@ er = cdissect(v, t->left, endpts[i - 1], endpts[i]); if (er == REG_OKAY) { nverified = i; continue; } - if (er == REG_NOMATCH) + if (er == REG_NOMATCH) { break; + } /* oops, something failed */ FREE(endpts); return er; } @@ -1174,12 +1189,13 @@ * victory. OTOH, if target string isn't empty, zero matches can't work * so we pretend the min is 1. */ min_matches = t->min; if (min_matches <= 0) { - if (begin == end) + if (begin == end) { return REG_OKAY; + } min_matches = 1; } /* * We need workspace to track the endpoints of each sub-match. Normally @@ -1229,27 +1245,29 @@ limit != end && (k >= min_matches || min_matches - k < end - limit)) limit++; /* if this is the last allowed sub-match, it must reach to the end */ - if ((size_t)k >= max_matches) + if ((size_t)k >= max_matches) { limit = end; + } /* try to find an endpoint for the k'th sub-match */ endpts[k] = shortest(v, d, endpts[k - 1], limit, end, (chr **) NULL, (int *) NULL); if (endpts[k] == NULL) { /* no match possible, so see if we can lengthen previous one */ k--; goto backtrack; } - MDEBUG(("%d: working endpoint %d: %ld\n", + MDEBUG(("%d: working endpoint %d: %" TCL_Z_MODIFIER "u\n", t->id, k, LOFF(endpts[k]))); /* k'th sub-match can no longer be considered verified */ - if (nverified >= k) + if (nverified >= k) { nverified = k - 1; + } if (endpts[k] != end) { /* haven't reached end yet, try another iteration if allowed */ if ((size_t)k >= max_matches) { /* must try to lengthen some previous match */ @@ -1266,12 +1284,13 @@ * We've identified a way to divide the string into k sub-matches * that works so far as the child DFA can tell. If k is an allowed * number of matches, start the slow part: recurse to verify each * sub-match. We always have k <= max_matches, needn't check that. */ - if (k < min_matches) + if (k < min_matches) { goto backtrack; + } MDEBUG(("%d: verifying %d..%d\n", t->id, nverified + 1, k)); for (i = nverified + 1; i <= k; i++) { zaptreesubs(v, t->left); @@ -1278,12 +1297,13 @@ er = cdissect(v, t->left, endpts[i - 1], endpts[i]); if (er == REG_OKAY) { nverified = i; continue; } - if (er == REG_NOMATCH) + if (er == REG_NOMATCH) { break; + } /* oops, something failed */ FREE(endpts); return er; } Index: generic/regfree.c ================================================================== --- generic/regfree.c +++ generic/regfree.c @@ -1,9 +1,9 @@ /* * regfree - free an RE * - * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. + * Copyright © 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. Index: generic/regfronts.c ================================================================== --- generic/regfronts.c +++ generic/regfronts.c @@ -2,11 +2,11 @@ * regcomp and regexec - front ends to re_ routines * * Mostly for implementation of backward-compatibility kludges. Note that * these routines exist ONLY in char versions. * - * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. + * Copyright © 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. Index: generic/regguts.h ================================================================== --- generic/regguts.h +++ generic/regguts.h @@ -201,15 +201,15 @@ * Interface definitions for locale-interface functions in locale.c. */ /* Representation of a set of characters. */ struct cvec { - int nchrs; /* number of chrs */ - int chrspace; /* number of chrs possible */ + size_t nchrs; /* number of chrs */ + size_t chrspace; /* number of chrs possible */ chr *chrs; /* pointer to vector of chrs */ - int nranges; /* number of ranges (chr pairs) */ - int rangespace; /* number of chrs possible */ + size_t nranges; /* number of ranges (chr pairs) */ + size_t rangespace; /* number of chrs possible */ chr *ranges; /* pointer to vector of chr pairs */ }; /* * definitions for non-deterministic finite autmaton (NFA) internal @@ -240,31 +240,31 @@ #define ABSIZE 10 struct arc a[ABSIZE]; }; struct state { - int no; -#define FREESTATE (-1) + size_t no; +#define FREESTATE ((size_t)-1) char flag; /* marks special states */ - int nins; /* number of inarcs */ + size_t nins; /* number of inarcs */ struct arc *ins; /* chain of inarcs */ - int nouts; /* number of outarcs */ + size_t nouts; /* number of outarcs */ struct arc *outs; /* chain of outarcs */ struct arc *free; /* chain of free arcs */ struct state *tmp; /* temporary for traversal algorithms */ struct state *next; /* chain for traversing all */ struct state *prev; /* back chain */ struct arcbatch oas; /* first arcbatch, avoid malloc in easy case */ - int noas; /* number of arcs used in first arcbatch */ + size_t noas; /* number of arcs used in first arcbatch */ }; struct nfa { - struct state *pre; /* pre-initial state */ + struct state *pre; /* preinitial state */ struct state *init; /* initial state */ struct state *final; /* final state */ - struct state *post; /* post-final state */ - int nstates; /* for numbering states */ + struct state *post; /* postfinal state */ + size_t nstates; /* for numbering states */ struct state *states; /* state-chain header */ struct state *slast; /* tail of the chain */ struct state *free; /* free list */ struct colormap *cm; /* the color map */ color bos[2]; /* colors, if any, assigned to BOS and BOL */ @@ -288,20 +288,20 @@ * arcs can be distinguished from plain by testing for co >= cnfa.ncolors. */ struct carc { color co; /* COLORLESS is list terminator */ - int to; /* next-state number */ + size_t to; /* next-state number */ }; struct cnfa { - int nstates; /* number of states */ + size_t nstates; /* number of states */ int ncolors; /* number of colors */ int flags; #define HASLACONS 01 /* uses lookahead constraints */ - int pre; /* setup state number */ - int post; /* teardown state number */ + size_t pre; /* setup state number */ + size_t post; /* teardown state number */ color bos[2]; /* colors, if any, assigned to BOS and BOL */ color eos[2]; /* colors, if any, assigned to EOS and EOL */ char *stflags; /* vector of per-state flags bytes */ #define CNFA_NOPROGRESS 01 /* flag bit for a no-progress state */ struct carc **states; /* vector of pointers to outarc lists */ @@ -394,15 +394,15 @@ int cflags; /* copy of compile flags */ long info; /* copy of re_info */ size_t nsub; /* copy of re_nsub */ struct subre *tree; struct cnfa search; /* for fast preliminary search */ - int ntree; /* number of subre's, plus one */ + size_t ntree; /* number of subre's, plus one */ struct colormap cmap; int (*compare) (const chr *, const chr *, size_t); struct subre *lacons; /* lookahead-constraint vector */ - int nlacons; /* size of lacons */ + size_t nlacons; /* size of lacons */ }; /* * Magic for allocating a variable workspace. This default version is * stack-hungry. Index: generic/tcl.decls ================================================================== --- generic/tcl.decls +++ generic/tcl.decls @@ -3,13 +3,13 @@ # 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 +# Copyright © 1998-1999 Scriptics Corporation. +# Copyright © 2001, 2002 Kevin B. Kenny. All rights reserved. +# Copyright © 2007 Daniel A. Steffen # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. library tcl @@ -38,38 +38,38 @@ } declare 2 { TCL_NORETURN void Tcl_Panic(const char *format, ...) } declare 3 { - void *Tcl_Alloc(size_t size) + void *Tcl_Alloc(TCL_HASH_TYPE size) } declare 4 { void Tcl_Free(void *ptr) } declare 5 { - void *Tcl_Realloc(void *ptr, size_t size) + void *Tcl_Realloc(void *ptr, TCL_HASH_TYPE size) } declare 6 { - void *Tcl_DbCkalloc(size_t size, const char *file, int line) + void *Tcl_DbCkalloc(TCL_HASH_TYPE size, const char *file, int line) } declare 7 { void Tcl_DbCkfree(void *ptr, const char *file, int line) } declare 8 { - void *Tcl_DbCkrealloc(void *ptr, size_t size, + void *Tcl_DbCkrealloc(void *ptr, TCL_HASH_TYPE size, const char *file, int line) } -# Tcl_CreateFileHandler and Tcl_DeleteFileHandler are only available on unix, +# Tcl_CreateFileHandler and Tcl_DeleteFileHandler are only available on Unix, # but they are part of the old generic interface, so we include them here for # compatibility reasons. -declare 9 unix { +declare 9 { void Tcl_CreateFileHandler(int fd, int mask, Tcl_FileProc *proc, void *clientData) } -declare 10 unix { +declare 10 { void Tcl_DeleteFileHandler(int fd) } declare 11 { void Tcl_SetTimer(const Tcl_Time *timePtr) } @@ -84,14 +84,14 @@ } declare 15 { void Tcl_AppendStringsToObj(Tcl_Obj *objPtr, ...) } declare 16 { - void Tcl_AppendToObj(Tcl_Obj *objPtr, const char *bytes, size_t length) + void Tcl_AppendToObj(Tcl_Obj *objPtr, const char *bytes, Tcl_Size length) } declare 17 { - Tcl_Obj *Tcl_ConcatObj(int objc, Tcl_Obj *const objv[]) + Tcl_Obj *Tcl_ConcatObj(Tcl_Size objc, Tcl_Obj *const objv[]) } declare 18 { int Tcl_ConvertToType(Tcl_Interp *interp, Tcl_Obj *objPtr, const Tcl_ObjType *typePtr) } @@ -104,22 +104,22 @@ 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) +# Tcl_Obj *Tcl_DbNewBooleanObj(int intValue, const char *file, int line) #} declare 23 { - Tcl_Obj *Tcl_DbNewByteArrayObj(const unsigned char *bytes, size_t length, - const char *file, int line) + Tcl_Obj *Tcl_DbNewByteArrayObj(const unsigned char *bytes, + Tcl_Size numBytes, const char *file, int line) } declare 24 { Tcl_Obj *Tcl_DbNewDoubleObj(double doubleValue, const char *file, int line) } declare 25 { - Tcl_Obj *Tcl_DbNewListObj(int objc, Tcl_Obj *const *objv, + Tcl_Obj *Tcl_DbNewListObj(Tcl_Size objc, Tcl_Obj *const *objv, const char *file, int line) } # Removed in 9.0 (changed to macro): #declare 26 { # Tcl_Obj *Tcl_DbNewLongObj(long longValue, const char *file, int line) @@ -126,28 +126,29 @@ #} declare 27 { Tcl_Obj *Tcl_DbNewObj(const char *file, int line) } declare 28 { - Tcl_Obj *Tcl_DbNewStringObj(const char *bytes, size_t length, + Tcl_Obj *Tcl_DbNewStringObj(const char *bytes, Tcl_Size length, const char *file, int line) } declare 29 { Tcl_Obj *Tcl_DuplicateObj(Tcl_Obj *objPtr) } declare 30 { void TclFreeObj(Tcl_Obj *objPtr) } declare 31 { - int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *boolPtr) + int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *intPtr) } declare 32 { int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, - int *boolPtr) + int *intPtr) } +# Only available in Tcl 8.x, NULL in Tcl 9.0 declare 33 { - unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr) + unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, Tcl_Size *numBytesPtr) } declare 34 { int Tcl_GetDouble(Tcl_Interp *interp, const char *src, double *doublePtr) } declare 35 { @@ -170,11 +171,11 @@ } declare 40 { const Tcl_ObjType *Tcl_GetObjType(const char *typeName) } declare 41 { - char *Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr) + char *TclGetStringFromObj(Tcl_Obj *objPtr, void *lengthPtr) } declare 42 { void Tcl_InvalidateStringRep(Tcl_Obj *objPtr) } declare 43 { @@ -184,91 +185,91 @@ declare 44 { int Tcl_ListObjAppendElement(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr) } declare 45 { - int Tcl_ListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr, - int *objcPtr, Tcl_Obj ***objvPtr) + int TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr, + void *objcPtr, Tcl_Obj ***objvPtr) } declare 46 { - int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, int index, + int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index, Tcl_Obj **objPtrPtr) } declare 47 { - int Tcl_ListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr, - int *lengthPtr) + int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr, + void *lengthPtr) } declare 48 { - int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, int first, - int count, int objc, Tcl_Obj *const objv[]) + int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size first, + Tcl_Size count, Tcl_Size objc, Tcl_Obj *const objv[]) } # Removed in 9.0 (changed to macro): #declare 49 { -# Tcl_Obj *Tcl_NewBooleanObj(int boolValue) +# Tcl_Obj *Tcl_NewBooleanObj(int intValue) #} declare 50 { - Tcl_Obj *Tcl_NewByteArrayObj(const unsigned char *bytes, size_t length) + Tcl_Obj *Tcl_NewByteArrayObj(const unsigned char *bytes, Tcl_Size numBytes) } declare 51 { Tcl_Obj *Tcl_NewDoubleObj(double doubleValue) } # Removed in 9.0 (changed to macro): #declare 52 { # Tcl_Obj *Tcl_NewIntObj(int intValue) #} declare 53 { - Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[]) + Tcl_Obj *Tcl_NewListObj(Tcl_Size objc, Tcl_Obj *const objv[]) } # Removed in 9.0 (changed to macro): #declare 54 { # Tcl_Obj *Tcl_NewLongObj(long longValue) #} declare 55 { Tcl_Obj *Tcl_NewObj(void) } declare 56 { - Tcl_Obj *Tcl_NewStringObj(const char *bytes, size_t length) + Tcl_Obj *Tcl_NewStringObj(const char *bytes, Tcl_Size length) } # Removed in 9.0 (changed to macro): #declare 57 { -# void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue) +# void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int intValue) #} declare 58 { - unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, size_t length) + unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, Tcl_Size numBytes) } declare 59 { void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, const unsigned char *bytes, - size_t length) + Tcl_Size numBytes) } declare 60 { void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue) } # Removed in 9.0 (changed to macro): #declare 61 { # void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue) #} declare 62 { - void Tcl_SetListObj(Tcl_Obj *objPtr, int objc, Tcl_Obj *const objv[]) + void Tcl_SetListObj(Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[]) } # Removed in 9.0 (changed to macro): #declare 63 { # void Tcl_SetLongObj(Tcl_Obj *objPtr, long longValue) #} declare 64 { - void Tcl_SetObjLength(Tcl_Obj *objPtr, size_t length) + void Tcl_SetObjLength(Tcl_Obj *objPtr, Tcl_Size length) } declare 65 { - void Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes, size_t length) + void Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes, Tcl_Size length) } # Removed in 9.0, replaced by macro. #declare 66 { # void Tcl_AddErrorInfo(Tcl_Interp *interp, const char *message) #} # Removed in 9.0, replaced by macro. #declare 67 { # void Tcl_AddObjErrorInfo(Tcl_Interp *interp, const char *message, -# int length) +# Tcl_Size length) #} declare 68 { void Tcl_AllowExceptions(Tcl_Interp *interp) } declare 69 { @@ -310,35 +311,35 @@ void *clientData) } declare 80 { void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, void *clientData) } -# Removed in 9.0: -#declare 81 { -# int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan) -#} +# Only available in Tcl 8.x, NULL in Tcl 9.0 +declare 81 { + int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan) +} declare 82 { int Tcl_CommandComplete(const char *cmd) } declare 83 { - char *Tcl_Concat(int argc, const char *const *argv) + char *Tcl_Concat(Tcl_Size argc, const char *const *argv) } declare 84 { - size_t Tcl_ConvertElement(const char *src, char *dst, int flags) + Tcl_Size Tcl_ConvertElement(const char *src, char *dst, int flags) } declare 85 { - size_t Tcl_ConvertCountedElement(const char *src, size_t length, char *dst, + Tcl_Size Tcl_ConvertCountedElement(const char *src, Tcl_Size length, char *dst, int flags) } declare 86 { int Tcl_CreateAlias(Tcl_Interp *childInterp, const char *childCmd, - Tcl_Interp *target, const char *targetCmd, int argc, + Tcl_Interp *target, const char *targetCmd, Tcl_Size argc, const char *const *argv) } declare 87 { int Tcl_CreateAliasObj(Tcl_Interp *childInterp, const char *childCmd, - Tcl_Interp *target, const char *targetCmd, int objc, + Tcl_Interp *target, const char *targetCmd, Tcl_Size objc, Tcl_Obj *const objv[]) } declare 88 { Tcl_Channel Tcl_CreateChannel(const Tcl_ChannelType *typePtr, const char *chanName, void *instanceData, int mask) @@ -385,11 +386,11 @@ declare 98 { Tcl_TimerToken Tcl_CreateTimerHandler(int milliseconds, Tcl_TimerProc *proc, void *clientData) } declare 99 { - Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, int level, + Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, Tcl_Size level, Tcl_CmdTraceProc *proc, void *clientData) } declare 100 { void Tcl_DeleteAssocData(Tcl_Interp *interp, const char *name) } @@ -425,11 +426,11 @@ } declare 110 { void Tcl_DeleteInterp(Tcl_Interp *interp) } declare 111 { - void Tcl_DetachPids(int numPids, Tcl_Pid *pidPtr) + void Tcl_DetachPids(Tcl_Size numPids, Tcl_Pid *pidPtr) } declare 112 { void Tcl_DeleteTimerHandler(Tcl_TimerToken token) } declare 113 { @@ -444,11 +445,11 @@ } declare 116 { void Tcl_DoWhenIdle(Tcl_IdleProc *proc, void *clientData) } declare 117 { - char *Tcl_DStringAppend(Tcl_DString *dsPtr, const char *bytes, size_t length) + char *Tcl_DStringAppend(Tcl_DString *dsPtr, const char *bytes, Tcl_Size length) } declare 118 { char *Tcl_DStringAppendElement(Tcl_DString *dsPtr, const char *element) } declare 119 { @@ -465,11 +466,11 @@ } declare 123 { void Tcl_DStringResult(Tcl_Interp *interp, Tcl_DString *dsPtr) } declare 124 { - void Tcl_DStringSetLength(Tcl_DString *dsPtr, size_t length) + void Tcl_DStringSetLength(Tcl_DString *dsPtr, Tcl_Size length) } declare 125 { void Tcl_DStringStartSublist(Tcl_DString *dsPtr) } declare 126 { @@ -530,11 +531,11 @@ declare 143 { void Tcl_Finalize(void) } # Removed in 9.0 (stub entry only) #declare 144 { -# void Tcl_FindExecutable(const char *argv0) +# const char *Tcl_FindExecutable(const char *argv0) #} declare 145 { Tcl_HashEntry *Tcl_FirstHashEntry(Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr) } @@ -562,11 +563,11 @@ declare 151 { Tcl_Channel Tcl_GetChannel(Tcl_Interp *interp, const char *chanName, int *modePtr) } declare 152 { - int Tcl_GetChannelBufferSize(Tcl_Channel chan) + Tcl_Size Tcl_GetChannelBufferSize(Tcl_Channel chan) } declare 153 { int Tcl_GetChannelHandle(Tcl_Channel chan, int direction, void **handlePtr) } @@ -614,24 +615,24 @@ } # Tcl_GetOpenFile is only available on unix, but it is a part of the old # generic interface, so we include it here for compatibility reasons. -declare 167 unix { - int Tcl_GetOpenFile(Tcl_Interp *interp, const char *chanID, int forWriting, - int checkUsage, void **filePtr) +declare 167 { + int Tcl_GetOpenFile(Tcl_Interp *interp, const char *chanID, + int forWriting, int checkUsage, void **filePtr) } # Obsolete. Should now use Tcl_FSGetPathType which is objectified # and therefore usually faster. declare 168 { Tcl_PathType Tcl_GetPathType(const char *path) } declare 169 { - size_t Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr) + Tcl_Size Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr) } declare 170 { - size_t Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr) + Tcl_Size Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr) } declare 171 { int Tcl_GetServiceMode(void) } declare 172 { @@ -683,11 +684,11 @@ declare 185 { int Tcl_IsSafe(Tcl_Interp *interp) } # Obsolete, use Tcl_FSJoinPath declare 186 { - char *Tcl_JoinPath(int argc, const char *const *argv, + char *Tcl_JoinPath(Tcl_Size argc, const char *const *argv, Tcl_DString *resultPtr) } declare 187 { int Tcl_LinkVar(Tcl_Interp *interp, const char *varName, void *addr, int type) @@ -699,18 +700,19 @@ # } declare 189 { Tcl_Channel Tcl_MakeFileChannel(void *handle, int mode) } -declare 190 { - int Tcl_MakeSafe(Tcl_Interp *interp) -} +# Removed in 9.0 +#declare 190 { +# int Tcl_MakeSafe(Tcl_Interp *interp) +#} declare 191 { Tcl_Channel Tcl_MakeTcpClientChannel(void *tcpSocket) } declare 192 { - char *Tcl_Merge(int argc, const char *const *argv) + char *Tcl_Merge(Tcl_Size argc, const char *const *argv) } declare 193 { Tcl_HashEntry *Tcl_NextHashEntry(Tcl_HashSearch *searchPtr) } declare 194 { @@ -723,21 +725,21 @@ declare 196 { Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags) } declare 197 { - Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc, + Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, Tcl_Size argc, const char **argv, int flags) } # This is obsolete, use Tcl_FSOpenFileChannel declare 198 { Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions) } declare 199 { Tcl_Channel Tcl_OpenTcpClient(Tcl_Interp *interp, int port, - const char *address, const char *myaddr, int myport, int async) + const char *address, const char *myaddr, int myport, int flags) } declare 200 { Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port, const char *host, Tcl_TcpAcceptProc *acceptProc, void *callbackData) @@ -753,14 +755,14 @@ } declare 204 { const char *Tcl_PosixError(Tcl_Interp *interp) } declare 205 { - void Tcl_QueueEvent(Tcl_Event *evPtr, Tcl_QueuePosition position) + void Tcl_QueueEvent(Tcl_Event *evPtr, int position) } declare 206 { - size_t Tcl_Read(Tcl_Channel chan, char *bufPtr, size_t toRead) + Tcl_Size Tcl_Read(Tcl_Channel chan, char *bufPtr, Tcl_Size toRead) } declare 207 { void Tcl_ReapDetachedProcs(void) } declare 208 { @@ -785,24 +787,24 @@ declare 214 { int Tcl_RegExpMatch(Tcl_Interp *interp, const char *text, const char *pattern) } declare 215 { - void Tcl_RegExpRange(Tcl_RegExp regexp, size_t index, + void Tcl_RegExpRange(Tcl_RegExp regexp, Tcl_Size index, const char **startPtr, const char **endPtr) } declare 216 { void Tcl_Release(void *clientData) } declare 217 { void Tcl_ResetResult(Tcl_Interp *interp) } declare 218 { - size_t Tcl_ScanElement(const char *src, int *flagPtr) + Tcl_Size Tcl_ScanElement(const char *src, int *flagPtr) } declare 219 { - size_t Tcl_ScanCountedElement(const char *src, size_t length, int *flagPtr) + Tcl_Size Tcl_ScanCountedElement(const char *src, Tcl_Size length, int *flagPtr) } # Removed in 9.0: #declare 220 { # int Tcl_SeekOld(Tcl_Channel chan, int offset, int mode) #} @@ -815,11 +817,11 @@ declare 223 { void Tcl_SetAssocData(Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc *proc, void *clientData) } declare 224 { - void Tcl_SetChannelBufferSize(Tcl_Channel chan, int sz) + void Tcl_SetChannelBufferSize(Tcl_Channel chan, Tcl_Size sz) } declare 225 { int Tcl_SetChannelOption(Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, const char *newValue) } @@ -836,14 +838,14 @@ 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) +# const char *Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc) #} declare 231 { - int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth) + Tcl_Size Tcl_SetRecursionLimit(Tcl_Interp *interp, Tcl_Size depth) } # Removed in 9.0, replaced by macro. #declare 232 { # void Tcl_SetResult(Tcl_Interp *interp, char *result, # Tcl_FreeProc *freeProc) @@ -877,21 +879,21 @@ } declare 241 { void Tcl_SourceRCFile(Tcl_Interp *interp) } declare 242 { - int Tcl_SplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr, + int TclSplitList(Tcl_Interp *interp, const char *listStr, void *argcPtr, const char ***argvPtr) } # Obsolete, use Tcl_FSSplitPath declare 243 { - void Tcl_SplitPath(const char *path, int *argcPtr, const char ***argvPtr) + void TclSplitPath(const char *path, void *argcPtr, const char ***argvPtr) } # Removed in 9.0 (stub entry only) #declare 244 { -# void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName, -# Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc) +# void Tcl_StaticLibrary(Tcl_Interp *interp, const char *prefix, +# Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc) #} # Removed in 9.0 (stub entry only) #declare 245 { # int Tcl_StringMatch(const char *str, const char *pattern) #} @@ -900,11 +902,11 @@ # 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) +# Tcl_VarTraceProc *proc, void *clientData) #} declare 248 { int Tcl_TraceVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, void *clientData) } @@ -911,11 +913,11 @@ declare 249 { char *Tcl_TranslateFileName(Tcl_Interp *interp, const char *name, Tcl_DString *bufferPtr) } declare 250 { - size_t Tcl_Ungets(Tcl_Channel chan, const char *str, size_t len, int atHead) + Tcl_Size Tcl_Ungets(Tcl_Channel chan, const char *str, Tcl_Size len, int atHead) } declare 251 { void Tcl_UnlinkVar(Tcl_Interp *interp, const char *varName) } declare 252 { @@ -930,11 +932,11 @@ 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) +# Tcl_VarTraceProc *proc, void *clientData) #} declare 256 { void Tcl_UntraceVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, void *clientData) @@ -954,23 +956,23 @@ 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) +# void *Tcl_VarTraceInfo(Tcl_Interp *interp, const char *varName, +# int flags, Tcl_VarTraceProc *procPtr, void *prevClientData) #} declare 262 { void *Tcl_VarTraceInfo2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *procPtr, void *prevClientData) } declare 263 { - size_t Tcl_Write(Tcl_Channel chan, const char *s, size_t slen) + Tcl_Size Tcl_Write(Tcl_Channel chan, const char *s, Tcl_Size slen) } declare 264 { - void Tcl_WrongNumArgs(Tcl_Interp *interp, int objc, + void Tcl_WrongNumArgs(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], const char *message) } declare 265 { int Tcl_DumpActiveMemory(const char *fileName) } @@ -1082,20 +1084,20 @@ 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. +# Removed in 9.0 #declare 290 { # void Tcl_DiscardResult(Tcl_SavedResult *statePtr) #} declare 291 { - int Tcl_EvalEx(Tcl_Interp *interp, const char *script, size_t numBytes, + int Tcl_EvalEx(Tcl_Interp *interp, const char *script, Tcl_Size numBytes, int flags) } declare 292 { - int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], + int Tcl_EvalObjv(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags) } declare 293 { int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) } @@ -1102,17 +1104,17 @@ declare 294 { TCL_NORETURN void Tcl_ExitThread(int status) } declare 295 { int Tcl_ExternalToUtf(Tcl_Interp *interp, Tcl_Encoding encoding, - const char *src, size_t srcLen, int flags, - Tcl_EncodingState *statePtr, char *dst, size_t dstLen, + const char *src, Tcl_Size srcLen, int flags, + Tcl_EncodingState *statePtr, char *dst, Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr) } declare 296 { char *Tcl_ExternalToUtfDString(Tcl_Encoding encoding, - const char *src, size_t srcLen, Tcl_DString *dsPtr) + const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr) } declare 297 { void Tcl_FinalizeThread(void) } declare 298 { @@ -1133,15 +1135,15 @@ declare 303 { void Tcl_GetEncodingNames(Tcl_Interp *interp) } declare 304 { int Tcl_GetIndexFromObjStruct(Tcl_Interp *interp, Tcl_Obj *objPtr, - const void *tablePtr, size_t offset, const char *msg, int flags, - int *indexPtr) + const void *tablePtr, Tcl_Size offset, const char *msg, int flags, + void *indexPtr) } declare 305 { - void *Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, size_t size) + void *Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, Tcl_Size size) } declare 306 { Tcl_Obj *Tcl_GetVar2Ex(Tcl_Interp *interp, const char *part1, const char *part2, int flags) } @@ -1160,21 +1162,21 @@ declare 311 { void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr, const Tcl_Time *timePtr) } declare 312 { - size_t Tcl_NumUtfChars(const char *src, size_t length) + Tcl_Size TclNumUtfChars(const char *src, Tcl_Size length) } declare 313 { - size_t Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, - size_t charsToRead, int appendFlag) + Tcl_Size Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, + Tcl_Size charsToRead, int appendFlag) } -# Removed in 9.0, replaced by macro. +# Removed in 9.0 #declare 314 { # void Tcl_RestoreResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr) #} -# Removed in 9.0, replaced by macro. +# Removed in 9.0 #declare 315 { # void Tcl_SaveResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr) #} declare 316 { int Tcl_SetSystemEncoding(Tcl_Interp *interp, const char *name) @@ -1186,14 +1188,14 @@ declare 318 { void Tcl_ThreadAlert(Tcl_ThreadId threadId) } declare 319 { void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, Tcl_Event *evPtr, - Tcl_QueuePosition position) + int position) } declare 320 { - int Tcl_UniCharAtIndex(const char *src, size_t index) + int Tcl_UniCharAtIndex(const char *src, Tcl_Size index) } declare 321 { int Tcl_UniCharToLower(int ch) } declare 322 { @@ -1201,60 +1203,60 @@ } declare 323 { int Tcl_UniCharToUpper(int ch) } declare 324 { - int Tcl_UniCharToUtf(int ch, char *buf) + Tcl_Size Tcl_UniCharToUtf(int ch, char *buf) } declare 325 { - const char *Tcl_UtfAtIndex(const char *src, size_t index) + const char *TclUtfAtIndex(const char *src, Tcl_Size index) } declare 326 { - int Tcl_UtfCharComplete(const char *src, size_t length) + int TclUtfCharComplete(const char *src, Tcl_Size length) } declare 327 { - size_t Tcl_UtfBackslash(const char *src, int *readPtr, char *dst) + Tcl_Size Tcl_UtfBackslash(const char *src, int *readPtr, char *dst) } declare 328 { const char *Tcl_UtfFindFirst(const char *src, int ch) } declare 329 { const char *Tcl_UtfFindLast(const char *src, int ch) } declare 330 { - const char *Tcl_UtfNext(const char *src) + const char *TclUtfNext(const char *src) } declare 331 { - const char *Tcl_UtfPrev(const char *src, const char *start) + const char *TclUtfPrev(const char *src, const char *start) } declare 332 { int Tcl_UtfToExternal(Tcl_Interp *interp, Tcl_Encoding encoding, - const char *src, size_t srcLen, int flags, - Tcl_EncodingState *statePtr, char *dst, size_t dstLen, + const char *src, Tcl_Size srcLen, int flags, + Tcl_EncodingState *statePtr, char *dst, Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr) } declare 333 { char *Tcl_UtfToExternalDString(Tcl_Encoding encoding, - const char *src, size_t srcLen, Tcl_DString *dsPtr) + const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr) } declare 334 { - int Tcl_UtfToLower(char *src) + Tcl_Size Tcl_UtfToLower(char *src) } declare 335 { - int Tcl_UtfToTitle(char *src) + Tcl_Size Tcl_UtfToTitle(char *src) } declare 336 { - int Tcl_UtfToChar16(const char *src, unsigned short *chPtr) + Tcl_Size Tcl_UtfToChar16(const char *src, unsigned short *chPtr) } declare 337 { - int Tcl_UtfToUpper(char *src) + Tcl_Size Tcl_UtfToUpper(char *src) } declare 338 { - size_t Tcl_WriteChars(Tcl_Channel chan, const char *src, size_t srcLen) + Tcl_Size Tcl_WriteChars(Tcl_Channel chan, const char *src, Tcl_Size srcLen) } declare 339 { - size_t Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr) + Tcl_Size Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr) } declare 340 { char *Tcl_GetString(Tcl_Obj *objPtr) } # Removed in 9.0: @@ -1290,64 +1292,63 @@ int Tcl_UniCharIsUpper(int ch) } declare 351 { int Tcl_UniCharIsWordChar(int ch) } -# Removed in 9.0: -#declare 352 { -# size_t Tcl_UniCharLen(const Tcl_UniChar *uniStr) -#} +declare 352 { + Tcl_Size Tcl_Char16Len(const unsigned short *uniStr) +} # Removed in 9.0: #declare 353 { # int Tcl_UniCharNcmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, -# size_t numChars) +# unsigned long numChars) #} declare 354 { char *Tcl_Char16ToUtfDString(const unsigned short *uniStr, - size_t uniLength, Tcl_DString *dsPtr) + Tcl_Size uniLength, Tcl_DString *dsPtr) } declare 355 { unsigned short *Tcl_UtfToChar16DString(const char *src, - size_t length, Tcl_DString *dsPtr) + Tcl_Size length, Tcl_DString *dsPtr) } declare 356 { Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj, int flags) } # Removed in 9.0: #declare 357 { # Tcl_Obj *Tcl_EvalTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr, -# int count) +# Tcl_Size count) #} declare 358 { void Tcl_FreeParse(Tcl_Parse *parsePtr) } declare 359 { void Tcl_LogCommandInfo(Tcl_Interp *interp, const char *script, - const char *command, size_t length) + const char *command, Tcl_Size length) } declare 360 { int Tcl_ParseBraces(Tcl_Interp *interp, const char *start, - size_t numBytes, Tcl_Parse *parsePtr, int append, + Tcl_Size numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr) } declare 361 { int Tcl_ParseCommand(Tcl_Interp *interp, const char *start, - size_t numBytes, int nested, Tcl_Parse *parsePtr) + Tcl_Size numBytes, int nested, Tcl_Parse *parsePtr) } declare 362 { - int Tcl_ParseExpr(Tcl_Interp *interp, const char *start, size_t numBytes, - Tcl_Parse *parsePtr) + int Tcl_ParseExpr(Tcl_Interp *interp, const char *start, + Tcl_Size numBytes, Tcl_Parse *parsePtr) } declare 363 { int Tcl_ParseQuotedString(Tcl_Interp *interp, const char *start, - size_t numBytes, Tcl_Parse *parsePtr, int append, + Tcl_Size numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr) } declare 364 { int Tcl_ParseVarName(Tcl_Interp *interp, const char *start, - size_t numBytes, Tcl_Parse *parsePtr, int append) + Tcl_Size numBytes, Tcl_Parse *parsePtr, int append) } # These 4 functions are obsolete, use Tcl_FSGetCwd, Tcl_FSChdir, # Tcl_FSAccess and Tcl_FSStat declare 365 { char *Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr) @@ -1382,46 +1383,45 @@ declare 375 { int Tcl_UniCharIsPunct(int ch) } declare 376 { int Tcl_RegExpExecObj(Tcl_Interp *interp, Tcl_RegExp regexp, - Tcl_Obj *textObj, size_t offset, size_t nmatches, int flags) + Tcl_Obj *textObj, Tcl_Size offset, Tcl_Size nmatches, int flags) } declare 377 { void Tcl_RegExpGetInfo(Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr) } declare 378 { - Tcl_Obj *Tcl_NewUnicodeObj(const Tcl_UniChar *unicode, size_t numChars) + Tcl_Obj *Tcl_NewUnicodeObj(const Tcl_UniChar *unicode, Tcl_Size numChars) } declare 379 { void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, - size_t numChars) + Tcl_Size numChars) } declare 380 { - size_t Tcl_GetCharLength(Tcl_Obj *objPtr) + Tcl_Size TclGetCharLength(Tcl_Obj *objPtr) } declare 381 { - int Tcl_GetUniChar(Tcl_Obj *objPtr, size_t index) + int TclGetUniChar(Tcl_Obj *objPtr, Tcl_Size index) } # Removed in 9.0, replaced by macro. #declare 382 { # Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj *objPtr) #} declare 383 { - Tcl_Obj *Tcl_GetRange(Tcl_Obj *objPtr, size_t first, size_t last) + Tcl_Obj *TclGetRange(Tcl_Obj *objPtr, Tcl_Size first, Tcl_Size last) } -# Removed in 9.0 -#declare 384 { -# void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, -# size_t length) -#} +declare 384 { + void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, + Tcl_Size length) +} declare 385 { int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *textObj, Tcl_Obj *patternObj) } declare 386 { - void Tcl_SetNotifier(Tcl_NotifierProcs *notifierProcPtr) + void Tcl_SetNotifier(const Tcl_NotifierProcs *notifierProcPtr) } declare 387 { Tcl_Mutex *Tcl_GetAllocMutex(void) } declare 388 { @@ -1430,29 +1430,29 @@ declare 389 { int Tcl_GetChannelNamesEx(Tcl_Interp *interp, const char *pattern) } declare 390 { int Tcl_ProcObjCmd(void *clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]) + Tcl_Size objc, Tcl_Obj *const objv[]) } declare 391 { void Tcl_ConditionFinalize(Tcl_Condition *condPtr) } declare 392 { void Tcl_MutexFinalize(Tcl_Mutex *mutex) } declare 393 { int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, - void *clientData, size_t stackSize, int flags) + void *clientData, TCL_HASH_TYPE stackSize, int flags) } # Introduced in 8.3.2 declare 394 { - size_t Tcl_ReadRaw(Tcl_Channel chan, char *dst, size_t bytesToRead) + Tcl_Size Tcl_ReadRaw(Tcl_Channel chan, char *dst, Tcl_Size bytesToRead) } declare 395 { - size_t Tcl_WriteRaw(Tcl_Channel chan, const char *src, size_t srcLen) + Tcl_Size Tcl_WriteRaw(Tcl_Channel chan, const char *src, Tcl_Size srcLen) } declare 396 { Tcl_Channel Tcl_GetTopChannel(Tcl_Channel chan) } declare 397 { @@ -1539,11 +1539,11 @@ 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) +# unsigned long numChars) #} # Removed in 9.0: #declare 420 { # int Tcl_UniCharCaseMatch(const Tcl_UniChar *uniStr, # const Tcl_UniChar *uniPattern, int nocase) @@ -1576,34 +1576,34 @@ declare 427 { void Tcl_UntraceCommand(Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, void *clientData) } declare 428 { - void *Tcl_AttemptAlloc(size_t size) + void *Tcl_AttemptAlloc(TCL_HASH_TYPE size) } declare 429 { - void *Tcl_AttemptDbCkalloc(size_t size, const char *file, int line) + void *Tcl_AttemptDbCkalloc(TCL_HASH_TYPE size, const char *file, int line) } declare 430 { - void *Tcl_AttemptRealloc(void *ptr, size_t size) + void *Tcl_AttemptRealloc(void *ptr, TCL_HASH_TYPE size) } declare 431 { - void *Tcl_AttemptDbCkrealloc(void *ptr, size_t size, + void *Tcl_AttemptDbCkrealloc(void *ptr, TCL_HASH_TYPE size, const char *file, int line) } declare 432 { - int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, size_t length) + int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, Tcl_Size length) } # TIP#10 (thread-aware channels) akupries declare 433 { Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel) } # introduced in 8.4a3 declare 434 { - Tcl_UniChar *Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr) + Tcl_UniChar *TclGetUnicodeFromObj(Tcl_Obj *objPtr, void *lengthPtr) } # TIP#15 (math function introspection) dkf # Removed in 9.0: #declare 435 { @@ -1641,12 +1641,12 @@ declare 443 { int Tcl_FSDeleteFile(Tcl_Obj *pathPtr) } declare 444 { int Tcl_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, - const char *sym2, Tcl_PackageInitProc **proc1Ptr, - Tcl_PackageInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, + const char *sym2, Tcl_LibraryInitProc **proc1Ptr, + Tcl_LibraryInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr) } declare 445 { int Tcl_FSMatchInDirectory(Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types) @@ -1697,23 +1697,23 @@ } declare 459 { int Tcl_FSConvertToPathType(Tcl_Interp *interp, Tcl_Obj *pathPtr) } declare 460 { - Tcl_Obj *Tcl_FSJoinPath(Tcl_Obj *listObj, int elements) + Tcl_Obj *Tcl_FSJoinPath(Tcl_Obj *listObj, Tcl_Size elements) } declare 461 { - Tcl_Obj *Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *lenPtr) + Tcl_Obj *TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr) } declare 462 { int Tcl_FSEqualPaths(Tcl_Obj *firstPtr, Tcl_Obj *secondPtr) } declare 463 { Tcl_Obj *Tcl_FSGetNormalizedPath(Tcl_Interp *interp, Tcl_Obj *pathPtr) } declare 464 { - Tcl_Obj *Tcl_FSJoinToPath(Tcl_Obj *pathPtr, int objc, + Tcl_Obj *Tcl_FSJoinToPath(Tcl_Obj *pathPtr, Tcl_Size objc, Tcl_Obj *const objv[]) } declare 465 { void *Tcl_FSGetInternalRep(Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr) @@ -1769,21 +1769,21 @@ } # TIP#56 (evaluate a parsed script) msofer declare 481 { int Tcl_EvalTokensStandard(Tcl_Interp *interp, Tcl_Token *tokenPtr, - size_t count) + Tcl_Size count) } # TIP#73 (access to current time) kbk declare 482 { void Tcl_GetTime(Tcl_Time *timeBuf) } # TIP#32 (object-enabled traces) kbk declare 483 { - Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, int level, int flags, + Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, Tcl_Size level, int flags, Tcl_CmdObjTraceProc *objProc, void *clientData, Tcl_CmdObjTraceDeleteProc *delProc) } declare 484 { int Tcl_GetCommandInfoFromToken(Tcl_Command token, Tcl_CmdInfo *infoPtr) @@ -1811,14 +1811,14 @@ } declare 490 { Tcl_StatBuf *Tcl_AllocStatBuf(void) } declare 491 { - Tcl_WideInt Tcl_Seek(Tcl_Channel chan, Tcl_WideInt offset, int mode) + long long Tcl_Seek(Tcl_Channel chan, long long offset, int mode) } declare 492 { - Tcl_WideInt Tcl_Tell(Tcl_Channel chan) + long long Tcl_Tell(Tcl_Channel chan) } # TIP#91 (back-compat enhancements for channels) dkf declare 493 { Tcl_DriverWideSeekProc *Tcl_ChannelWideSeekProc( @@ -1839,11 +1839,11 @@ declare 496 { int Tcl_DictObjRemove(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr) } declare 497 { - int Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr) + int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, void *sizePtr) } declare 498 { int Tcl_DictObjFirst(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr) @@ -1855,15 +1855,15 @@ declare 500 { void Tcl_DictObjDone(Tcl_DictSearch *searchPtr) } declare 501 { int Tcl_DictObjPutKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr, - int keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr) + Tcl_Size keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr) } declare 502 { int Tcl_DictObjRemoveKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr, - int keyc, Tcl_Obj *const *keyv) + Tcl_Size keyc, Tcl_Obj *const *keyv) } declare 503 { Tcl_Obj *Tcl_NewDictObj(void) } declare 504 { @@ -1952,11 +1952,11 @@ } declare 524 { int Tcl_LimitExceeded(Tcl_Interp *interp) } declare 525 { - void Tcl_LimitSetCommands(Tcl_Interp *interp, int commandLimit) + void Tcl_LimitSetCommands(Tcl_Interp *interp, Tcl_Size commandLimit) } declare 526 { void Tcl_LimitSetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr) } declare 527 { @@ -2086,11 +2086,11 @@ int Tcl_TakeBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, void *value) } # TIP #208 ('chan' command) jeffh declare 560 { - int Tcl_TruncateChannel(Tcl_Channel chan, Tcl_WideInt length) + int Tcl_TruncateChannel(Tcl_Channel chan, long long length) } declare 561 { Tcl_DriverTruncateProc *Tcl_ChannelTruncateProc( const Tcl_ChannelType *chanTypePtr) } @@ -2141,28 +2141,28 @@ } # TIP#268 (extended version numbers and requirements) akupries declare 573 { int Tcl_PkgRequireProc(Tcl_Interp *interp, const char *name, - int objc, Tcl_Obj *const objv[], void *clientDataPtr) + Tcl_Size objc, Tcl_Obj *const objv[], void *clientDataPtr) } # TIP#270 (utility C routines for string formatting) dgp declare 574 { void Tcl_AppendObjToErrorInfo(Tcl_Interp *interp, Tcl_Obj *objPtr) } declare 575 { void Tcl_AppendLimitedToObj(Tcl_Obj *objPtr, const char *bytes, - size_t length, size_t limit, const char *ellipsis) + Tcl_Size length, Tcl_Size limit, const char *ellipsis) } declare 576 { - Tcl_Obj *Tcl_Format(Tcl_Interp *interp, const char *format, int objc, + Tcl_Obj *Tcl_Format(Tcl_Interp *interp, const char *format, Tcl_Size objc, Tcl_Obj *const objv[]) } declare 577 { int Tcl_AppendFormatToObj(Tcl_Interp *interp, Tcl_Obj *objPtr, - const char *format, int objc, Tcl_Obj *const objv[]) + const char *format, Tcl_Size objc, Tcl_Obj *const objv[]) } declare 578 { Tcl_Obj *Tcl_ObjPrintf(const char *format, ...) } declare 579 { @@ -2195,15 +2195,15 @@ } declare 584 { int Tcl_NREvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) } declare 585 { - int Tcl_NREvalObjv(Tcl_Interp *interp, int objc, + int Tcl_NREvalObjv(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags) } declare 586 { - int Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd, int objc, + int Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd, Tcl_Size objc, Tcl_Obj *const objv[], int flags) } declare 587 { void Tcl_NRAddCallback(Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, void *data0, void *data1, void *data2, @@ -2211,11 +2211,11 @@ } # For use by NR extenders, to have a simple way to also provide a (required!) # classic objProc declare 588 { int Tcl_NRCallObjProc(Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, - void *clientData, int objc, Tcl_Obj *const objv[]) + void *clientData, Tcl_Size objc, Tcl_Obj *const objv[]) } # TIP#316 (Tcl_StatBuf reader functions) dkf declare 589 { unsigned Tcl_GetFSDeviceFromStat(const Tcl_StatBuf *statPtr) @@ -2237,23 +2237,23 @@ } declare 595 { int Tcl_GetDeviceTypeFromStat(const Tcl_StatBuf *statPtr) } declare 596 { - Tcl_WideInt Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr) + long long Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr) } declare 597 { - Tcl_WideInt Tcl_GetModificationTimeFromStat(const Tcl_StatBuf *statPtr) + long long Tcl_GetModificationTimeFromStat(const Tcl_StatBuf *statPtr) } declare 598 { - Tcl_WideInt Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr) + long long Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr) } declare 599 { - Tcl_WideUInt Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr) + unsigned long long Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr) } declare 600 { - Tcl_WideUInt Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr) + unsigned long long Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr) } declare 601 { unsigned Tcl_GetBlockSizeFromStat(const Tcl_StatBuf *statPtr) } @@ -2267,12 +2267,12 @@ Tcl_Obj **paramListPtr) } # TIP#265 (option parser) dkf for Sam Bromley declare 604 { - int Tcl_ParseArgsObjv(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, - int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv) + int TclParseArgsObjv(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, + void *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv) } # TIP#336 (manipulate the error line) dgp declare 605 { int Tcl_GetErrorLine(Tcl_Interp *interp) @@ -2302,19 +2302,19 @@ int Tcl_ZlibDeflate(Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj) } declare 611 { int Tcl_ZlibInflate(Tcl_Interp *interp, int format, Tcl_Obj *data, - size_t buffersize, Tcl_Obj *gzipHeaderDictObj) + Tcl_Size buffersize, Tcl_Obj *gzipHeaderDictObj) } declare 612 { unsigned int Tcl_ZlibCRC32(unsigned int crc, const unsigned char *buf, - size_t len) + Tcl_Size len) } declare 613 { unsigned int Tcl_ZlibAdler32(unsigned int adler, const unsigned char *buf, - size_t len) + Tcl_Size len) } declare 614 { int Tcl_ZlibStreamInit(Tcl_Interp *interp, int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle) } @@ -2330,11 +2330,11 @@ declare 618 { int Tcl_ZlibStreamPut(Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush) } declare 619 { int Tcl_ZlibStreamGet(Tcl_ZlibStream zshandle, Tcl_Obj *data, - size_t count) + Tcl_Size count) } declare 620 { int Tcl_ZlibStreamClose(Tcl_ZlibStream zshandle) } declare 621 { @@ -2384,47 +2384,47 @@ Tcl_Obj *compressionDictionaryObj) } # ----- BASELINE -- FOR -- 8.6.0 ----- # -# TIP #456 +# TIP #456/#468 declare 631 { Tcl_Channel Tcl_OpenTcpServerEx(Tcl_Interp *interp, const char *service, - const char *host, unsigned int flags, Tcl_TcpAcceptProc *acceptProc, - void *callbackData) + const char *host, unsigned int flags, int backlog, + Tcl_TcpAcceptProc *acceptProc, void *callbackData) } # TIP #430 declare 632 { - int TclZipfs_Mount(Tcl_Interp *interp, const char *mountPoint, - const char *zipname, const char *passwd) + int TclZipfs_Mount(Tcl_Interp *interp, const char *zipname, + const char *mountPoint, const char *passwd) } declare 633 { int TclZipfs_Unmount(Tcl_Interp *interp, const char *mountPoint) } declare 634 { Tcl_Obj *TclZipfs_TclLibrary(void) } declare 635 { - int TclZipfs_MountBuffer(Tcl_Interp *interp, const char *mountPoint, - unsigned char *data, size_t datalen, int copy) + int TclZipfs_MountBuffer(Tcl_Interp *interp, const void *data, + size_t datalen, const char *mountPoint, int copy) } # TIP #445 declare 636 { - void Tcl_FreeIntRep(Tcl_Obj *objPtr) + void Tcl_FreeInternalRep(Tcl_Obj *objPtr) } declare 637 { char *Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes, - size_t numBytes) + TCL_HASH_TYPE numBytes) } declare 638 { - Tcl_ObjIntRep *Tcl_FetchIntRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr) + Tcl_ObjInternalRep *Tcl_FetchInternalRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr) } declare 639 { - void Tcl_StoreIntRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, - const Tcl_ObjIntRep *irPtr) + void Tcl_StoreInternalRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, + const Tcl_ObjInternalRep *irPtr) } declare 640 { int Tcl_HasStringRep(Tcl_Obj *objPtr) } @@ -2442,32 +2442,199 @@ } # TIP#312 New Tcl_LinkArray() function declare 644 { int Tcl_LinkArray(Tcl_Interp *interp, const char *varName, void *addr, - int type, size_t size) + int type, Tcl_Size size) } declare 645 { int Tcl_GetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, - size_t endValue, size_t *indexPtr) + Tcl_Size endValue, Tcl_Size *indexPtr) } # TIP #548 declare 646 { - int Tcl_UtfToUniChar(const char *src, int *chPtr) + Tcl_Size Tcl_UtfToUniChar(const char *src, int *chPtr) } declare 647 { char *Tcl_UniCharToUtfDString(const int *uniStr, - size_t uniLength, Tcl_DString *dsPtr) + Tcl_Size uniLength, Tcl_DString *dsPtr) } declare 648 { int *Tcl_UtfToUniCharDString(const char *src, - size_t length, Tcl_DString *dsPtr) + Tcl_Size length, Tcl_DString *dsPtr) +} + +# TIP #568 +declare 649 { + unsigned char *TclGetBytesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, + void *numBytesPtr) +} +declare 650 { + unsigned char *Tcl_GetBytesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, + Tcl_Size *numBytesPtr) +} + +# TIP #481 +declare 651 { + char *Tcl_GetStringFromObj(Tcl_Obj *objPtr, Tcl_Size *lengthPtr) +} +declare 652 { + Tcl_UniChar *Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, Tcl_Size *lengthPtr) +} + +# TIP 660 +declare 653 { + int Tcl_GetSizeIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, + Tcl_Size *sizePtr) +} + +# TIP #575 +declare 654 { + int Tcl_UtfCharComplete(const char *src, Tcl_Size length) +} +declare 655 { + const char *Tcl_UtfNext(const char *src) +} +declare 656 { + const char *Tcl_UtfPrev(const char *src, const char *start) +} +declare 657 { + int Tcl_UniCharIsUnicode(int ch) +} + +# 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) } -# ----- BASELINE -- FOR -- 8.7.0 ----- # +# ----- 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. @@ -2477,56 +2644,47 @@ ################################ # 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 + +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) +} ################################ -# 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) +# Windows specific functions +declare 3 { + void Tcl_WinConvertError(unsigned errCode) } ############################################################################## # Public functions that are not accessible via the stubs table. export { - void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, + void Tcl_MainEx(Tcl_Size argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp) } export { - void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName, - Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc) + void Tcl_StaticLibrary(Tcl_Interp *interp, const char *prefix, + Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc) } export { - void Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc) + const char *Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc) } export { Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc) } export { - void Tcl_FindExecutable(const char *argv0) + const char *Tcl_FindExecutable(const char *argv0) } export { const char *Tcl_InitStubs(Tcl_Interp *interp, const char *version, int exact) } @@ -2540,11 +2698,15 @@ } export { void Tcl_GetMemoryInfo(Tcl_DString *dsPtr) } export { - void Tcl_InitSubsystems(void) + const char *Tcl_InitSubsystems(void) +} +export { + const char *TclZipfs_AppHook(int *argc, char ***argv) } + # Local Variables: # mode: tcl # End: Index: generic/tcl.h ================================================================== --- generic/tcl.h +++ generic/tcl.h @@ -43,20 +43,23 @@ * 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 +#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_ALPHA_RELEASE +# define TCL_RELEASE_SERIAL 4 -#define TCL_VERSION "9.0" -#define TCL_PATCH_LEVEL "9.0a2" +# define TCL_VERSION "9.0" +# define TCL_PATCH_LEVEL "9.0a4" +#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. @@ -98,19 +101,24 @@ * should, so also for their sake, we keep the #include to be consistent with * prior Tcl releases. */ #include +#include #if defined(__GNUC__) && (__GNUC__ > 2) -# define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b))) +# 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) && (_MSC_VER >= 1310) +# if defined(_MSC_VER) # define TCL_NORETURN _declspec(noreturn) # define TCL_NOINLINE __declspec(noinline) # else # define TCL_NORETURN /* nothing */ # define TCL_NOINLINE /* nothing */ @@ -147,12 +155,11 @@ * correctly decorate the C library imported function. Use CRTIMPORT * for this purpose. _DLL is defined by the compiler when linking to * MSVCRT. */ -#if (defined(_WIN32) && (defined(_MSC_VER) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0550)) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec)))) -# define HAVE_DECLSPEC 1 +#ifdef _WIN32 # ifdef STATIC_BUILD # define DLLIMPORT # define DLLEXPORT # ifdef _DLL # define CRTIMPORT __declspec(dllimport) @@ -230,20 +237,25 @@ * configure runs only once for multiple architectures): */ #ifdef __APPLE__ # ifdef __LP64__ -# undef TCL_WIDE_INT_TYPE # define TCL_WIDE_INT_IS_LONG 1 # define TCL_CFG_DO64BIT 1 # else /* !__LP64__ */ -# define TCL_WIDE_INT_TYPE long long # undef TCL_WIDE_INT_IS_LONG # undef TCL_CFG_DO64BIT # endif /* __LP64__ */ # undef HAVE_STRUCT_STAT64 #endif /* __APPLE__ */ + +/* Cross-compiling 32-bit on a 64-bit platform? Then our + * configure script does the wrong thing. Correct that here. + */ +#if defined(__GNUC__) && !defined(_WIN32) && !defined(__LP64__) +# undef TCL_WIDE_INT_IS_LONG +#endif /* * Define Tcl_WideInt to be a type that is (at least) 64-bits wide, and define * Tcl_WideUInt to be the unsigned variant of that type (assuming that where * we have one, we can have the other.) @@ -256,114 +268,115 @@ * 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__ */ +#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 -# 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 */ +# include +# 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 -# define TCL_LL_MODIFIER "ll" +# 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 defined(_WIN32) - typedef struct __stat64 Tcl_StatBuf; +#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 ((ptrdiff_t)(((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 { - dev_t st_dev; + unsigned st_dev; unsigned short st_ino; unsigned short st_mode; short st_nlink; short st_uid; short st_gid; /* Here is a 2-byte gap */ - dev_t st_rdev; + unsigned st_rdev; /* Here is a 4-byte gap */ long long st_size; - struct {long long tv_sec;} st_atim; - struct {long long tv_sec;} st_mtim; - struct {long long tv_sec;} st_ctim; + struct {long tv_sec;} st_atim; + struct {long tv_sec;} st_mtim; + struct {long tv_sec;} st_ctim; } Tcl_StatBuf; -#elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__) - typedef struct stat64 Tcl_StatBuf; #else typedef struct stat Tcl_StatBuf; #endif /* *---------------------------------------------------------------------------- * Data structures defined opaquely in this module. The definitions below just - * provide dummy types. A few fields are made visible in Tcl_Interp - * 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(). + * provide dummy types. */ -typedef struct Tcl_Interp Tcl_Interp; - typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler; typedef struct Tcl_Channel_ *Tcl_Channel; typedef struct Tcl_ChannelTypeVersion_ *Tcl_ChannelTypeVersion; typedef struct Tcl_Command_ *Tcl_Command; typedef struct Tcl_Condition_ *Tcl_Condition; typedef struct Tcl_Dict_ *Tcl_Dict; typedef struct Tcl_EncodingState_ *Tcl_EncodingState; typedef struct Tcl_Encoding_ *Tcl_Encoding; typedef struct Tcl_Event Tcl_Event; +typedef struct Tcl_Interp Tcl_Interp; typedef struct Tcl_InterpState_ *Tcl_InterpState; typedef struct Tcl_LoadHandle_ *Tcl_LoadHandle; typedef struct Tcl_Mutex_ *Tcl_Mutex; typedef struct Tcl_Pid_ *Tcl_Pid; typedef struct Tcl_RegExp_ *Tcl_RegExp; @@ -448,22 +461,32 @@ * 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 +#if TCL_MAJOR_VERSION > 8 + Tcl_Size start; /* Character offset of first character in * match. */ - size_t end; /* Character offset of first character after + Tcl_Size end; /* Character offset of first character after * the match. */ +#else + long start; + long end; +#endif } Tcl_RegExpIndices; typedef struct Tcl_RegExpInfo { - size_t nsubs; /* Number of subexpressions in the compiled + Tcl_Size nsubs; /* Number of subexpressions in the compiled * expression. */ Tcl_RegExpIndices *matches; /* Array of nsubs match offset pairs. */ - size_t extendStart; /* The offset at which a subsequent match +#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. @@ -533,10 +556,17 @@ int level, char *command, Tcl_CmdProc *proc, void *cmdClientData, int argc, const char *argv[]); typedef int (Tcl_CmdObjTraceProc) (void *clientData, Tcl_Interp *interp, int level, const char *command, Tcl_Command commandInfo, int objc, struct Tcl_Obj *const *objv); +#if TCL_MAJOR_VERSION > 8 +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); +#else +#define Tcl_CmdObjTraceProc2 Tcl_CmdObjTraceProc +#endif 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, @@ -555,12 +585,18 @@ 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); +#if TCL_MAJOR_VERSION > 8 +typedef int (Tcl_ObjCmdProc2) (void *clientData, Tcl_Interp *interp, + Tcl_Size objc, struct Tcl_Obj *const *objv); +#else +#define Tcl_ObjCmdProc2 Tcl_ObjCmdProc +#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); @@ -575,11 +611,38 @@ 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. @@ -599,20 +662,53 @@ * 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 (intrep) for - * a Tcl value. An intrep is associated with an Tcl_ObjType when both + * The following structure stores an internal representation (internalrep) for + * a Tcl value. An internalrep is associated with an Tcl_ObjType when both * are stored in the same Tcl_Obj. The routines of the Tcl_ObjType govern - * the handling of the intrep. + * the handling of the internalrep. */ -typedef union Tcl_ObjIntRep { /* The internal representation: */ +typedef union Tcl_ObjInternalRep { /* The internal representation: */ long longValue; /* - an long integer value. */ double doubleValue; /* - a double-precision floating value. */ void *otherValuePtr; /* - another, type-specific value, */ /* not used internally any more. */ Tcl_WideInt wideValue; /* - an integer value >= 64bits */ @@ -622,20 +718,20 @@ } twoPtrValue; struct { /* - internal rep as a pointer and a long, */ void *ptr; /* not used internally any more. */ unsigned long value; } ptrAndLongRep; -} Tcl_ObjIntRep; +} Tcl_ObjInternalRep; /* * One of the following structures exists for each object in the Tcl system. * An object stores a value as either a string, some internal representation, * or both. */ typedef struct Tcl_Obj { - size_t refCount; /* When 0 the object will be freed. */ + Tcl_Size refCount; /* When 0 the object will be freed. */ char *bytes; /* This points to the first byte of the * object's string representation. The array * must be followed by a null byte (i.e., at * offset length) but may also contain * embedded null characters. The array's @@ -643,28 +739,19 @@ * the string rep is invalid and must be * regenerated from the internal rep. Clients * should use Tcl_GetStringFromObj or * Tcl_GetString to get a pointer to the byte * array as a readonly value. */ - size_t length; /* The number of bytes at *bytes, not + Tcl_Size length; /* The number of bytes at *bytes, not * including the terminating null. */ const Tcl_ObjType *typePtr; /* Denotes the object's type. Always * corresponds to the type of the object's * internal rep. NULL indicates the object has * no internal rep (has no type). */ - Tcl_ObjIntRep internalRep; /* The internal representation: */ + Tcl_ObjInternalRep 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). @@ -712,18 +799,18 @@ */ typedef struct Tcl_CallFrame { Tcl_Namespace *nsPtr; int dummy1; - int dummy2; + Tcl_Size dummy2; void *dummy3; void *dummy4; void *dummy5; - int dummy6; + Tcl_Size dummy6; void *dummy7; void *dummy8; - int dummy9; + Tcl_Size dummy9; void *dummy10; void *dummy11; void *dummy12; void *dummy13; } Tcl_CallFrame; @@ -741,15 +828,15 @@ * Tcl_CreateCommand. The other function is typically set to a compatibility * wrapper that does string-to-object or object-to-string argument conversions * then calls the other function. */ -typedef struct Tcl_CmdInfo { +typedef struct { int isNativeObjectProc; /* 1 if objProc was registered by a call to - * Tcl_CreateObjCommand; 0 otherwise. - * Tcl_SetCmdInfo does not modify this - * field. */ + * 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; @@ -760,10 +847,12 @@ 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 @@ -773,13 +862,13 @@ #define TCL_DSTRING_STATIC_SIZE 200 typedef struct Tcl_DString { char *string; /* Points to beginning of string: either * staticSpace below or a malloced array. */ - size_t length; /* Number of non-NULL characters in the - * string. */ - size_t spaceAvl; /* Total number of bytes available for the + Tcl_Size length; /* Number of bytes in string excluding + * terminating nul */ + Tcl_Size spaceAvl; /* Total number of bytes available for the * string and its terminating NULL char. */ char staticSpace[TCL_DSTRING_STATIC_SIZE]; /* Space to use in common case where string is * small. */ } Tcl_DString; @@ -800,11 +889,25 @@ * Definition for a number of bytes of buffer space sufficient to hold the * string representation of an integer in base 10 (assuming the existence of * 64-bit integers). */ -#define TCL_INTEGER_SPACE 24 +#define TCL_INTEGER_SPACE (3*(int)sizeof(Tcl_WideInt)) + +/* + *---------------------------------------------------------------------------- + * Type values returned by Tcl_GetNumberFromObj + * TCL_NUMBER_INT Representation is a Tcl_WideInt + * TCL_NUMBER_BIG Representation is an mp_int + * TCL_NUMBER_DOUBLE Representation is a double + * TCL_NUMBER_NAN Value is NaN. + */ + +#define TCL_NUMBER_INT 2 +#define TCL_NUMBER_BIG 3 +#define TCL_NUMBER_DOUBLE 4 +#define TCL_NUMBER_NAN 5 /* * Flag values passed to Tcl_ConvertElement. * TCL_DONT_USE_BRACES forces it not to enclose the element in braces, but to * use backslash quoting instead. @@ -818,17 +921,30 @@ #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_INDEX_TEMP_TABLE 2 +#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! @@ -880,14 +996,10 @@ #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 /* @@ -931,18 +1043,22 @@ #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; @@ -961,11 +1077,11 @@ 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 + 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 @@ -1049,20 +1165,25 @@ * points to first entry in bucket's hash * chain, or NULL. */ Tcl_HashEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; /* Bucket array used for small tables (to * avoid mallocs and frees). */ - size_t numBuckets; /* Total number of buckets allocated at + Tcl_Size numBuckets; /* Total number of buckets allocated at * **bucketPtr. */ - size_t numEntries; /* Total number of entries present in + Tcl_Size numEntries; /* Total number of entries present in * table. */ - size_t rebuildSize; /* Enlarge table when numEntries gets to be + Tcl_Size rebuildSize; /* Enlarge table when numEntries gets to be * this large. */ +#if TCL_MAJOR_VERSION > 8 size_t mask; /* Mask value used in hashing function. */ +#endif int downShift; /* Shift count used in hashing function. * Designed to use high-order bits of * randomized keys. */ +#if TCL_MAJOR_VERSION < 9 + int mask; /* Mask value used in hashing function. */ +#endif int keyType; /* Type of keys used in this table. It's * either TCL_CUSTOM_KEYS, TCL_STRING_KEYS, * TCL_ONE_WORD_KEYS, or an integer giving the * number of ints that is the size of the * key. */ @@ -1079,11 +1200,11 @@ * hash tables: */ typedef struct Tcl_HashSearch { Tcl_HashTable *tablePtr; /* Table being searched. */ - size_t nextIndex; /* Index of next bucket to be enumerated after + Tcl_Size nextIndex; /* Index of next bucket to be enumerated after * present one. */ Tcl_HashEntry *nextEntryPtr;/* Next entry to be enumerated in the current * bucket. */ } Tcl_HashSearch; @@ -1120,11 +1241,11 @@ */ typedef struct { void *next; /* Search position for underlying hash * table. */ - size_t epoch; /* Epoch marker for dictionary being searched, + TCL_HASH_TYPE epoch; /* Epoch marker for dictionary being searched, * or 0 if search has terminated. */ Tcl_Dict dictionaryPtr; /* Reference to dictionary being searched. */ } Tcl_DictSearch; /* @@ -1153,15 +1274,16 @@ Tcl_EventProc *proc; /* Function to call to service this event. */ struct Tcl_Event *nextPtr; /* Next in list of pending events, or NULL. */ }; /* - * Positions to pass to Tcl_QueueEvent: + * Positions to pass to Tcl_QueueEvent/Tcl_ThreadQueueEvent: */ typedef enum { - TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK + TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK, + TCL_QUEUE_ALERT_IF_EMPTY=4 } Tcl_QueuePosition; /* * Values to pass to Tcl_SetServiceMode to specify the behavior of notifier * event routines. @@ -1175,12 +1297,20 @@ * 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); @@ -1223,11 +1353,15 @@ /* * Value to use as the closeProc for a channel that supports the close2Proc * interface. */ -#define TCL_CLOSE2PROC NULL +#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. */ @@ -1263,22 +1397,22 @@ typedef int (Tcl_DriverGetHandleProc) (void *instanceData, int direction, void **handlePtr); typedef int (Tcl_DriverFlushProc) (void *instanceData); typedef int (Tcl_DriverHandlerProc) (void *instanceData, int interestMask); -typedef Tcl_WideInt (Tcl_DriverWideSeekProc) (void *instanceData, - Tcl_WideInt offset, int mode, int *errorCodePtr); +typedef long long (Tcl_DriverWideSeekProc) (void *instanceData, + long long offset, int mode, int *errorCodePtr); /* * TIP #218, Channel Thread Actions */ typedef void (Tcl_DriverThreadActionProc) (void *instanceData, int action); /* * TIP #208, File Truncation (etc.) */ typedef int (Tcl_DriverTruncateProc) (void *instanceData, - Tcl_WideInt length); + long long length); /* * struct Tcl_ChannelType: * * One such structure exists for each type (kind) of channel. It collects @@ -1474,11 +1608,11 @@ * explanations in the structure show the importance of each function. */ typedef struct Tcl_Filesystem { const char *typeName; /* The name of the filesystem. */ - size_t structureLength; /* Length of this structure, so future binary + Tcl_Size structureLength; /* Length of this structure, so future binary * compatibility can be assured. */ Tcl_FSVersion version; /* Version of the filesystem type. */ Tcl_FSPathInFilesystemProc *pathInFilesystemProc; /* Determines whether the pathname is in this * filesystem. This is the most important @@ -1636,12 +1770,12 @@ typedef struct Tcl_Token { int type; /* Type of token, such as TCL_TOKEN_WORD; see * below for valid types. */ const char *start; /* First character in token. */ - size_t size; /* Number of bytes in token. */ - size_t numComponents; /* If this token is composed of other tokens, + Tcl_Size size; /* Number of bytes in token. */ + Tcl_Size numComponents; /* If this token is composed of other tokens, * this field tells how many of them there are * (including components of components, etc.). * The component tokens immediately follow * this one. */ } Tcl_Token; @@ -1703,11 +1837,11 @@ * the operator, then TCL_TOKEN_SUB_EXPR tokens * for the left then the right operands. * TCL_TOKEN_OPERATOR - The token describes one expression operator. * An operator might be the name of a math * function such as "abs". A TCL_TOKEN_OPERATOR - * token is always preceeded by one + * token is always preceded by one * TCL_TOKEN_SUB_EXPR token for the operator's * subexpression, and is followed by zero or more * TCL_TOKEN_SUB_EXPR tokens for the operator's * operands. NumComponents is always 0. * TCL_TOKEN_EXPAND_WORD - This token is just like TCL_TOKEN_WORD except @@ -1751,32 +1885,38 @@ #define NUM_STATIC_TOKENS 20 typedef struct Tcl_Parse { const char *commentStart; /* Pointer to # that begins the first of one * or more comments preceding the command. */ - size_t commentSize; /* Number of bytes in comments (up through + Tcl_Size commentSize; /* Number of bytes in comments (up through * newline character that terminates the last * comment). If there were no comments, this * field is 0. */ const char *commandStart; /* First character in first word of * command. */ - int commandSize; /* Number of bytes in command, including first + Tcl_Size commandSize; /* Number of bytes in command, including first * character of first word, up through the * terminating newline, close bracket, or * semicolon. */ - int numWords; /* Total number of words in command. May be + Tcl_Size numWords; /* Total number of words in command. May be * 0. */ Tcl_Token *tokenPtr; /* Pointer to first token representing the * words of the command. Initially points to * staticTokens, but may change to point to * malloc-ed space if command exceeds space in * staticTokens. */ - int numTokens; /* Total number of tokens in command. */ - int tokensAvailable; /* Total number of tokens available at + Tcl_Size numTokens; /* Total number of tokens in command. */ + Tcl_Size tokensAvailable; /* Total number of tokens available at * *tokenPtr. */ int errorType; /* One of the parsing error types defined * above. */ +#if TCL_MAJOR_VERSION > 8 + int incomplete; /* This field is set to 1 by Tcl_ParseCommand + * if the command appears to be incomplete. + * This information is used by + * Tcl_CommandComplete. */ +#endif /* * The fields below are intended only for the private use of the parser. * They should not be used by functions that invoke Tcl_ParseCommand. */ @@ -1791,14 +1931,13 @@ * 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. */ +#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 @@ -1824,15 +1963,15 @@ 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 + Tcl_Size nullSize; /* Number of zero bytes that signify * end-of-string in this encoding. This number * is used to determine the source string * length when the srcLen argument is - * negative. Must be 1 or 2. */ + * negative. Must be 1, 2, or 4. */ } Tcl_EncodingType; /* * The following definitions are used as values for the conversion control * flags argument when converting text from one character set to another: @@ -1851,18 +1990,11 @@ * 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_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 @@ -1873,17 +2005,42 @@ * *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 -#define TCL_ENCODING_STOPONERROR 0x04 +#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_TCL8 0x01000000 +#define TCL_ENCODING_PROFILE_STRICT 0x02000000 +#define TCL_ENCODING_PROFILE_REPLACE 0x03000000 +#if TCL_MAJOR_VERSION < 9 +#define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_TCL8 +#else +#define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_TCL8 +#endif /* * The following definitions are the error codes returned by the conversion * routines: * @@ -1900,51 +2057,53 @@ * 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. + * encoding method was misidentified. * 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. + * 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 - * (or perhaps 1 if we want to support a non-unicode enabled core). If > 3, + * 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 -#define TCL_UTF_MAX 4 +# 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 > 3 +#if TCL_UTF_MAX == 4 /* * int isn't 100% accurate as it should be a strict 4-byte value - * (perhaps wchar_t). ILP64/SILP64 systems may have troubles. The + * (perhaps int32_t). ILP64/SILP64 systems may have troubles. The * size of this value must be reflected correctly in regcustom.h. */ typedef int Tcl_UniChar; -#else +#elif TCL_UTF_MAX == 3 && !defined(BUILD_tcl) typedef unsigned short Tcl_UniChar; +#else +# error "This TCL_UTF_MAX value is not supported" #endif /* *---------------------------------------------------------------------------- * TIP #59: The following structure is used in calls 'Tcl_RegisterConfig' to @@ -1971,11 +2130,15 @@ * 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 @@ -2107,16 +2270,16 @@ */ #define TCL_TCPSERVER_REUSEADDR (1<<0) #define TCL_TCPSERVER_REUSEPORT (1<<1) /* - * Constants for special size_t-typed values, see TIP #494 + * Constants for special Tcl_Size-typed values, see TIP #494 */ -#define TCL_IO_FAILURE ((size_t)-1) -#define TCL_AUTO_LENGTH ((size_t)-1) -#define TCL_INDEX_NONE ((size_t)-1) +#define TCL_IO_FAILURE ((Tcl_Size)-1) +#define TCL_AUTO_LENGTH ((Tcl_Size)-1) +#define TCL_INDEX_NONE ((Tcl_Size)-1) /* *---------------------------------------------------------------------------- * Single public declaration for NRE. */ @@ -2128,11 +2291,15 @@ *---------------------------------------------------------------------------- * 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 *)) +#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 @@ -2141,18 +2308,32 @@ 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_RELEASE_LEVEL == TCL_FINAL_RELEASE +#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 @@ -2160,11 +2341,13 @@ (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 +#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) \ @@ -2177,29 +2360,68 @@ * 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_SetPanicProc(Tcl_ConsolePanic), Tcl_CreateInterp()))) +EXTERN TCL_NORETURN void Tcl_MainEx(Tcl_Size argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp, const char *version, int exact); -EXTERN void Tcl_InitSubsystems(void); +EXTERN const char * Tcl_InitSubsystems(void); EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr); -EXTERN void Tcl_FindExecutable(const char *argv0); -EXTERN void Tcl_SetPanicProc( +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_StaticPackage(Tcl_Interp *interp, - const char *pkgName, - Tcl_PackageInitProc *initProc, - Tcl_PackageInitProc *safeInitProc); +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 int TclZipfs_AppHook(int *argc, wchar_t ***argv); +EXTERN const char *TclZipfs_AppHook(int *argc, wchar_t ***argv); #else -EXTERN int TclZipfs_AppHook(int *argc, char ***argv); +EXTERN const char *TclZipfs_AppHook(int *argc, char ***argv); +#endif +#if defined(_WIN32) && defined(UNICODE) +#ifndef USE_TCL_STUBS +# define Tcl_FindExecutable(arg) ((Tcl_FindExecutable)((const char *)(arg))) +#endif +# define Tcl_MainEx Tcl_MainExW + EXTERN TCL_NORETURN void Tcl_MainExW(Tcl_Size argc, wchar_t **argv, + Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); +#endif +#if defined(USE_TCL_STUBS) && (TCL_MAJOR_VERSION > 8) +#define Tcl_SetPanicProc(panicProc) \ + TclInitStubTable(((const char *(*)(Tcl_PanicProc *))TclStubCall((void *)panicProc))(panicProc)) +#define Tcl_InitSubsystems() \ + TclInitStubTable(((const char *(*)(void))TclStubCall((void *)1))()) +#define Tcl_FindExecutable(argv0) \ + TclInitStubTable(((const char *(*)(const char *))TclStubCall((void *)2))(argv0)) +#define TclZipfs_AppHook(argcp, argvp) \ + TclInitStubTable(((const char *(*)(int *, void *))TclStubCall((void *)3))(argcp, argvp)) +#define Tcl_MainExW(argc, argv, appInitProc, interp) \ + (void)((const char *(*)(Tcl_Size, const void *, Tcl_AppInitProc *, Tcl_Interp *)) \ + TclStubCall((void *)4))(argc, argv, appInitProc, interp) +#if !defined(_WIN32) || !defined(UNICODE) +#define Tcl_MainEx(argc, argv, appInitProc, interp) \ + (void)((const char *(*)(Tcl_Size, const void *, Tcl_AppInitProc *, Tcl_Interp *)) \ + TclStubCall((void *)5))(argc, argv, appInitProc, interp) +#endif +#define Tcl_StaticLibrary(interp, pkgName, initProc, safeInitProc) \ + (void)((const char *(*)(Tcl_Interp *, const char *, Tcl_LibraryInitProc *, Tcl_LibraryInitProc *)) \ + TclStubCall((void *)6))(interp, pkgName, initProc, safeInitProc) +#define Tcl_SetExitProc(proc) \ + ((Tcl_ExitProc *(*)(Tcl_ExitProc *))TclStubCall((void *)7))(proc) +#define Tcl_GetMemoryInfo(dsPtr) \ + (void)((const char *(*)(Tcl_DString *))TclStubCall((void *)8))(dsPtr) +#define Tcl_SetPreInitScript(string) \ + ((const char *(*)(const char *))TclStubCall((void *)9))(string) #endif /* *---------------------------------------------------------------------------- * Include the public function declarations that are accessible via the stubs @@ -2230,13 +2452,13 @@ #ifndef BUILD_tcl # define ckalloc Tcl_Alloc # define attemptckalloc Tcl_AttemptAlloc # ifdef _MSC_VER /* Silence invalid C4090 warnings */ -# define ckfree(a) Tcl_Free((char *)(a)) -# define ckrealloc(a,b) Tcl_Realloc((char *)(a),(b)) -# define attemptckrealloc(a,b) Tcl_AttemptRealloc((char *)(a),(b)) +# define ckfree(a) Tcl_Free((void *)(a)) +# define ckrealloc(a,b) Tcl_Realloc((void *)(a),(b)) +# define attemptckrealloc(a,b) Tcl_AttemptRealloc((void *)(a),(b)) # else # define ckfree Tcl_Free # define ckrealloc Tcl_Realloc # define attemptckrealloc Tcl_AttemptRealloc # endif @@ -2267,17 +2489,36 @@ # define Tcl_DecrRefCount(objPtr) \ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__) # undef Tcl_IsShared # define Tcl_IsShared(objPtr) \ Tcl_DbIsShared(objPtr, __FILE__, __LINE__) +/* + * Free the Obj by effectively doing: + * + * Tcl_IncrRefCount(objPtr); + * Tcl_DecrRefCount(objPtr); + * + * This will free the obj if there are no references to the obj. + */ +# define Tcl_BounceRefCount(objPtr) \ + TclBounceRefCount(objPtr, __FILE__, __LINE__) + +static inline void TclBounceRefCount(Tcl_Obj* objPtr, const char* fn, int line) +{ + if (objPtr) { + if ((objPtr)->refCount == 0) { + Tcl_DbDecrRefCount(objPtr, fn, line); + } + } +} #else # undef Tcl_IncrRefCount # define Tcl_IncrRefCount(objPtr) \ - ++(objPtr)->refCount + ((void)++(objPtr)->refCount) /* * Use do/while0 idiom for optimum correctness without compiler warnings. - * http://c2.com/cgi/wiki?TrivialDoWhileLoop + * https://wiki.c2.com/?TrivialDoWhileLoop */ # undef Tcl_DecrRefCount # define Tcl_DecrRefCount(objPtr) \ do { \ Tcl_Obj *_objPtr = (objPtr); \ @@ -2286,10 +2527,28 @@ } \ } 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 @@ -2327,11 +2586,11 @@ *---------------------------------------------------------------------------- * Macros for clients to use to access fields of hash entries: */ #define Tcl_GetHashValue(h) ((h)->clientData) -#define Tcl_SetHashValue(h, value) ((h)->clientData = (void *) (value)) +#define Tcl_SetHashValue(h, value) ((h)->clientData = (void *)(value)) #define Tcl_GetHashKey(tablePtr, h) \ ((void *) (((tablePtr)->keyType == TCL_ONE_WORD_KEYS || \ (tablePtr)->keyType == TCL_CUSTOM_PTR_KEYS) \ ? (h)->key.oneWordValue \ : (h)->key.string)) @@ -2339,12 +2598,14 @@ /* * 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 */ Index: generic/tclAlloc.c ================================================================== --- generic/tclAlloc.c +++ generic/tclAlloc.c @@ -4,13 +4,13 @@ * This is a very fast storage allocator. It allocates blocks of a small * number of different sizes, and keeps free lists of each size. Blocks * that don't exactly fit are passed up to the next larger size. Blocks * over a certain size are directly allocated from the system. * - * Copyright (c) 1983 Regents of the University of California. - * Copyright (c) 1996-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1983 Regents of the University of California. + * Copyright © 1996-1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -29,11 +29,11 @@ /* * We should really make use of AC_CHECK_TYPE(caddr_t) here, but it can wait * until Tcl uses config.h properly. */ -#if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__) +#if defined(_MSC_VER) || defined(__MSVCRT__) typedef size_t caddr_t; #endif /* * The overhead on a block is at least 8 bytes. When free, this space contains @@ -92,11 +92,11 @@ * 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)) +#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 @@ -114,11 +114,11 @@ &bigBlocks, &bigBlocks }; /* * The allocator is protected by a special mutex that must be explicitly - * initialized. Futhermore, because Tcl_Alloc may be used before anything else + * initialized. Furthermore, because Tcl_Alloc may be used before anything else * in Tcl, we make this module self-initializing after all with the allocInit * variable. */ #if TCL_THREADS @@ -508,11 +508,11 @@ *---------------------------------------------------------------------- */ void * TclpRealloc( - void *oldPtr, /* Pointer to alloced block. */ + void *oldPtr, /* Pointer to alloc'ed block. */ size_t numBytes) /* New size of memory. */ { int i; union overhead *overPtr; struct block *bigBlockPtr; @@ -580,11 +580,11 @@ #endif Tcl_MutexUnlock(allocMutexPtr); return (void *)(overPtr+1); } - maxSize = 1 << (i+3); + maxSize = (size_t)1 << (i+3); expensive = 0; if (numBytes+OVERHEAD > maxSize) { expensive = 1; } else if (i>0 && numBytes+OVERHEAD < maxSize/2) { expensive = 1; @@ -607,11 +607,11 @@ TclpFree(oldPtr); return newPtr; } /* - * Ok, we don't have to copy, it fits as-is + * No need to copy. It fits as-is. */ #ifndef NDEBUG overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); BLOCK_END(overPtr) = RMAGIC; @@ -653,22 +653,22 @@ fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s); for (i = 0; i < NBUCKETS; i++) { for (j=0, overPtr=nextf[i]; overPtr; overPtr=overPtr->next, j++) { fprintf(stderr, " %u", j); } - totalFree += ((size_t)j) * (1 << (i + 3)); + totalFree += ((size_t)j) * ((size_t)1 << (i + 3)); } fprintf(stderr, "\nused:\t"); for (i = 0; i < NBUCKETS; i++) { fprintf(stderr, " %" TCL_Z_MODIFIER "u", numMallocs[i]); - totalUsed += numMallocs[i] * (1 << (i + 3)); + totalUsed += numMallocs[i] * ((size_t)1 << (i + 3)); } fprintf(stderr, "\n\tTotal small in use: %" TCL_Z_MODIFIER "u, total free: %" TCL_Z_MODIFIER "u\n", totalUsed, totalFree); - fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %" TCL_Z_MODIFIER "u\n", + fprintf(stderr, "\n\tNumber of big (>%" TCL_Z_MODIFIER "u) blocks in use: %" TCL_Z_MODIFIER "u\n", MAXMALLOC, numMallocs[NBUCKETS]); Tcl_MutexUnlock(allocMutexPtr); } #endif @@ -747,14 +747,16 @@ { 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 Index: generic/tclArithSeries.c ================================================================== --- /dev/null +++ generic/tclArithSeries.c @@ -0,0 +1,1205 @@ +/* + * 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 "tcl.h" +#include "tclInt.h" +#include +#include + +/* + * 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; + Tcl_WideInt start; + Tcl_WideInt end; + Tcl_WideInt step; +} ArithSeries; +typedef struct { + Tcl_Size len; + Tcl_Obj **elements; + int isDouble; + double start; + double end; + double step; + int precision; +} ArithSeriesDbl; + +/* -------------------------- ArithSeries object ---------------------------- */ + +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 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 + * + * - 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 +ArithRound(double d, unsigned int n) { + double scalefactor = pow(10, n); + return round(d*scalefactor)/scalefactor; +} + +static inline double +ArithSeriesIndexDbl( + ArithSeries *arithSeriesRepPtr, + Tcl_WideInt index) +{ + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; + if (arithSeriesRepPtr->isDouble) { + double d = dblRepPtr->start + (index * dblRepPtr->step); + unsigned n = (dblRepPtr->precision > 0 ? dblRepPtr->precision : 0); + return ArithRound(d, n); + } else { + return (double)(arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step)); + } +} + +static inline Tcl_WideInt +ArithSeriesIndexInt( + ArithSeries *arithSeriesRepPtr, + Tcl_WideInt index) +{ + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; + if (arithSeriesRepPtr->isDouble) { + return (Tcl_WideInt)(dblRepPtr->start + ((index) * dblRepPtr->step)); + } else { + return (arithSeriesRepPtr->start + (index * arithSeriesRepPtr->step)); + } +} + +static inline ArithSeries* +ArithSeriesGetInternalRep(Tcl_Obj *objPtr) +{ + const Tcl_ObjInternalRep *irPtr; + irPtr = TclFetchInternalRep((objPtr), &arithSeriesType); + return irPtr ? (ArithSeries *)irPtr->twoPtrValue.ptr1 : NULL; +} + +/* + * Compute number of significant factional digits + */ +static inline int +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 int +maxPrecision(double start, double end, double step) +{ + int dp = Precision(step); + int i = Precision(start); + dp = i>dp ? i : dp; + i = Precision(end); + dp = i>dp ? i : dp; + return dp; +} + +static int TclArithSeriesObjStep(Tcl_Obj *arithSeriesObj, Tcl_Obj **stepObj); + +/* + *---------------------------------------------------------------------- + * + * 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, int precision) +{ + double istart, iend, istep, ilen; + if (step == 0) { + return 0; + } + istart = start * pow(10,precision); + iend = end * pow(10,precision); + istep = step * pow(10,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. + * + * 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 *srcArithSeriesRepPtr = + (ArithSeries *) srcPtr->internalRep.twoPtrValue.ptr1; + /* + * Allocate a new ArithSeries structure. */ + + if (srcArithSeriesRepPtr->isDouble) { + ArithSeriesDbl *srcArithSeriesDblRepPtr = + (ArithSeriesDbl *)srcArithSeriesRepPtr; + ArithSeriesDbl *copyArithSeriesDblRepPtr = + (ArithSeriesDbl *) Tcl_Alloc(sizeof(ArithSeriesDbl)); + *copyArithSeriesDblRepPtr = *srcArithSeriesDblRepPtr; + copyArithSeriesDblRepPtr->elements = NULL; + copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesDblRepPtr; + } else { + ArithSeries *copyArithSeriesRepPtr = + (ArithSeries *) Tcl_Alloc(sizeof(ArithSeries)); + *copyArithSeriesRepPtr = *srcArithSeriesRepPtr; + copyArithSeriesRepPtr->elements = NULL; + copyPtr->internalRep.twoPtrValue.ptr1 = copyArithSeriesRepPtr; + } + copyPtr->internalRep.twoPtrValue.ptr2 = NULL; + copyPtr->typePtr = &arithSeriesType; +} + +/* + *---------------------------------------------------------------------- + * + * FreeArithSeriesInternalRep -- + * + * Free any allocated memory in the ArithSeries Rep + * + * Results: + * None. + * + * Side effects: + * + *---------------------------------------------------------------------- + */ +static void +FreeArithSeriesInternalRep(Tcl_Obj *arithSeriesObjPtr) /* Free any allocated memory */ +{ + ArithSeries *arithSeriesRepPtr = (ArithSeries*)arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; + + if (arithSeriesRepPtr) { + if (arithSeriesRepPtr->elements) { + Tcl_WideInt i, len = arithSeriesRepPtr->len; + for (i=0; ielements[i]); + } + Tcl_Free((char*)arithSeriesRepPtr->elements); + arithSeriesRepPtr->elements = NULL; + } + 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; + ArithSeries *arithSeriesRepPtr; + + length = len>=0 ? len : -1; + if (length < 0) length = -1; + + TclNewObj(arithSeriesObj); + + if (length <= 0) { + return arithSeriesObj; + } + + arithSeriesRepPtr = (ArithSeries*) Tcl_Alloc(sizeof (ArithSeries)); + arithSeriesRepPtr->isDouble = 0; + arithSeriesRepPtr->start = start; + arithSeriesRepPtr->end = end; + arithSeriesRepPtr->step = step; + arithSeriesRepPtr->len = length; + arithSeriesRepPtr->elements = NULL; + 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->isDouble = 1; + arithSeriesRepPtr->start = start; + arithSeriesRepPtr->end = end; + arithSeriesRepPtr->step = step; + arithSeriesRepPtr->len = length; + arithSeriesRepPtr->elements = NULL; + 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) { + int precision = maxPrecision(dstart,dend,dstep); + len = ArithSeriesLenDbl(dstart, dend, dstep, precision); + } else { + len = ArithSeriesLenInt(start, end, step); + } + } + } + + if (!endObj) { + if (useDoubles) { + dend = dstart + (dstep * (len-1)); + 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", -1)); + 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 *),/* Used for error reporting if not NULL. */ + 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(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 *arithSeriesDblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; + double start, end, step; + + Tcl_GetDoubleFromObj(NULL, startObj, &start); + Tcl_GetDoubleFromObj(NULL, endObj, &end); + Tcl_GetDoubleFromObj(NULL, stepObj, &step); + arithSeriesDblRepPtr->start = start; + arithSeriesDblRepPtr->end = end; + arithSeriesDblRepPtr->step = step; + arithSeriesDblRepPtr->precision = maxPrecision(start, end, step); + arithSeriesDblRepPtr->len = + ArithSeriesLenDbl(start, end, step, arithSeriesDblRepPtr->precision); + arithSeriesDblRepPtr->elements = NULL; + + } else { + Tcl_WideInt start, end, step; + Tcl_GetWideIntFromObj(NULL, startObj, &start); + Tcl_GetWideIntFromObj(NULL, endObj, &end); + Tcl_GetWideIntFromObj(NULL, stepObj, &step); + arithSeriesRepPtr->start = start; + arithSeriesRepPtr->end = end; + arithSeriesRepPtr->step = step; + arithSeriesRepPtr->len = ArithSeriesLenInt(start, end, step); + arithSeriesRepPtr->elements = NULL; + } + + 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; + Tcl_Obj **objv; + int i, objc; + + arithSeriesRepPtr = ArithSeriesGetInternalRep(objPtr); + + 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", -1)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); + } + return TCL_ERROR; + } + arithSeriesRepPtr->elements = objv; + 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_ObjPrintf("value is not an arithseries")); + 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 *arithSeriesDblRepPtr = + (ArithSeriesDbl*)arithSeriesRepPtr; + arithSeriesDblRepPtr->start = dstart; + arithSeriesDblRepPtr->end = dend; + arithSeriesDblRepPtr->step = dstep; + } else { + arithSeriesRepPtr->start = start; + arithSeriesRepPtr->end = end; + arithSeriesRepPtr->step = step; + } + if (arithSeriesRepPtr->elements) { + Tcl_WideInt i; + for (i=0; ielements[i]); + } + Tcl_Free((char*)arithSeriesRepPtr->elements); + } + arithSeriesRepPtr->elements = NULL; + + 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 = ArithSeriesIndexDbl(arithSeriesRepPtr, i); + size_t slen = d>0 ? log10(d)+1 : d<0 ? log10((0-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 = Tcl_GetStringFromObj(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 *arithSeriesRepPtr = (ArithSeries*)arithSeriesObjPtr->internalRep.twoPtrValue.ptr1; + ArithSeriesDbl *dblRepPtr = (ArithSeriesDbl*)arithSeriesRepPtr; + int status; + Tcl_Size index, incr, elen, vlen; + + if (arithSeriesRepPtr->isDouble) { + 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 = Tcl_GetStringFromObj(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 ? Tcl_GetStringFromObj(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 { + ArithSeries *intRepPtr = arithSeriesRepPtr; + 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 = Tcl_GetStringFromObj(valueObj, &vlen); + char const *estr = elemObj ? Tcl_GetStringFromObj(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: + */ Index: generic/tclAssembly.c ================================================================== --- generic/tclAssembly.c +++ generic/tclAssembly.c @@ -4,12 +4,12 @@ * Assembler for Tcl bytecodes. * * This file contains the procedures that convert Tcl Assembly Language (TAL) * to a sequence of bytecode instructions for the Tcl execution engine. * - * Copyright (c) 2010 by Ozgur Dogan Ugurlu. - * Copyright (c) 2010 by Kevin B. Kenny. + * Copyright © 2010 Ozgur Dogan Ugurlu. + * Copyright © 2010 Kevin B. Kenny. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -220,13 +220,13 @@ * generation */ Tcl_Parse* parsePtr; /* Parse of the current line of source */ Tcl_HashTable labelHash; /* Hash table whose keys are labels and whose * values are 'label' objects storing the code * offsets of the labels. */ - int cmdLine; /* Current line number within the assembly + Tcl_Size cmdLine; /* Current line number within the assembly * code */ - int* clNext; /* Invisible continuation line for + Tcl_Size* clNext; /* Invisible continuation line for * [info frame] */ BasicBlock* head_bb; /* First basic block in the code */ BasicBlock* curr_bb; /* Current basic block */ int maxDepth; /* Maximum stack depth encountered */ int curCatchDepth; /* Current depth of catches */ @@ -275,11 +275,11 @@ static int DefineLabel(AssemblyEnv* envPtr, const char* label); static void DeleteMirrorJumpTable(JumptableInfo* jtPtr); static void FillInJumpOffsets(AssemblyEnv*); static int CreateMirrorJumpTable(AssemblyEnv* assemEnvPtr, Tcl_Obj* jumpTable); -static int FindLocalVar(AssemblyEnv* envPtr, +static size_t FindLocalVar(AssemblyEnv* envPtr, Tcl_Token** tokenPtrPtr); static int FinishAssembly(AssemblyEnv*); static void FreeAssemblyEnv(AssemblyEnv*); static int GetBooleanOperand(AssemblyEnv*, Tcl_Token**, int*); static int GetListIndexOperand(AssemblyEnv*, Tcl_Token**, int*); @@ -323,11 +323,12 @@ static const Tcl_ObjType assembleCodeType = { "assemblecode", FreeAssembleCodeInternalRep, /* freeIntRepProc */ DupAssembleCodeInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - NULL /* setFromAnyProc */ + NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; /* * Source instructions recognized in the Tcl Assembly Language (TAL) */ @@ -768,11 +769,11 @@ *----------------------------------------------------------------------------- */ int Tcl_AssembleObjCmd( - ClientData clientData, /* clientData */ + void *clientData, /* clientData */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { /* @@ -783,11 +784,11 @@ return Tcl_NRCallObjProc(interp, TclNRAssembleObjCmd, clientData, objc, objv); } int TclNRAssembleObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { ByteCode *codePtr; /* Pointer to the bytecode to execute */ @@ -854,18 +855,18 @@ /* Bytecode resulting from the assembly */ Namespace* namespacePtr; /* Namespace in which variable and command * names in the bytecode resolve */ int status; /* Status return from Tcl_AssembleCode */ const char* source; /* String representation of the source code */ - size_t sourceLen; /* Length of the source code in bytes */ + Tcl_Size sourceLen; /* Length of the source code in bytes */ /* * Get the expression ByteCode from the object. If it exists, make sure it * is valid in the current context. */ - ByteCodeGetIntRep(objPtr, &assembleCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &assembleCodeType, codePtr); if (codePtr) { namespacePtr = iPtr->varFramePtr->nsPtr; if (((Interp *) *codePtr->interpHandle == iPtr) && (codePtr->compileEpoch == iPtr->compileEpoch) @@ -878,18 +879,18 @@ /* * Not valid, so free it and regenerate. */ - Tcl_StoreIntRep(objPtr, &assembleCodeType, NULL); + Tcl_StoreInternalRep(objPtr, &assembleCodeType, NULL); } /* * Set up the compilation environment, and assemble the code. */ - source = TclGetStringFromObj(objPtr, &sourceLen); + source = Tcl_GetStringFromObj(objPtr, &sourceLen); TclInitCompileEnv(interp, &compEnv, source, sourceLen, NULL, 0); status = TclAssembleCode(&compEnv, source, sourceLen, TCL_EVAL_DIRECT); if (status != TCL_OK) { /* * Assembly failed. Clean up and report the error. @@ -955,19 +956,19 @@ int TclCompileAssembleCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command - * created by Tcl_ParseCommand. */ + * created by TclParseCommand. */ TCL_UNUSED(Command *), CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; /* Token in the input script */ - int numCommands = envPtr->numCommands; + size_t numCommands = envPtr->numCommands; int offset = envPtr->codeNext - envPtr->codeStart; - int depth = envPtr->currStackDepth; + size_t depth = envPtr->currStackDepth; /* * Make sure that the command has a single arg that is a simple word. */ if (parsePtr->numWords != 2) { @@ -988,11 +989,11 @@ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%.*s\" body, line %d)", (int)parsePtr->tokenPtr->size, parsePtr->tokenPtr->start, Tcl_GetErrorLine(interp))); - envPtr->numCommands = numCommands; + TclDisposeFailedCompile(envPtr, numCommands); envPtr->codeNext = envPtr->codeStart + offset; envPtr->currStackDepth = depth; TclCompileSyntaxError(interp, envPtr); } return TCL_OK; @@ -1044,11 +1045,12 @@ do { /* * Parse out one command line from the assembly script. */ - status = Tcl_ParseCommand(interp, instPtr, bytesLeft, 0, parsePtr); + status = TclParseCommand(interp, instPtr, bytesLeft, + PARSE_USE_INTERNAL_TOKENS, parsePtr); /* * Report errors in the parse. */ @@ -1266,14 +1268,14 @@ * instruction */ TalInstType instType; /* Type of the instruction */ Tcl_Obj* operand1Obj = NULL; /* First operand to the instruction */ const char* operand1; /* String rep of the operand */ - size_t operand1Len; /* String length of the operand */ + Tcl_Size operand1Len; /* String length of the operand */ int opnd; /* Integer representation of an operand */ int litIndex; /* Literal pool index of a constant */ - int localVar; /* LVT index of a local variable */ + Tcl_Size localVar; /* LVT index of a local variable */ int flags; /* Flags for a basic block */ JumptableInfo* jtPtr; /* Pointer to a jumptable */ int infoIndex; /* Index of the jumptable in auxdata */ int status = TCL_ERROR; /* Return value from this function */ @@ -1309,11 +1311,11 @@ goto cleanup; } if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) { goto cleanup; } - operand1 = TclGetStringFromObj(operand1Obj, &operand1Len); + operand1 = Tcl_GetStringFromObj(operand1Obj, &operand1Len); litIndex = TclRegisterLiteral(envPtr, operand1, operand1Len, 0); BBEmitInst1or4(assemEnvPtr, tblIdx, litIndex, 0); break; case ASSEM_1BYTE: @@ -1382,11 +1384,11 @@ goto cleanup; } if (opnd < 0 || opnd > 3) { Tcl_SetObjResult(interp, Tcl_NewStringObj("operand must be [0..3]", -1)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND<0,>3", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND<0,>3", (void *)NULL); goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, opnd); break; @@ -1476,11 +1478,11 @@ TalInstructionTable+tblIdx); } else if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) { goto cleanup; } else { - operand1 = TclGetStringFromObj(operand1Obj, &operand1Len); + operand1 = Tcl_GetStringFromObj(operand1Obj, &operand1Len); litIndex = TclRegisterLiteral(envPtr, operand1, operand1Len, 0); /* * Assumes that PUSH is the first slot! */ @@ -1623,11 +1625,11 @@ } if (opnd < 2) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj("operand must be >=2", -1)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND>=2", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND>=2", (void *)NULL); } goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd); break; @@ -1809,19 +1811,19 @@ * We'll record the stack usage of the script in the BasicBlock, and * accumulate it together with the stack usage of the enclosing assembly * code. */ - int savedStackDepth = envPtr->currStackDepth; - int savedMaxStackDepth = envPtr->maxStackDepth; + size_t savedStackDepth = envPtr->currStackDepth; + size_t savedMaxStackDepth = envPtr->maxStackDepth; int savedExceptArrayNext = envPtr->exceptArrayNext; envPtr->currStackDepth = 0; envPtr->maxStackDepth = 0; StartBasicBlock(assemEnvPtr, BB_FALLTHRU, NULL); - switch(instPtr->tclInstCode) { + switch (instPtr->tclInstCode) { case INST_EVAL_STK: TclCompileScript(interp, tokenPtr->start, tokenPtr->size, envPtr); break; case INST_EXPR_STK: TclCompileExpr(interp, tokenPtr->start, tokenPtr->size, envPtr, 1); @@ -1966,11 +1968,11 @@ static int CreateMirrorJumpTable( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Obj* jumps) /* List of alternating keywords and labels */ { - int objc; /* Number of elements in the 'jumps' list */ + Tcl_Size objc; /* Number of elements in the 'jumps' list */ Tcl_Obj** objv; /* Pointers to the elements in the list */ CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ @@ -1979,23 +1981,26 @@ JumptableInfo* jtPtr; Tcl_HashTable* jtHashPtr; /* Hashtable in the JumptableInfo */ Tcl_HashEntry* hashEntry; /* Entry for a key in the hashtable */ int isNew; /* Flag==1 if the key is not yet in the * table. */ - int i; + Tcl_Size i; - if (Tcl_ListObjGetElements(interp, jumps, &objc, &objv) != TCL_OK) { + if (TclListObjLengthM(interp, jumps, &objc) != TCL_OK) { return TCL_ERROR; } if (objc % 2 != 0) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "jump table must have an even number of list elements", -1)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADJUMPTABLE", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADJUMPTABLE", (void *)NULL); } return TCL_ERROR; + } + if (TclListObjGetElementsM(interp, jumps, &objc, &objv) != TCL_OK) { + return TCL_ERROR; } /* * Allocate the jumptable. */ @@ -2017,11 +2022,11 @@ if (!isNew) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "duplicate entry in jump table for \"%s\"", TclGetString(objv[i]))); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "DUPJUMPTABLEENTRY"); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "DUPJUMPTABLEENTRY", (void *)NULL); DeleteMirrorJumpTable(jtPtr); return TCL_ERROR; } } Tcl_SetHashValue(hashEntry, objv[i+1]); @@ -2102,11 +2107,11 @@ if (!TclWordKnownAtCompileTime(*tokenPtrPtr, operandObj)) { Tcl_DecrRefCount(operandObj); if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "assembly code may not contain substitutions", -1)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NOSUBST", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NOSUBST", (void *)NULL); } return TCL_ERROR; } *tokenPtrPtr = TokenAfter(*tokenPtrPtr); Tcl_IncrRefCount(operandObj); @@ -2241,11 +2246,11 @@ static int GetListIndexOperand( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Token** tokenPtrPtr, /* Current token from the parser */ - int* result) /* OUTPUT: Integer extracted from the token */ + int* result) /* OUTPUT: encoded index derived from the token */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ @@ -2293,11 +2298,11 @@ * has not yet been seen and the execution context allows for it. * *----------------------------------------------------------------------------- */ -static int +static size_t FindLocalVar( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Token** tokenPtrPtr) { CompileEnv* envPtr = assemEnvPtr->envPtr; @@ -2307,31 +2312,31 @@ Tcl_Token* tokenPtr = *tokenPtrPtr; /* INOUT: Pointer to the next token in the * source code. */ Tcl_Obj* varNameObj; /* Name of the variable */ const char* varNameStr; - size_t varNameLen; - int localVar; /* Index of the variable in the LVT */ + Tcl_Size varNameLen; + Tcl_Size localVar; /* Index of the variable in the LVT */ if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &varNameObj) != TCL_OK) { - return -1; + return TCL_INDEX_NONE; } - varNameStr = TclGetStringFromObj(varNameObj, &varNameLen); + varNameStr = Tcl_GetStringFromObj(varNameObj, &varNameLen); if (CheckNamespaceQualifiers(interp, varNameStr, varNameLen)) { Tcl_DecrRefCount(varNameObj); - return -1; + return TCL_INDEX_NONE; } localVar = TclFindCompiledLocal(varNameStr, varNameLen, 1, envPtr); Tcl_DecrRefCount(varNameObj); - if (localVar == -1) { + if (localVar < 0) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot use this instruction to create a variable" " in a non-proc context", -1)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "LVT", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "LVT", (void *)NULL); } - return -1; + return TCL_INDEX_NONE; } *tokenPtrPtr = TokenAfter(tokenPtr); return localVar; } @@ -2360,11 +2365,11 @@ for (p = name; p+2 < name+nameLen; p++) { if ((*p == ':') && (p[1] == ':')) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "variable \"%s\" is not local", name)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONLOCAL", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONLOCAL", name, (void *)NULL); return TCL_ERROR; } } return TCL_OK; } @@ -2396,11 +2401,11 @@ Tcl_Obj* result; /* Error message */ if (value < 0 || value > 0xFF) { result = Tcl_NewStringObj("operand does not fit in one byte", -1); Tcl_SetObjResult(interp, result); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -2431,11 +2436,11 @@ Tcl_Obj* result; /* Error message */ if (value > 0x7F || value < -0x80) { result = Tcl_NewStringObj("operand does not fit in one byte", -1); Tcl_SetObjResult(interp, result); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -2464,11 +2469,11 @@ Tcl_Obj* result; /* Error message */ if (value < 0) { result = Tcl_NewStringObj("operand must be nonnegative", -1); Tcl_SetObjResult(interp, result); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONNEGATIVE", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONNEGATIVE", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -2497,11 +2502,11 @@ Tcl_Obj* result; /* Error message */ if (value <= 0) { result = Tcl_NewStringObj("operand must be positive", -1); Tcl_SetObjResult(interp, result); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "POSITIVE", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "POSITIVE", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -2549,11 +2554,11 @@ 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); + (void *)NULL); } return TCL_ERROR; } /* @@ -2950,11 +2955,11 @@ if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "undefined label \"%s\"", TclGetString(jumpTarget))); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NOLABEL", - TclGetString(jumpTarget), NULL); + TclGetString(jumpTarget), (void *)NULL); Tcl_SetErrorLine(interp, bbPtr->jumpLine); } } /* @@ -3235,11 +3240,11 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" instruction may not appear in " "a context where an exception has been " "caught and not disposed of.", tclInstructionTable[opcode].name)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADTHROW", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADTHROW", (void *)NULL); AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr); } return TCL_ERROR; } offset += tclInstructionTable[opcode].numBytes; @@ -3315,11 +3320,11 @@ CheckStack( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ - int maxDepth; /* Maximum stack depth overall */ + Tcl_Size maxDepth; /* Maximum stack depth overall */ /* * Checking the head block will check all the other blocks recursively. */ @@ -3415,11 +3420,11 @@ /* * TODO - add execution trace of both paths */ Tcl_SetErrorLine(interp, blockPtr->startLine); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", (void *)NULL); } return TCL_ERROR; } /* @@ -3438,11 +3443,11 @@ */ if (initialStackDepth + blockPtr->minStackDepth < 0) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj("stack underflow", -1)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", (void *)NULL); AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr); Tcl_SetErrorLine(interp, blockPtr->startLine); } return TCL_ERROR; } @@ -3457,11 +3462,11 @@ < (blockPtr->enclosingCatch->initialStackDepth + blockPtr->enclosingCatch->finalStackDepth)) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "code pops stack below level of enclosing catch", -1)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACKINCATCH", -1); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACKINCATCH", (void *)NULL); AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr); Tcl_SetErrorLine(interp, blockPtr->startLine); } return TCL_ERROR; } @@ -3585,11 +3590,11 @@ if (depth != 1) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "stack is unbalanced on exit from the code (depth=%d)", depth)); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", (void *)NULL); } return TCL_ERROR; } /* @@ -3730,11 +3735,11 @@ if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "execution reaches an instruction in inconsistent " "exception contexts", -1)); Tcl_SetErrorLine(interp, bbPtr->startLine); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADCATCH", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADCATCH", (void *)NULL); } return TCL_ERROR; } if (state > bbPtr->catchState) { bbPtr->catchState = state; @@ -3789,11 +3794,11 @@ if (enclosing == NULL) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "endCatch without a corresponding beginCatch", -1)); Tcl_SetErrorLine(interp, bbPtr->startLine); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADENDCATCH", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADENDCATCH", (void *)NULL); } return TCL_ERROR; } fallThruEnclosing = enclosing->enclosingCatch; fallThruState = enclosing->catchState; @@ -3865,11 +3870,11 @@ if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "catch still active on exit from assembly code", -1)); Tcl_SetErrorLine(interp, assemEnvPtr->curr_bb->enclosingCatch->startLine); - Tcl_SetErrorCode(interp, "TCL", "ASSEM", "UNCLOSEDCATCH", NULL); + Tcl_SetErrorCode(interp, "TCL", "ASSEM", "UNCLOSEDCATCH", (void *)NULL); } return TCL_ERROR; } return TCL_OK; } @@ -4124,11 +4129,11 @@ block = catches[catchDepth]; catchIndices[catchDepth] = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); range = envPtr->exceptArrayPtr + catchIndices[catchDepth]; range->nestingLevel = envPtr->exceptDepth + catchDepth; - envPtr->maxExceptDepth = + envPtr->maxExceptDepth= TclMax(range->nestingLevel + 1, envPtr->maxExceptDepth); range->codeOffset = bbPtr->startOffset; entryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash, TclGetString(block->jumpTarget)); @@ -4161,11 +4166,11 @@ CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* bbPtr; /* Current basic block */ int rangeBase; /* Base of the foreign exception ranges when * they are reinstalled */ - int rangeIndex; /* Index of the current foreign exception + size_t rangeIndex; /* Index of the current foreign exception * range as reinstalled */ ExceptionRange* range; /* Current foreign exception range */ unsigned char opcode; /* Current instruction's opcode */ int catchIndex; /* Index of the exception range to which the * current instruction refers */ @@ -4188,11 +4193,11 @@ range = bbPtr->foreignExceptions + i; rangeIndex = TclCreateExceptRange(range->type, envPtr); range->nestingLevel += envPtr->exceptDepth + bbPtr->catchDepth; memcpy(envPtr->exceptArrayPtr + rangeIndex, range, sizeof(ExceptionRange)); - if (range->nestingLevel >= envPtr->maxExceptDepth) { + if (range->nestingLevel + 1 >= envPtr->maxExceptDepth + 1) { envPtr->maxExceptDepth = range->nestingLevel + 1; } } /* @@ -4285,20 +4290,20 @@ *----------------------------------------------------------------------------- * * DupAssembleCodeInternalRep -- * * Part of the Tcl object type implementation for Tcl assembly language - * bytecode. We do not copy the bytecode intrep. Instead, we return + * bytecode. We do not copy the bytecode internalrep. Instead, we return * without setting copyPtr->typePtr, so the copy is a plain string copy * of the assembly source, and if it is to be used as a compiled * expression, it will need to be reprocessed. * * This makes sense, because with Tcl's copy-on-write practices, the * usual (only?) time Tcl_DuplicateObj() will be called is when the copy * is about to be modified, which would invalidate any copied bytecode * anyway. The only reason it might make sense to copy the bytecode is if - * we had some modifying routines that operated directly on the intrep, + * we had some modifying routines that operated directly on the internalrep, * as we do for lists and dicts. * * Results: * None. * @@ -4338,11 +4343,11 @@ FreeAssembleCodeInternalRep( Tcl_Obj *objPtr) { ByteCode *codePtr; - ByteCodeGetIntRep(objPtr, &assembleCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &assembleCodeType, codePtr); assert(codePtr != NULL); TclReleaseByteCode(codePtr); } Index: generic/tclAsync.c ================================================================== --- generic/tclAsync.c +++ generic/tclAsync.c @@ -3,12 +3,12 @@ * * This file provides low-level support needed to invoke signal handlers * in a safe way. The code here doesn't actually handle signals, though. * This code is based on proposals made by Mark Diekhans and Don Libes. * - * Copyright (c) 1993 The Regents of the University of California. - * Copyright (c) 1994 Sun Microsystems, Inc. + * Copyright © 1993 The Regents of the University of California. + * Copyright © 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -23,33 +23,27 @@ typedef struct AsyncHandler { int ready; /* Non-zero means this handler should be * invoked in the next call to * Tcl_AsyncInvoke. */ - struct AsyncHandler *nextPtr; - /* Next in list of all handlers for the - * process. */ + struct AsyncHandler *nextPtr, *prevPtr; + /* Next, previous in list of all handlers + * for the process. */ Tcl_AsyncProc *proc; /* Procedure to call when handler is * invoked. */ - ClientData clientData; /* Value to pass to handler when it is + void *clientData; /* Value to pass to handler when it is * invoked. */ struct ThreadSpecificData *originTsd; /* Used in Tcl_AsyncMark to modify thread- * specific data from outside the thread it is * associated to. */ Tcl_ThreadId originThrdId; /* Origin thread where this token was created * and where it will be yielded. */ + void *notifierData; /* Platform notifier data or NULL. */ } AsyncHandler; typedef struct ThreadSpecificData { - /* - * The variables below maintain a list of all existing handlers specific - * to the calling thread. - */ - AsyncHandler *firstHandler; /* First handler defined for process, or NULL - * if none. */ - AsyncHandler *lastHandler; /* Last handler or NULL. */ int asyncReady; /* This is set to 1 whenever a handler becomes * ready and it is cleared to zero whenever * Tcl_AsyncInvoke is called. It can be * checked elsewhere in the application by * calling Tcl_AsyncReady to see if @@ -56,39 +50,74 @@ * Tcl_AsyncInvoke should be invoked. */ int asyncActive; /* Indicates whether Tcl_AsyncInvoke is * currently working. If so then we won't set * asyncReady again until Tcl_AsyncInvoke * returns. */ - Tcl_Mutex asyncMutex; /* Thread-specific AsyncHandler linked-list - * lock */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; + +/* Mutex to protect linked-list of AsyncHandlers in the process. */ +TCL_DECLARE_MUTEX(asyncMutex) + +/* List of all existing handlers of the process. */ +static AsyncHandler *firstHandler = NULL; +static AsyncHandler *lastHandler = NULL; /* *---------------------------------------------------------------------- * * TclFinalizeAsync -- * - * Finalizes the mutex in the thread local data structure for the async + * Finalizes the thread local data structure for the async * subsystem. * * Results: * None. * * Side effects: - * Forgets knowledge of the mutex should it have been created. + * Cleans up left-over async handlers for the calling thread. * *---------------------------------------------------------------------- */ void TclFinalizeAsync(void) { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + AsyncHandler *token, *toDelete = NULL; + Tcl_ThreadId self = Tcl_GetCurrentThread(); + + Tcl_MutexLock(&asyncMutex); + for (token = firstHandler; token != NULL;) { + AsyncHandler *nextToken = token->nextPtr; - if (tsdPtr->asyncMutex != NULL) { - Tcl_MutexFinalize(&tsdPtr->asyncMutex); + 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); } } /* *---------------------------------------------------------------------- @@ -111,31 +140,34 @@ Tcl_AsyncHandler Tcl_AsyncCreate( Tcl_AsyncProc *proc, /* Procedure to call when handler is * invoked. */ - ClientData clientData) /* Argument to pass to handler. */ + void *clientData) /* Argument to pass to handler. */ { AsyncHandler *asyncPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); asyncPtr = (AsyncHandler*)Tcl_Alloc(sizeof(AsyncHandler)); asyncPtr->ready = 0; asyncPtr->nextPtr = NULL; + asyncPtr->prevPtr = NULL; asyncPtr->proc = proc; asyncPtr->clientData = clientData; asyncPtr->originTsd = tsdPtr; asyncPtr->originThrdId = Tcl_GetCurrentThread(); + asyncPtr->notifierData = TclpNotifierData(); - Tcl_MutexLock(&tsdPtr->asyncMutex); - if (tsdPtr->firstHandler == NULL) { - tsdPtr->firstHandler = asyncPtr; + Tcl_MutexLock(&asyncMutex); + if (firstHandler == NULL) { + firstHandler = asyncPtr; } else { - tsdPtr->lastHandler->nextPtr = asyncPtr; + asyncPtr->prevPtr = lastHandler; + lastHandler->nextPtr = asyncPtr; } - tsdPtr->lastHandler = asyncPtr; - Tcl_MutexUnlock(&tsdPtr->asyncMutex); + lastHandler = asyncPtr; + Tcl_MutexUnlock(&asyncMutex); return (Tcl_AsyncHandler) asyncPtr; } /* *---------------------------------------------------------------------- @@ -160,17 +192,90 @@ Tcl_AsyncMark( Tcl_AsyncHandler async) /* Token for handler. */ { AsyncHandler *token = (AsyncHandler *) async; - Tcl_MutexLock(&token->originTsd->asyncMutex); + Tcl_MutexLock(&asyncMutex); token->ready = 1; if (!token->originTsd->asyncActive) { token->originTsd->asyncReady = 1; Tcl_ThreadAlert(token->originThrdId); } - Tcl_MutexUnlock(&token->originTsd->asyncMutex); + Tcl_MutexUnlock(&asyncMutex); + +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AsyncMarkFromSignal -- + * + * This procedure is similar to Tcl_AsyncMark but must be used + * in POSIX signal contexts. In addition to Tcl_AsyncMark the + * signal number is passed. + * + * Results: + * True, when the handler will be marked, false otherwise. + * + * Side effects: + * The handler gets marked for invocation later. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_AsyncMarkFromSignal( + Tcl_AsyncHandler async, /* Token for handler. */ + int sigNumber) /* Signal number. */ +{ +#if TCL_THREADS + AsyncHandler *token = (AsyncHandler *) async; + + return TclAsyncNotifier(sigNumber, token->originThrdId, + token->notifierData, &token->ready, -1); +#else + (void)sigNumber; + + Tcl_AsyncMark(async); + return 1; +#endif +} + +/* + *---------------------------------------------------------------------- + * + * TclAsyncMarkFromNotifier -- + * + * This procedure is called from the notifier thread and + * invokes Tcl_AsyncMark for specifically marked handlers. + * + * Results: + * None. + * + * Side effects: + * Handlers get marked for invocation later. + * + *---------------------------------------------------------------------- + */ + +void +TclAsyncMarkFromNotifier(void) +{ + AsyncHandler *token; + + Tcl_MutexLock(&asyncMutex); + for (token = firstHandler; token != NULL; + token = token->nextPtr) { + if (token->ready == -1) { + token->ready = 1; + if (!token->originTsd->asyncActive) { + token->originTsd->asyncReady = 1; + Tcl_ThreadAlert(token->originThrdId); + } + } + } + Tcl_MutexUnlock(&asyncMutex); } /* *---------------------------------------------------------------------- * @@ -198,15 +303,16 @@ * completion code from command that just * completed. */ { AsyncHandler *asyncPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + Tcl_ThreadId self = Tcl_GetCurrentThread(); - Tcl_MutexLock(&tsdPtr->asyncMutex); + Tcl_MutexLock(&asyncMutex); if (tsdPtr->asyncReady == 0) { - Tcl_MutexUnlock(&tsdPtr->asyncMutex); + Tcl_MutexUnlock(&asyncMutex); return code; } tsdPtr->asyncReady = 0; tsdPtr->asyncActive = 1; if (interp == NULL) { @@ -222,26 +328,29 @@ * execution of a handler, then the list structure may change so it isn't * safe to continue down the list anyway. */ while (1) { - for (asyncPtr = tsdPtr->firstHandler; asyncPtr != NULL; + for (asyncPtr = firstHandler; asyncPtr != NULL; asyncPtr = asyncPtr->nextPtr) { + if (asyncPtr->originThrdId != self) { + continue; + } if (asyncPtr->ready) { break; } } if (asyncPtr == NULL) { break; } asyncPtr->ready = 0; - Tcl_MutexUnlock(&tsdPtr->asyncMutex); + Tcl_MutexUnlock(&asyncMutex); code = asyncPtr->proc(asyncPtr->clientData, interp, code); - Tcl_MutexLock(&tsdPtr->asyncMutex); + Tcl_MutexLock(&asyncMutex); } tsdPtr->asyncActive = 0; - Tcl_MutexUnlock(&tsdPtr->asyncMutex); + Tcl_MutexUnlock(&asyncMutex); return code; } /* *---------------------------------------------------------------------- @@ -269,49 +378,36 @@ 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_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); } /* *---------------------------------------------------------------------- Index: generic/tclBasic.c ================================================================== --- generic/tclBasic.c +++ generic/tclBasic.c @@ -3,17 +3,17 @@ * * 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 - * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. - * Copyright (c) 2008 Miguel Sofer + * Copyright © 1987-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. + * Copyright © 2001, 2002 Kevin B. Kenny. All rights reserved. + * Copyright © 2007 Daniel A. Steffen + * Copyright © 2006-2008 Joe Mistachkin. All rights reserved. + * 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. */ @@ -62,10 +62,45 @@ #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 /* 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 @@ -91,12 +126,12 @@ Tcl_Interp *interp; /* Interp this struct belongs to. */ Tcl_AsyncHandler async; /* Async handler token for script * cancellation. */ char *result; /* The script cancellation result or NULL for * a default result. */ - size_t length; /* Length of the above error message. */ - ClientData clientData; /* Not used. */ + Tcl_Size length; /* Length of the above error message. */ + void *clientData; /* Not used. */ int flags; /* Additional flags */ } CancelInfo; static Tcl_HashTable cancelTable; static int cancelTableInitialized = 0; /* 0 means not yet initialized. */ TCL_DECLARE_MUTEX(cancelLock); @@ -135,22 +170,23 @@ static Tcl_ObjCmdProc BadEnsembleSubcommand; static char * CallCommandTraces(Interp *iPtr, Command *cmdPtr, const char *oldName, const char *newName, int flags); -static int CancelEvalProc(ClientData clientData, +static int CancelEvalProc(void *clientData, Tcl_Interp *interp, int code); static int CheckDoubleResult(Tcl_Interp *interp, double dResult); -static void DeleteCoroutine(ClientData clientData); -static void DeleteInterpProc(Tcl_Interp *interp); -static void DeleteOpCmdClientData(ClientData clientData); +static void DeleteCoroutine(void *clientData); +static Tcl_FreeProc DeleteInterpProc; +static void DeleteOpCmdClientData(void *clientData); #ifdef USE_DTRACE static Tcl_ObjCmdProc DTraceObjCmd; static Tcl_NRPostProc DTraceCmdReturn; #else # define DTraceCmdReturn NULL #endif /* USE_DTRACE */ +static Tcl_ObjCmdProc InvokeStringCommand; static Tcl_ObjCmdProc ExprAbsFunc; static Tcl_ObjCmdProc ExprBinaryFunc; static Tcl_ObjCmdProc ExprBoolFunc; static Tcl_ObjCmdProc ExprCeilFunc; static Tcl_ObjCmdProc ExprDoubleFunc; @@ -215,12 +251,12 @@ /* * Magical counts for the number of arguments accepted by a coroutine command * after particular kinds of [yield]. */ -#define CORO_ACTIVATE_YIELD PTR2INT(NULL) -#define CORO_ACTIVATE_YIELDM PTR2INT(NULL)+1 +#define CORO_ACTIVATE_YIELD NULL +#define CORO_ACTIVATE_YIELDM INT2PTR(1) #define COROUTINE_ARGUMENTS_SINGLE_OPTIONAL (-1) #define COROUTINE_ARGUMENTS_ARBITRARY (-2) /* @@ -261,10 +297,16 @@ } UnsafeEnsembleInfo; /* * The built-in commands, and the functions that implement them: */ + +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. */ @@ -289,10 +331,11 @@ {"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}, @@ -301,14 +344,15 @@ {"lremove", Tcl_LremoveObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lrepeat", Tcl_LrepeatObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lreplace", Tcl_LreplaceObjCmd, TclCompileLreplaceCmd, NULL, CMD_IS_SAFE}, {"lreverse", Tcl_LreverseObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lsearch", Tcl_LsearchObjCmd, NULL, NULL, CMD_IS_SAFE}, + {"lseq", Tcl_LseqObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, NULL, CMD_IS_SAFE}, {"lsort", Tcl_LsortObjCmd, NULL, NULL, CMD_IS_SAFE}, {"package", Tcl_PackageObjCmd, NULL, TclNRPackageObjCmd, CMD_IS_SAFE}, - {"proc", Tcl_ProcObjCmd, NULL, NULL, CMD_IS_SAFE}, + {"proc", procObjCmd, NULL, NULL, CMD_IS_SAFE}, {"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, NULL, CMD_IS_SAFE}, {"regsub", Tcl_RegsubObjCmd, TclCompileRegsubCmd, NULL, CMD_IS_SAFE}, {"rename", Tcl_RenameObjCmd, NULL, NULL, CMD_IS_SAFE}, {"return", Tcl_ReturnObjCmd, TclCompileReturnCmd, NULL, CMD_IS_SAFE}, {"scan", Tcl_ScanObjCmd, NULL, NULL, CMD_IS_SAFE}, @@ -586,10 +630,122 @@ } /* *---------------------------------------------------------------------- * + * 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 = Tcl_GetStringFromObj(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, (void *)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, (void *)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, (void *)NULL); + } else { + Tcl_AppendResult(interp, p+1, (void *)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, (void *)NULL); + } else { + Tcl_AppendResult(interp, p+1, (void *)NULL); + } + return TCL_OK; + } + p = strchr(p+1, '.'); + } + Tcl_AppendResult(interp, "0", (void *)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", (void *)NULL); + return TCL_OK; + } + p = strchr(p+1, '.'); + } + Tcl_AppendResult(interp, "0", (void *)NULL); + return TCL_OK; + } + Tcl_AppendResult(interp, (char *)clientData, (void *)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: @@ -623,12 +779,11 @@ #ifdef TCL_COMPILE_STATS ByteCodeStats *statsPtr; #endif /* TCL_COMPILE_STATS */ char mathFuncName[32]; CallFrame *framePtr; - - Tcl_InitSubsystems(); + const char *version = Tcl_InitSubsystems(); /* * Panic if someone updated the CallFrame structure without also updating * the Tcl_CallFrame structure (or vice versa). */ @@ -655,10 +810,11 @@ } Tcl_MutexUnlock(&cancelLock); } +#undef TclObjInterpProc if (commandTypeInit == 0) { TclRegisterCommandTypeName(TclObjInterpProc, "proc"); TclRegisterCommandTypeName(TclEnsembleImplementationCmd, "ensemble"); TclRegisterCommandTypeName(TclAliasObjCmd, "alias"); TclRegisterCommandTypeName(TclLocalAliasObjCmd, "alias"); @@ -683,11 +839,11 @@ /* Special invalid value: Any attempt to free the legacy result * will cause a crash. */ iPtr->legacyFreeProc = (void (*) (void))-1; iPtr->errorLine = 0; iPtr->stubTable = &tclStubs; - iPtr->objResultPtr = Tcl_NewObj(); + TclNewObj(iPtr->objResultPtr); Tcl_IncrRefCount(iPtr->objResultPtr); iPtr->handle = TclHandleCreate(iPtr); iPtr->globalNsPtr = NULL; iPtr->hiddenCmdTablePtr = NULL; iPtr->interpInfo = NULL; @@ -741,10 +897,14 @@ 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; @@ -764,11 +924,11 @@ iPtr->tracesForbiddingInline = 0; iPtr->activeCmdTracePtr = NULL; iPtr->activeInterpTracePtr = NULL; iPtr->assocData = NULL; iPtr->execEnvPtr = NULL; /* Set after namespaces initialized. */ - iPtr->emptyObjPtr = Tcl_NewObj(); + TclNewObj(iPtr->emptyObjPtr); /* Another empty object. */ Tcl_IncrRefCount(iPtr->emptyObjPtr); iPtr->threadId = Tcl_GetCurrentThread(); /* TIP #378 */ @@ -828,11 +988,11 @@ /* * TIP #285, Script cancellation support. */ - iPtr->asyncCancelMsg = Tcl_NewObj(); + TclNewObj(iPtr->asyncCancelMsg); cancelInfo = (CancelInfo *)Tcl_Alloc(sizeof(CancelInfo)); cancelInfo->interp = interp; iPtr->asyncCancel = Tcl_AsyncCreate(CancelEvalProc, cancelInfo); @@ -905,16 +1065,16 @@ 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 + * preexisting 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 + * InvokeStringCommand. 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. + * the result. If a command has a Tcl_ObjCmdProc but no + * Tcl_CmdProc, set the Tcl_CmdProc to NULL. */ for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) { if ((cmdInfoPtr->objProc == NULL) && (cmdInfoPtr->compileProc == NULL) @@ -929,11 +1089,11 @@ cmdPtr->hPtr = hPtr; cmdPtr->nsPtr = iPtr->globalNsPtr; cmdPtr->refCount = 1; cmdPtr->cmdEpoch = 0; cmdPtr->compileProc = cmdInfoPtr->compileProc; - cmdPtr->proc = TclInvokeObjectCommand; + cmdPtr->proc = NULL; cmdPtr->clientData = cmdPtr; cmdPtr->objProc = cmdInfoPtr->objProc; cmdPtr->objClientData = NULL; cmdPtr->deleteProc = NULL; cmdPtr->deleteData = NULL; @@ -959,10 +1119,11 @@ TclInitBinaryCmd(interp); TclInitChanCmd(interp); TclInitDictCmd(interp); TclInitEncodingCmd(interp); TclInitFileCmd(interp); + TclInitHamtCmd(interp); TclInitInfoCmd(interp); TclInitNamespaceCmd(interp); TclInitStringCmd(interp); TclInitPrefixCmd(interp); TclInitProcessCmd(interp); @@ -1113,27 +1274,25 @@ Tcl_SetVar2(interp, "tcl_patchLevel", NULL, TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "tcl_version", NULL, TCL_VERSION, TCL_GLOBAL_ONLY); TclpSetVariables(interp); -#if TCL_THREADS - /* - * The existence of the "threaded" element of the tcl_platform array - * indicates that this particular Tcl shell has been compiled with threads - * turned on. Using "info exists tcl_platform(threaded)" a Tcl script can - * introspect on the interpreter level of thread safety. - */ - - Tcl_SetVar2(interp, "tcl_platform", "threaded", "1", TCL_GLOBAL_ONLY); -#endif - /* * Register Tcl's version number. * TIP #268: Full patchlevel instead of just major.minor + * TIP #599: Extended build information "+......" */ 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)); } @@ -1159,11 +1318,11 @@ return interp; } static void DeleteOpCmdClientData( - ClientData clientData) + void *clientData) { TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData; Tcl_Free(occdPtr); } @@ -1195,15 +1354,15 @@ } if (nameStr != NULL) { int isNew; hPtr = Tcl_CreateHashEntry(&commandTypeTable, - (void *) implementationProc, &isNew); + implementationProc, &isNew); Tcl_SetHashValue(hPtr, (void *) nameStr); } else { hPtr = Tcl_FindHashEntry(&commandTypeTable, - (void *) implementationProc); + implementationProc); if (hPtr != NULL) { Tcl_DeleteHashEntry(hPtr); } } Tcl_MutexUnlock(&commandTypeLock); @@ -1324,21 +1483,21 @@ *---------------------------------------------------------------------- */ static int BadEnsembleSubcommand( - ClientData clientData, + void *clientData, Tcl_Interp *interp, TCL_UNUSED(int) /*objc*/, TCL_UNUSED(Tcl_Obj *const *) /* objv */) { const UnsafeEnsembleInfo *infoPtr = (const UnsafeEnsembleInfo *)clientData; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "not allowed to invoke subcommand %s of %s", infoPtr->commandName, infoPtr->ensembleNsName)); - Tcl_SetErrorCode(interp, "TCL", "SAFE", "SUBCOMMAND", NULL); + Tcl_SetErrorCode(interp, "TCL", "SAFE", "SUBCOMMAND", (void *)NULL); return TCL_ERROR; } /* *-------------------------------------------------------------- @@ -1364,11 +1523,11 @@ void Tcl_CallWhenDeleted( Tcl_Interp *interp, /* Interpreter to watch. */ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about * to be deleted. */ - ClientData clientData) /* One-word value to pass to proc. */ + void *clientData) /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; static Tcl_ThreadDataKey assocDataCounterKey; int *assocDataCounterPtr = (int *)Tcl_GetThreadData(&assocDataCounterKey, sizeof(int)); @@ -1375,11 +1534,11 @@ int isNew; char buffer[32 + TCL_INTEGER_SPACE]; AssocData *dPtr = (AssocData *)Tcl_Alloc(sizeof(AssocData)); Tcl_HashEntry *hPtr; - sprintf(buffer, "Assoc Data Key #%d", *assocDataCounterPtr); + snprintf(buffer, sizeof(buffer), "Assoc Data Key #%d", *assocDataCounterPtr); (*assocDataCounterPtr)++; if (iPtr->assocData == NULL) { iPtr->assocData = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS); @@ -1412,11 +1571,11 @@ void Tcl_DontCallWhenDeleted( Tcl_Interp *interp, /* Interpreter to watch. */ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about * to be deleted. */ - ClientData clientData) /* One-word value to pass to proc. */ + void *clientData) /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; Tcl_HashTable *hTablePtr; Tcl_HashSearch hSearch; Tcl_HashEntry *hPtr; @@ -1460,11 +1619,11 @@ Tcl_SetAssocData( Tcl_Interp *interp, /* Interpreter to associate with. */ const char *name, /* Name for association. */ Tcl_InterpDeleteProc *proc, /* Proc to call when interpreter is about to * be deleted. */ - ClientData clientData) /* One-word value to pass to proc. */ + void *clientData) /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; AssocData *dPtr; Tcl_HashEntry *hPtr; int isNew; @@ -1517,15 +1676,15 @@ hPtr = Tcl_FindHashEntry(iPtr->assocData, name); if (hPtr == NULL) { return; } dPtr = (AssocData *)Tcl_GetHashValue(hPtr); + Tcl_DeleteHashEntry(hPtr); if (dPtr->proc != NULL) { dPtr->proc(dPtr->clientData, interp); } Tcl_Free(dPtr); - Tcl_DeleteHashEntry(hPtr); } /* *---------------------------------------------------------------------- * @@ -1542,11 +1701,11 @@ * None. * *---------------------------------------------------------------------- */ -ClientData +void * Tcl_GetAssocData( Tcl_Interp *interp, /* Interpreter associated with. */ const char *name, /* Name of association. */ Tcl_InterpDeleteProc **procPtr) /* Pointer to place to store address of @@ -1642,11 +1801,11 @@ /* * Ensure that the interpreter is eventually deleted. */ - Tcl_EventuallyFree(interp, (Tcl_FreeProc *) DeleteInterpProc); + Tcl_EventuallyFree(interp, DeleteInterpProc); } /* *---------------------------------------------------------------------- * @@ -1668,18 +1827,19 @@ *---------------------------------------------------------------------- */ static void DeleteInterpProc( - Tcl_Interp *interp) /* Interpreter to delete. */ + void *blockPtr) /* Interpreter to delete. */ { + Tcl_Interp *interp = (Tcl_Interp *) blockPtr; Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_HashTable *hTablePtr; ResolverScheme *resPtr, *nextResPtr; - int i; + Tcl_Size i; /* * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup, * unless we are exiting. */ @@ -1710,11 +1870,11 @@ * TIP #285, Script cancellation support. Delete this interp from the * global hash table of CancelInfo structs. */ Tcl_MutexLock(&cancelLock); - hPtr = Tcl_FindHashEntry(&cancelTable, (char *) iPtr); + hPtr = Tcl_FindHashEntry(&cancelTable, iPtr); if (hPtr != NULL) { CancelInfo *cancelInfo = (CancelInfo *)Tcl_GetHashValue(hPtr); if (cancelInfo != NULL) { if (cancelInfo->result != NULL) { @@ -1776,32 +1936,32 @@ } Tcl_DeleteHashTable(hTablePtr); Tcl_Free(hTablePtr); } - /* - * Invoke deletion callbacks; note that a callback can create new - * callbacks, so we iterate. - */ - while (iPtr->assocData != NULL) { + if (iPtr->assocData != NULL) { AssocData *dPtr; hTablePtr = iPtr->assocData; - iPtr->assocData = NULL; + /* + * Invoke deletion callbacks; note that a callback can create new + * callbacks, so we iterate. + */ for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search); hPtr != NULL; hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) { dPtr = (AssocData *)Tcl_GetHashValue(hPtr); - Tcl_DeleteHashEntry(hPtr); if (dPtr->proc != NULL) { dPtr->proc(dPtr->clientData, interp); } + Tcl_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]. @@ -1905,11 +2065,11 @@ ExtCmdLoc *eclPtr = (ExtCmdLoc *)Tcl_GetHashValue(hPtr); if (eclPtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(eclPtr->path); } - for (i=0; i< eclPtr->nuloc; i++) { + for (i=0; inuloc; i++) { Tcl_Free(eclPtr->loc[i].line); } if (eclPtr->loc != NULL) { Tcl_Free(eclPtr->loc); @@ -2029,11 +2189,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "HIDDENTOKEN", (void *)NULL); return TCL_ERROR; } /* * Find the command to hide. An error is returned if cmdName can't be @@ -2054,11 +2214,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "HIDE", "NON_GLOBAL", (void *)NULL); return TCL_ERROR; } /* * Initialize the hidden command table if necessary. @@ -2080,24 +2240,24 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "HIDE", "ALREADY_HIDDEN", (void *)NULL); return TCL_ERROR; } /* - * NB: This code is currently 'like' a rename to a specialy set apart name + * NB: This code is currently 'like' a rename to a special separate name * table. Changes here and in TclRenameCommand must be kept in synch until * the common parts are actually factorized out. */ /* * Remove the hash entry for the command from the interpreter command - * table. This is like deleting the command, so bump its command epoch; - * this invalidates any cached references that point to the command. + * table. This is like deleting the command, so bump its command epoch + * to invalidate any cached references that point to the command. */ if (cmdPtr->hPtr != NULL) { Tcl_DeleteHashEntry(cmdPtr->hPtr); cmdPtr->hPtr = NULL; @@ -2184,11 +2344,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "NON_GLOBAL", (void *)NULL); return TCL_ERROR; } /* * Get the command from the hidden command table: @@ -2201,11 +2361,11 @@ } if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown hidden command \"%s\"", hiddenCmdToken)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN", - hiddenCmdToken, NULL); + hiddenCmdToken, (void *)NULL); return TCL_ERROR; } cmdPtr = (Command *)Tcl_GetHashValue(hPtr); /* @@ -2214,11 +2374,11 @@ * really know how to handle it). */ if (cmdPtr->nsPtr != iPtr->globalNsPtr) { /* - * This case is theoritically impossible, we might rather Tcl_Panic + * This case is theoretically impossible, we might rather Tcl_Panic * than 'nicely' erroring out ? */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "trying to expose a non-global command namespace command", @@ -2239,11 +2399,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "COMMAND_EXISTS", (void *)NULL); return TCL_ERROR; } /* * Command resolvers (per-interp, per-namespace) might have resolved to a @@ -2320,11 +2480,11 @@ * Side effects: * If a command named cmdName already exists for interp, it is deleted. * In the future, when cmdName is seen as the name of a command by * Tcl_Eval, proc will be called. To support the bytecode interpreter, * the command is created with a wrapper Tcl_ObjCmdProc - * (TclInvokeStringCommand) that eventially calls proc. When the command + * (InvokeStringCommand) that eventually calls proc. When the command * is deleted from the table, deleteProc will be called. See the manual * entry for details on the calling sequence. * *---------------------------------------------------------------------- */ @@ -2336,11 +2496,11 @@ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_CmdProc *proc, /* Function to associate with cmdName. */ - ClientData clientData, /* Arbitrary value passed to string proc. */ + void *clientData, /* Arbitrary value passed to string proc. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { Interp *iPtr = (Interp *) interp; @@ -2462,11 +2622,11 @@ cmdPtr->hPtr = hPtr; cmdPtr->nsPtr = nsPtr; cmdPtr->refCount = 1; cmdPtr->cmdEpoch = 0; cmdPtr->compileProc = NULL; - cmdPtr->objProc = TclInvokeStringCommand; + cmdPtr->objProc = InvokeStringCommand; cmdPtr->objClientData = cmdPtr; cmdPtr->proc = proc; cmdPtr->clientData = clientData; cmdPtr->deleteProc = deleteProc; cmdPtr->deleteData = clientData; @@ -2522,10 +2682,70 @@ * 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). */ @@ -2533,11 +2753,11 @@ * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_ObjCmdProc *proc, /* Object-based function to associate with * name. */ - ClientData clientData, /* Arbitrary value to pass to object + void *clientData, /* Arbitrary value to pass to object * function. */ Tcl_CmdDeleteProc *deleteProc /* If not NULL, gives a function to call when * this command is deleted. */ ) @@ -2583,11 +2803,11 @@ 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 + 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. */ { @@ -2691,11 +2911,11 @@ cmdPtr->refCount = 1; cmdPtr->cmdEpoch = 0; cmdPtr->compileProc = NULL; cmdPtr->objProc = proc; cmdPtr->objClientData = clientData; - cmdPtr->proc = TclInvokeObjectCommand; + cmdPtr->proc = NULL; cmdPtr->clientData = cmdPtr; cmdPtr->deleteProc = deleteProc; cmdPtr->deleteData = clientData; cmdPtr->flags = 0; cmdPtr->importRefPtr = NULL; @@ -2732,11 +2952,11 @@ } /* *---------------------------------------------------------------------- * - * TclInvokeStringCommand -- + * InvokeStringCommand -- * * "Wrapper" Tcl_ObjCmdProc used to call an existing string-based * Tcl_CmdProc if no object-based function exists for a command. A * pointer to this function is stored as the Tcl_ObjCmdProc in a Command * structure. It simply turns around and calls the string Tcl_CmdProc in @@ -2745,18 +2965,18 @@ * Results: * A standard Tcl object result value. * * Side effects: * Besides those side effects of the called Tcl_CmdProc, - * TclInvokeStringCommand allocates and frees storage. + * InvokeStringCommand allocates and frees storage. * *---------------------------------------------------------------------- */ int -TclInvokeStringCommand( - ClientData clientData, /* Points to command's Command structure. */ +InvokeStringCommand( + void *clientData, /* Points to command's Command structure. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Command *cmdPtr = (Command *)clientData; @@ -2776,75 +2996,10 @@ 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 -- @@ -2894,11 +3049,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", oldName, (void *)NULL); return TCL_ERROR; } /* * If the new command name is NULL or empty, delete the command. Do this @@ -2909,11 +3064,11 @@ Tcl_DeleteCommandFromToken(interp, cmd); return TCL_OK; } cmdNsPtr = cmdPtr->nsPtr; - oldFullName = Tcl_NewObj(); + TclNewObj(oldFullName); Tcl_IncrRefCount(oldFullName); Tcl_GetCommandFullName(interp, cmd, oldFullName); /* * Make sure that the destination command does not already exist. The @@ -2925,19 +3080,19 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", (void *)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); + "TARGET_EXISTS", (void *)NULL); result = TCL_ERROR; goto done; } /* @@ -3102,10 +3257,44 @@ * 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) @@ -3122,22 +3311,50 @@ cmdPtr = (Command *) cmd; cmdPtr->proc = infoPtr->proc; cmdPtr->clientData = infoPtr->clientData; if (infoPtr->objProc == NULL) { - cmdPtr->objProc = TclInvokeStringCommand; + cmdPtr->objProc = InvokeStringCommand; cmdPtr->objClientData = cmdPtr; cmdPtr->nreProc = NULL; } else { if (infoPtr->objProc != cmdPtr->objProc) { cmdPtr->nreProc = NULL; cmdPtr->objProc = infoPtr->objProc; } cmdPtr->objClientData = infoPtr->objClientData; } - cmdPtr->deleteProc = infoPtr->deleteProc; - cmdPtr->deleteData = infoPtr->deleteData; + 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; } /* *---------------------------------------------------------------------- @@ -3200,24 +3417,37 @@ return 0; } /* * Set isNativeObjectProc 1 if objProc was registered by a call to - * Tcl_CreateObjCommand. Otherwise set it to 0. + * Tcl_CreateObjCommand. Set isNativeObjectProc 2 if objProc was + * registered by a call to Tcl_CreateObjCommand2. Otherwise set it to 0. */ cmdPtr = (Command *) cmd; infoPtr->isNativeObjectProc = - (cmdPtr->objProc != TclInvokeStringCommand); + (cmdPtr->objProc != InvokeStringCommand); infoPtr->objProc = cmdPtr->objProc; infoPtr->objClientData = cmdPtr->objClientData; infoPtr->proc = cmdPtr->proc; infoPtr->clientData = cmdPtr->clientData; - infoPtr->deleteProc = cmdPtr->deleteProc; - infoPtr->deleteData = cmdPtr->deleteData; + 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; } /* *---------------------------------------------------------------------- @@ -3420,18 +3650,19 @@ */ cmdPtr->flags |= CMD_DYING; /* - * Call trace functions for the command being deleted. Then delete its - * traces. + * 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. */ @@ -3597,11 +3828,10 @@ if (flags == 0) { return NULL; } } cmdPtr->flags |= CMD_TRACE_ACTIVE; - cmdPtr->refCount++; result = NULL; active.nextPtr = iPtr->activeCmdTracePtr; active.reverseScan = 0; iPtr->activeCmdTracePtr = &active; @@ -3655,11 +3885,10 @@ * 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; } @@ -3676,18 +3905,18 @@ * * Results: * The value given for the code argument. * * Side effects: - * Transfers a message from the cancelation message to the interpreter. + * Transfers a message from the cancellation message to the interpreter. * *---------------------------------------------------------------------- */ static int CancelEvalProc( - ClientData clientData, /* Interp to cancel the script in progress. */ + void *clientData, /* Interp to cancel the script in progress. */ TCL_UNUSED(Tcl_Interp *), int code) /* Current return code from command. */ { CancelInfo *cancelInfo = (CancelInfo *)clientData; Interp *iPtr; @@ -3808,11 +4037,11 @@ 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); + "attempt to call eval in deleted interpreter", (void *)NULL); return TCL_ERROR; } if (iPtr->execEnvPtr->rewind) { return TCL_ERROR; @@ -3830,17 +4059,17 @@ /* * Check depth of nested calls to Tcl_Eval: if this gets too large, it's * probably because of an infinite loop somewhere. */ - if (((iPtr->numLevels) <= iPtr->maxNestingDepth)) { + if ((iPtr->numLevels <= iPtr->maxNestingDepth)) { return TCL_OK; } Tcl_SetObjResult(interp, Tcl_NewStringObj( "too many nested evaluations (infinite loop?)", -1)); - Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", NULL); + Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -3944,19 +4173,19 @@ * interp's result; otherwise, we leave it alone. */ if (flags & TCL_LEAVE_ERR_MSG) { const char *id, *message = NULL; - size_t length; + Tcl_Size length; /* * Setup errorCode variables so that we can differentiate between * being canceled and unwound. */ if (iPtr->asyncCancelMsg != NULL) { - message = TclGetStringFromObj(iPtr->asyncCancelMsg, &length); + message = Tcl_GetStringFromObj(iPtr->asyncCancelMsg, &length); } else { length = 0; } if (iPtr->flags & TCL_CANCEL_UNWIND) { @@ -3970,11 +4199,11 @@ message = "eval canceled"; } } Tcl_SetObjResult(interp, Tcl_NewStringObj(message, -1)); - Tcl_SetErrorCode(interp, "TCL", "CANCEL", id, message, NULL); + Tcl_SetErrorCode(interp, "TCL", "CANCEL", id, message, (void *)NULL); } /* * Return TCL_ERROR to the caller (not necessarily just the Tcl core * itself) that indicates further processing of the script or command in @@ -4009,11 +4238,11 @@ Tcl_CancelEval( Tcl_Interp *interp, /* Interpreter in which to cancel the * script. */ Tcl_Obj *resultObjPtr, /* The script cancellation error message or * NULL for a default error message. */ - ClientData clientData, /* Passed to CancelEvalProc. */ + void *clientData, /* Passed to CancelEvalProc. */ int flags) /* Collection of OR-ed bits that control * the cancellation of the script. Only * TCL_CANCEL_UNWIND is currently * supported. */ { @@ -4032,11 +4261,11 @@ * No CancelInfo hash table (Tcl_CreateInterp has never been called?) */ goto done; } - hPtr = Tcl_FindHashEntry(&cancelTable, (char *) interp); + hPtr = Tcl_FindHashEntry(&cancelTable, interp); if (hPtr == NULL) { /* * No CancelInfo record for this interpreter. */ @@ -4051,11 +4280,11 @@ * allowed to catch the script cancellation because the evaluation stack * for the interp is completely unwound. */ if (resultObjPtr != NULL) { - result = TclGetStringFromObj(resultObjPtr, &cancelInfo->length); + result = Tcl_GetStringFromObj(resultObjPtr, &cancelInfo->length); cancelInfo->result = (char *)Tcl_Realloc(cancelInfo->result,cancelInfo->length); memcpy(cancelInfo->result, result, cancelInfo->length); TclDecrRefCount(resultObjPtr); /* Discard their result object. */ } else { cancelInfo->result = NULL; @@ -4115,11 +4344,11 @@ int Tcl_EvalObjv( Tcl_Interp *interp, /* Interpreter in which to evaluate the * command. Also used for error reporting. */ - int objc, /* Number of words in command. */ + Tcl_Size objc, /* Number of words in command. */ Tcl_Obj *const objv[], /* An array of pointers to objects that are * the words that make up the command. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and @@ -4134,11 +4363,11 @@ int TclNREvalObjv( Tcl_Interp *interp, /* Interpreter in which to evaluate the * command. Also used for error reporting. */ - int objc, /* Number of words in command. */ + Tcl_Size objc, /* Number of words in command. */ Tcl_Obj *const objv[], /* An array of pointers to objects that are * the words that make up the command. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and @@ -4168,11 +4397,11 @@ return TCL_OK; } static int EvalObjvCore( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int) /*result*/) { Command *cmdPtr = NULL, *preCmdPtr = (Command *)data[0]; int flags = PTR2INT(data[1]); @@ -4260,11 +4489,11 @@ * it ourselves, all we can do is raise an error. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "attempt to invoke a deleted command")); - Tcl_SetErrorCode(interp, "TCL", "EVAL", "DELETEDCOMMAND", NULL); + Tcl_SetErrorCode(interp, "TCL", "EVAL", "DELETEDCOMMAND", (void *)NULL); return TCL_ERROR; } } if (cmdPtr == NULL) { cmdPtr = TEOV_LookupCmdFromObj(interp, objv[0], lookupNsPtr); @@ -4328,16 +4557,16 @@ return TCL_OK; } static int Dispatch( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int) /*result*/) { Tcl_ObjCmdProc *objProc = (Tcl_ObjCmdProc *)data[0]; - ClientData clientData = data[1]; + void *clientData = data[1]; int objc = PTR2INT(data[2]); Tcl_Obj **objv = (Tcl_Obj **)data[3]; Interp *iPtr = (Interp *) interp; #ifdef USE_DTRACE @@ -4392,24 +4621,28 @@ return result; } static int NRCommand( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; + Tcl_Obj *listPtr; iPtr->numLevels--; /* * If there is a tailcall, schedule it next */ if (data[1] && (data[1] != INT2PTR(1))) { - TclNRAddCallback(interp, TclNRTailcallEval, data[1], NULL, NULL, NULL); + 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? @@ -4461,11 +4694,11 @@ /* * Error messages */ TclNRAddCallback(interp, TEOV_Error, INT2PTR(objc), - (ClientData) objv, NULL, NULL); + objv, NULL, NULL); } if (iPtr->numLevels == 1) { /* * No CONTINUE or BREAK at level 0, manage RETURN @@ -4492,21 +4725,21 @@ iPtr->varFramePtr = iPtr->rootFramePtr; } static int TEOV_RestoreVarFrame( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { ((Interp *) interp)->varFramePtr = (CallFrame *)data[0]; return result; } static int TEOV_Exception( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int allowExceptions = (PTR2INT(data[0]) & TCL_ALLOW_EXCEPTIONS); @@ -4531,18 +4764,18 @@ return result; } static int TEOV_Error( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *listPtr; const char *cmdString; - size_t cmdLen; + Tcl_Size cmdLen; int objc = PTR2INT(data[0]); Tcl_Obj **objv = (Tcl_Obj **)data[1]; if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { /* @@ -4550,11 +4783,11 @@ * error log: get it out of the itemPtr. The details depend on the * type. */ listPtr = Tcl_NewListObj(objc, objv); - cmdString = TclGetStringFromObj(listPtr, &cmdLen); + cmdString = Tcl_GetStringFromObj(listPtr, &cmdLen); Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen); Tcl_DecrRefCount(listPtr); } iPtr->flags &= ~ERR_ALREADY_LOGGED; return result; @@ -4567,11 +4800,11 @@ Tcl_Obj *const objv[], Namespace *lookupNsPtr) { Command * cmdPtr; Interp *iPtr = (Interp *) interp; - int i, newObjc, handlerObjc; + Tcl_Size i, newObjc, handlerObjc; Tcl_Obj **newObjv, **handlerObjv; CallFrame *varFramePtr = iPtr->varFramePtr; Namespace *currNsPtr = NULL;/* Used to check for and invoke any registered * unknown command handler for the current * namespace (TIP 181). */ @@ -4595,15 +4828,15 @@ Tcl_IncrRefCount(currNsPtr->unknownHandlerPtr); } /* * Get the list of words for the unknown handler and allocate enough space - * to hold both the handler prefix and all words of the command invokation + * to hold both the handler prefix and all words of the command invocation * itself. */ - Tcl_ListObjGetElements(NULL, currNsPtr->unknownHandlerPtr, + TclListObjGetElementsM(NULL, currNsPtr->unknownHandlerPtr, &handlerObjc, &handlerObjv); newObjc = objc + handlerObjc; newObjv = (Tcl_Obj **)TclStackAlloc(interp, sizeof(Tcl_Obj *) * newObjc); /* @@ -4631,11 +4864,11 @@ 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); + TclGetString(objv[0]), (void *)NULL); /* * Release any resources we locked and allocated during the handler * call. */ @@ -4657,11 +4890,11 @@ return TclNREvalObjv(interp, newObjc, newObjv, TCL_EVAL_NOERR, NULL); } static int TEOV_NotFoundCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int objc = PTR2INT(data[0]); @@ -4694,13 +4927,13 @@ int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Command *cmdPtr = *cmdPtrPtr; - size_t length, newEpoch, cmdEpoch = cmdPtr->cmdEpoch; + Tcl_Size length, newEpoch, cmdEpoch = cmdPtr->cmdEpoch; int traceCode = TCL_OK; - const char *command = TclGetStringFromObj(commandPtr, &length); + const char *command = Tcl_GetStringFromObj(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 @@ -4737,22 +4970,22 @@ return TCL_OK; } static int TEOV_RunLeaveTraces( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int traceCode = TCL_OK; int objc = PTR2INT(data[0]); Tcl_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); + Tcl_Size length; + const char *command = Tcl_GetStringFromObj(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); @@ -4830,15 +5063,413 @@ Tcl_Interp *interp, /* Interpreter in which to lookup variables, * execute nested commands, and report * errors. */ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to * evaluate and concatenate. */ - size_t count) /* Number of tokens to consider at tokenPtr. + Tcl_Size count) /* Number of tokens to consider at tokenPtr. * Must be at least 1. */ { return TclSubstTokens(interp, tokenPtr, count, /* numLeftPtr */ NULL, 1, - NULL, NULL); + NULL, NULL, 0); +} + +/* + *---------------------------------------------------------------------- + * + * TclEvalScriptTokens -- + * + * + * Results: + * + * Side effects: + * + * TIP #280 : Keep public API, internally extended API. + *---------------------------------------------------------------------- + */ + +int +TclEvalScriptTokens( + Tcl_Interp *interp, + Tcl_Token *tokenPtr, + Tcl_Size length, + int flags, + Tcl_Size line, + 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. + */ +{ + Tcl_Size numCommands = tokenPtr->numComponents; + Tcl_Token *scriptTokenPtr = tokenPtr; + Interp *iPtr = (Interp *) interp; + int code = TCL_OK; + Tcl_Size objLength = 20; + int *expand, *expandStack; + Tcl_Size *lines, *lineSpace, *linesStack; + Tcl_Obj **objvSpace, **stackObjArray; + const char *cmdString = scriptTokenPtr->start; + Tcl_Size cmdSize = scriptTokenPtr->size; + CmdFrame *eeFramePtr; /* TIP #280 Structures for tracking of command + * locations. */ + int allowExceptions = 1; + 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 (iPtr->numLevels == 0) { + allowExceptions = iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS; + } + + if (length == 0) { + Tcl_Panic("EvalScriptTokens: can't eval zero tokens"); + } + if (tokenPtr->type != TCL_TOKEN_SCRIPT) { + Tcl_Panic("EvalScriptTokens: invalid token array, expected script"); + } + tokenPtr++; length--; + if (numCommands) { + TclAdvanceLines(&line, scriptTokenPtr->start, tokenPtr->start); + TclAdvanceContinuations(&line, &clNext, tokenPtr->start - outerScript); + } + + if (length == 0) { + return TclInterpReady(interp); + } + + /* + * TIP #280 Initialize tracking. Do not push on the frame stack yet. + * + * We open a new context, either for a sourced script, or 'eval'. + * For sourced files we always have a path object, even if nothing was + * specified in the interp itself. That makes code using it simpler as + * NULL checks can be left out. Sourced file without path in the + * 'scriptFile' is possible during Tcl initialization. + */ + + eeFramePtr = (CmdFrame *)TclStackAlloc(interp, sizeof(CmdFrame)); + if (iPtr->evalFlags & TCL_EVAL_FILE) { + /* + * Set up for a sourced file. + */ + + eeFramePtr->type = TCL_LOCATION_SOURCE; + + if (iPtr->scriptFile) { + /* + * Normalization here, to have the correct pwd. Should have + * negligible impact on performance, as the norm should have been + * done already by the 'source' invoking us, and it caches the + * result. + */ + + Tcl_Obj *norm = Tcl_FSGetNormalizedPath(interp, iPtr->scriptFile); + + if (norm == NULL) { + /* + * Error message in the interp result. + */ + TclStackFree(interp, eeFramePtr); + return TCL_ERROR; + } + eeFramePtr->data.eval.path = norm; + } else { + TclNewLiteralStringObj(eeFramePtr->data.eval.path, ""); + } + Tcl_IncrRefCount(eeFramePtr->data.eval.path); + } else { + /* + * Set up for plain eval. + */ + + eeFramePtr->type = TCL_LOCATION_EVAL; + eeFramePtr->data.eval.path = NULL; + } + + eeFramePtr->level = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level + 1 : 1; + eeFramePtr->framePtr = iPtr->framePtr; + eeFramePtr->nextPtr = iPtr->cmdFramePtr; + eeFramePtr->nline = 0; + eeFramePtr->line = NULL; + eeFramePtr->cmdObj = NULL; + + iPtr->cmdFramePtr = eeFramePtr; + iPtr->evalFlags = 0; + objvSpace = stackObjArray = (Tcl_Obj **) + TclStackAlloc(interp, objLength * sizeof(Tcl_Obj *)); + expand = expandStack = (int *) + TclStackAlloc(interp, objLength * sizeof(int)); + lineSpace = linesStack = (Tcl_Size *) + TclStackAlloc(interp, objLength * sizeof(Tcl_Size)); + while (numCommands-- && (code == TCL_OK)) { + int expandRequested = 0; + Tcl_Size objc, objectsNeeded = 0; + Tcl_Size numWords = tokenPtr->numComponents; + Tcl_Obj **objv; + Tcl_Token *commandTokenPtr = tokenPtr; + + /* + * 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 = commandTokenPtr->start; + Tcl_Size *wordCLNext = clNext; + + if (length == 0) { + Tcl_Panic("EvalScriptTokens: overran token array"); + } + if (tokenPtr->type != TCL_TOKEN_CMD) { + Tcl_Panic("EvalScriptTokens: invalid token array, expected cmd"); + } + tokenPtr++; length--; + + if (numWords == 0) continue; + if (numWords > objLength) { + if (expand != expandStack) { + Tcl_Free(expand); + } + expand = (int *)Tcl_Alloc(numWords * sizeof(int)); + if (objvSpace != stackObjArray) { + Tcl_Free(objvSpace); + } + objvSpace = (Tcl_Obj **)Tcl_Alloc(numWords * sizeof(Tcl_Obj *)); + if (lineSpace != linesStack) { + Tcl_Free(lineSpace); + } + lineSpace = (Tcl_Size *)Tcl_Alloc(numWords * sizeof(Tcl_Size)); + objLength = numWords; + } + + objv = objvSpace; + lines = lineSpace; + iPtr->cmdFramePtr = eeFramePtr->nextPtr; + for (objc = 0; objc < numWords; + objc++, length -= (tokenPtr->numComponents + 1), + tokenPtr += tokenPtr->numComponents+1) { + if (length == 0) { + Tcl_Panic("EvalScriptTokens: overran token array"); + } + if (!(tokenPtr->type & (TCL_TOKEN_WORD + | TCL_TOKEN_SIMPLE_WORD | TCL_TOKEN_EXPAND_WORD))) { + Tcl_Panic("EvalScriptTokens: invalid token array, expected word: %d: %.*s", tokenPtr->type, (int)tokenPtr->size, tokenPtr->start); + } + if (length < tokenPtr->numComponents + 1) { + Tcl_Panic("EvalScriptTokens: overran token array"); + } + + /* + * TIP #280. Track lines to current word. Save the information + * on a per-word basis, signaling dynamic words as needed. + * Make the information available to the recursively called + * evaluator as well, including the type of context (source + * vs. eval). + */ + + TclAdvanceLines(&wordLine, wordStart, tokenPtr->start); + TclAdvanceContinuations (&wordLine, &wordCLNext, + tokenPtr->start - outerScript); + wordStart = tokenPtr->start; + + lines[objc] = TclWordKnownAtCompileTime(tokenPtr, NULL) + ? wordLine : -1; + + if (eeFramePtr->type == TCL_LOCATION_SOURCE) { + iPtr->evalFlags |= TCL_EVAL_FILE; + } + + code = TclSubstTokens(interp, tokenPtr+1, tokenPtr->numComponents, + NULL, wordLine, wordCLNext, outerScript, flags); + + iPtr->evalFlags = 0; + + if (code != TCL_OK) { + break; + } + objv[objc] = Tcl_GetObjResult(interp); + Tcl_IncrRefCount(objv[objc]); + if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) { + Tcl_Size numElements; + + code = TclListObjLengthM(interp, objv[objc], &numElements); + if (code == TCL_ERROR) { + /* + * Attempt to expand a non-list + */ + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (expanding word %ld)", objc)); + objc++; + break; + } + expandRequested = 1; + expand[objc] = 1; + objectsNeeded += (numElements ? numElements : 1); + } else { + expand[objc] = 0; + objectsNeeded++; + } + + if (wordCLNext) { + TclContinuationsEnterDerived (objv[objc], + wordStart - outerScript, wordCLNext); + } + } + 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; + int inPlaceCopy = 1; + + if (objectsNeeded > objLength) { + inPlaceCopy = 0; + objv = objvSpace = (Tcl_Obj **)Tcl_Alloc(objectsNeeded * sizeof(Tcl_Obj*)); + lines = lineSpace = (Tcl_Size *)Tcl_Alloc(objectsNeeded * sizeof (Tcl_Size)); + } + + objc = 0; + while (wordIdx--) { + if (expand[wordIdx]) { + Tcl_Size numElements; + Tcl_Obj **elements, *temp = copy[wordIdx]; + TclListObjGetElementsM(NULL, temp, &numElements, + &elements); + objc += numElements; + while (numElements--) { + lines[objIdx] = -1; + objv[objIdx--] = elements[numElements]; + Tcl_IncrRefCount(elements[numElements]); + } + Tcl_DecrRefCount(temp); + } else { + lines[objIdx] = lcopy[wordIdx]; + objv[objIdx--] = copy[wordIdx]; + objc++; + } + } + objv += objIdx+1; + + if (!inPlaceCopy && (copy != stackObjArray)) { + Tcl_Free(copy); + Tcl_Free(lcopy); + } + } + + /* + * Execute the command and free the objects for its words. + * + * TIP #280: Remember the command itself for 'info frame'. + * Here is where we put our frame on the stack of frames too. + * _After_ the nested commands have been executed. + */ + + eeFramePtr->cmd = commandTokenPtr->start; + eeFramePtr->len = commandTokenPtr->size; + eeFramePtr->nline = objc; + eeFramePtr->line = lines; + + TclArgumentEnter(interp, objv, objc, eeFramePtr); + code = Tcl_EvalObjv(interp, objc, objv, + flags|TCL_EVAL_NOERR|TCL_EVAL_SOURCE_IN_FRAME); + TclArgumentRelease(interp, objv, objc); + + eeFramePtr->line = NULL; + eeFramePtr->nline = 0; + if (eeFramePtr->cmdObj) { + Tcl_DecrRefCount(eeFramePtr->cmdObj); + eeFramePtr->cmdObj = NULL; + } + + error: + while (objc > 0) { + Tcl_DecrRefCount(objv[--objc]); + } + cmdString = commandTokenPtr->start; + cmdSize = commandTokenPtr->size; + + /* + * TIP #280 Track Lines. Now we track how many lines were in the + * executed command. + */ + + if (numCommands) { + TclAdvanceLines(&line, commandTokenPtr->start, tokenPtr->start); + } + } + if (length && (code == TCL_OK)) { + code = TclSubstTokens(interp, tokenPtr, length, NULL, line, clNext, + outerScript, flags); + } + if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { + Tcl_LogCommandInfo(interp, scriptTokenPtr->start, cmdString, cmdSize); + } + iPtr->flags &= ~ERR_ALREADY_LOGGED; + if (lineSpace != linesStack) { + Tcl_Free(lineSpace); + } + TclStackFree(interp, linesStack); + if (expand != expandStack) { + Tcl_Free(expand); + } + TclStackFree(interp, expandStack); + if (objvSpace != stackObjArray) { + Tcl_Free(objvSpace); + } + TclStackFree(interp, stackObjArray); + + if (iPtr->numLevels == 0) { + if (code == TCL_RETURN) { + code = TclUpdateReturnInfo(iPtr); + } + if ((code != TCL_OK) && (code != TCL_ERROR) && !allowExceptions) { + ProcessUnexpectedResult(interp, code); + code = TCL_ERROR; + Tcl_LogCommandInfo(interp, scriptTokenPtr->start, + cmdString, cmdSize); + } + } + /* + * TIP #280. Release the local CmdFrame, and its contents. + */ + + iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr; + if (eeFramePtr->type == TCL_LOCATION_SOURCE) { + Tcl_DecrRefCount(eeFramePtr->data.eval.path); + } + TclStackFree(interp, eeFramePtr); + return code; } /* *---------------------------------------------------------------------- * @@ -4863,11 +5494,11 @@ int Tcl_EvalEx( Tcl_Interp *interp, /* Interpreter in which to evaluate the * script. Also used for error reporting. */ const char *script, /* First character of script to evaluate. */ - size_t numBytes, /* Number of bytes in script. If -1, the + Tcl_Size numBytes, /* Number of bytes in script. If -1, the * script consists of all bytes up to the * first null character. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL is currently supported. */ @@ -4878,458 +5509,42 @@ int TclEvalEx( Tcl_Interp *interp, /* Interpreter in which to evaluate the * script. Also used for error reporting. */ const char *script, /* First character of script to evaluate. */ - size_t numBytes, /* Number of bytes in script. If -1, the + Tcl_Size numBytes, /* Number of bytes in script. If -1, the * script consists of all bytes up to the - * first NUL character. */ - int flags, /* Collection of OR-ed bits that control the - * evaluation of the script. Only - * TCL_EVAL_GLOBAL is currently supported. */ - int line, /* The line the script starts on. */ - int *clNextOuter, /* Information about an outer context for */ - 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; - } - - /* - * Each iteration through the following loop parses the next command from - * the script and then executes it. - */ - - objv = objvSpace = stackObjArray; - lines = lineSpace = linesStack; - expand = expandStack; - p = script; - bytesLeft = numBytes; - - /* - * TIP #280 Initialize tracking. Do not push on the frame stack yet. - * - * We open a new context, either for a sourced script, or 'eval'. - * For sourced files we always have a path object, even if nothing was - * specified in the interp itself. That makes code using it simpler as - * NULL checks can be left out. Sourced file without path in the - * 'scriptFile' is possible during Tcl initialization. - */ - - eeFramePtr->level = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level + 1 : 1; - eeFramePtr->framePtr = iPtr->framePtr; - eeFramePtr->nextPtr = iPtr->cmdFramePtr; - eeFramePtr->nline = 0; - eeFramePtr->line = NULL; - eeFramePtr->cmdObj = NULL; - - iPtr->cmdFramePtr = eeFramePtr; - if (iPtr->evalFlags & TCL_EVAL_FILE) { - /* - * Set up for a sourced file. - */ - - eeFramePtr->type = TCL_LOCATION_SOURCE; - - if (iPtr->scriptFile) { - /* - * Normalization here, to have the correct pwd. Should have - * negligible impact on performance, as the norm should have been - * done already by the 'source' invoking us, and it caches the - * result. - */ - - Tcl_Obj *norm = Tcl_FSGetNormalizedPath(interp, iPtr->scriptFile); - - if (norm == NULL) { - /* - * Error message in the interp result. - */ - - code = TCL_ERROR; - goto error; - } - eeFramePtr->data.eval.path = norm; - } else { - TclNewLiteralStringObj(eeFramePtr->data.eval.path, ""); - } - Tcl_IncrRefCount(eeFramePtr->data.eval.path); - } else { - /* - * Set up for plain eval. - */ - - eeFramePtr->type = TCL_LOCATION_EVAL; - eeFramePtr->data.eval.path = NULL; - } - - iPtr->evalFlags = 0; - do { - if (Tcl_ParseCommand(interp, p, bytesLeft, 0, parsePtr) != TCL_OK) { - code = TCL_ERROR; - Tcl_LogCommandInfo(interp, script, parsePtr->commandStart, - parsePtr->term + 1 - parsePtr->commandStart); - goto posterror; - } - - /* - * TIP #280 Track lines. The parser may have skipped text till it - * found the command we are now at. We have to count the lines in this - * block, and do not forget invisible continuation lines. - */ - - TclAdvanceLines(&line, p, parsePtr->commandStart); - TclAdvanceContinuations(&line, &clNext, - parsePtr->commandStart - outerScript); - - gotParse = 1; - if (parsePtr->numWords > 0) { - /* - * 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). - */ - - TclAdvanceLines(&wordLine, wordStart, tokenPtr->start); - TclAdvanceContinuations(&wordLine, &wordCLNext, - tokenPtr->start - outerScript); - wordStart = tokenPtr->start; - - lines[objectsUsed] = TclWordKnownAtCompileTime(tokenPtr, NULL) - ? wordLine : -1; - - if (eeFramePtr->type == TCL_LOCATION_SOURCE) { - iPtr->evalFlags |= TCL_EVAL_FILE; - } - - code = TclSubstTokens(interp, tokenPtr+1, - tokenPtr->numComponents, NULL, wordLine, - wordCLNext, outerScript); - - iPtr->evalFlags = 0; - - if (code != TCL_OK) { - break; - } - objv[objectsUsed] = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(objv[objectsUsed]); - if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) { - int numElements; - - 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]); - } - Tcl_DecrRefCount(temp); - } else { - lines[objIdx] = lcopy[wordIdx]; - objv[objIdx--] = copy[wordIdx]; - objectsUsed++; - } - } - objv += objIdx+1; - - if (copy != stackObjArray) { - Tcl_Free(copy); - } - if (lcopy != linesStack) { - Tcl_Free(lcopy); - } - } - - /* - * Execute the command and free the objects for its words. - * - * TIP #280: Remember the command itself for 'info frame'. We - * shorten the visible command by one char to exclude the - * termination character, if necessary. Here is where we put our - * frame on the stack of frames too. _After_ the nested commands - * have been executed. - */ - - eeFramePtr->cmd = parsePtr->commandStart; - eeFramePtr->len = parsePtr->commandSize; - - if (parsePtr->term == - parsePtr->commandStart + parsePtr->commandSize - 1) { - eeFramePtr->len--; - } - - eeFramePtr->nline = objectsUsed; - eeFramePtr->line = lines; - - TclArgumentEnter(interp, objv, objectsUsed, eeFramePtr); - code = Tcl_EvalObjv(interp, objectsUsed, objv, - TCL_EVAL_NOERR | TCL_EVAL_SOURCE_IN_FRAME); - TclArgumentRelease(interp, objv, objectsUsed); - - eeFramePtr->line = NULL; - eeFramePtr->nline = 0; - if (eeFramePtr->cmdObj) { - Tcl_DecrRefCount(eeFramePtr->cmdObj); - eeFramePtr->cmdObj = NULL; - } - - if (code != TCL_OK) { - goto error; - } - for (i = 0; i < objectsUsed; i++) { - Tcl_DecrRefCount(objv[i]); - } - objectsUsed = 0; - if (objvSpace != stackObjArray) { - Tcl_Free(objvSpace); - objvSpace = stackObjArray; - Tcl_Free(lineSpace); - lineSpace = linesStack; - } - - /* - * Free expand separately since objvSpace could have been - * reallocated above. - */ - - if (expand != expandStack) { - Tcl_Free(expand); - expand = expandStack; - } - } - - /* - * Advance to the next command in the script. - * - * TIP #280 Track Lines. Now we track how many lines were in the - * executed command. - */ - - next = parsePtr->commandStart + parsePtr->commandSize; - bytesLeft -= next - p; - p = next; - TclAdvanceLines(&line, parsePtr->commandStart, p); - Tcl_FreeParse(parsePtr); - gotParse = 0; - } while (bytesLeft > 0); - iPtr->varFramePtr = savedVarFramePtr; - code = TCL_OK; - goto cleanup_return; - - error: - /* - * Generate and log various pieces of error information. - */ - - if (iPtr->numLevels == 0) { - if (code == TCL_RETURN) { - code = TclUpdateReturnInfo(iPtr); - } - if ((code != TCL_OK) && (code != TCL_ERROR) && !allowExceptions) { - ProcessUnexpectedResult(interp, code); - code = TCL_ERROR; - } - } - if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { - commandLength = parsePtr->commandSize; - if (parsePtr->term == parsePtr->commandStart + commandLength - 1) { - /* - * The terminator character (such as ; or ]) of the command where - * the error occurred is the last character in the parsed command. - * Reduce the length by one so that the error message doesn't - * include the terminator character. - */ - - commandLength -= 1; - } - Tcl_LogCommandInfo(interp, script, parsePtr->commandStart, - commandLength); - } - posterror: - iPtr->flags &= ~ERR_ALREADY_LOGGED; - - /* - * Then free resources that had been allocated to the command. - */ - - for (i = 0; i < objectsUsed; i++) { - Tcl_DecrRefCount(objv[i]); - } - if (gotParse) { - Tcl_FreeParse(parsePtr); - } - if (objvSpace != stackObjArray) { - Tcl_Free(objvSpace); - Tcl_Free(lineSpace); - } - if (expand != expandStack) { - Tcl_Free(expand); - } - iPtr->varFramePtr = savedVarFramePtr; - - cleanup_return: - /* - * TIP #280. Release the local CmdFrame, and its contents. - */ - - iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr; - if (eeFramePtr->type == TCL_LOCATION_SOURCE) { - Tcl_DecrRefCount(eeFramePtr->data.eval.path); - } - TclStackFree(interp, linesStack); - TclStackFree(interp, expandStack); - TclStackFree(interp, stackObjArray); - TclStackFree(interp, eeFramePtr); - TclStackFree(interp, parsePtr); - + * first null 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 + * EvalTokensStandard(), 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. + */ +{ + Tcl_Token *lastTokenPtr, *tokensPtr = TclParseScript(interp, + script, numBytes, /* flags */ 0, &lastTokenPtr, NULL); + int code = TclEvalScriptTokens(interp, tokensPtr, + 1 + (Tcl_Size)(lastTokenPtr - tokensPtr), flags, line, + clNextOuter, outerScript); + Tcl_Free(tokensPtr); return code; } /* *---------------------------------------------------------------------- @@ -5349,11 +5564,11 @@ *---------------------------------------------------------------------- */ void TclAdvanceLines( - int *line, + Tcl_Size *line, const char *start, const char *end) { const char *p; @@ -5384,12 +5599,12 @@ *---------------------------------------------------------------------- */ void TclAdvanceContinuations( - int *line, - int **clNextPtrPtr, + Tcl_Size *line, + Tcl_Size **clNextPtrPtr, int loc) { /* * Track the invisible continuation lines embedded in a script, if any. * Here they are just spaces (already). They were removed by @@ -5456,12 +5671,12 @@ for (i = 1; i < objc; i++) { /* * Ignore argument words without line information (= dynamic). If they * are variables they may have location information associated with - * that, either through globally recorded 'set' invokations, or - * literals in bytecode. Eitehr way there is no need to record + * that, either through globally recorded 'set' invocations, or + * literals in bytecode. Either way there is no need to record * something here. */ if (cfPtr->line[i] < 0) { continue; @@ -5520,11 +5735,11 @@ int i; for (i = 1; i < objc; i++) { CFWord *cfwPtr; Tcl_HashEntry *hPtr = - Tcl_FindHashEntry(iPtr->lineLAPtr, (char *) objv[i]); + Tcl_FindHashEntry(iPtr->lineLAPtr, objv[i]); if (!hPtr) { continue; } cfwPtr = (CFWord *)Tcl_GetHashValue(hPtr); @@ -5563,20 +5778,20 @@ Tcl_Interp *interp, Tcl_Obj *objv[], int objc, void *codePtr, CmdFrame *cfPtr, - int cmd, - size_t pc) + 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, (char *) codePtr); + Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr); if (!hePtr) { return; } eclPtr = (ExtCmdLoc *)Tcl_GetHashValue(hePtr); @@ -5678,11 +5893,11 @@ CFWordBC *cfwPtr = (CFWordBC *) cfPtr->litarg; while (cfwPtr) { CFWordBC *nextPtr = cfwPtr->nextPtr; Tcl_HashEntry *hPtr = - Tcl_FindHashEntry(iPtr->lineLABCPtr, (char *) cfwPtr->obj); + Tcl_FindHashEntry(iPtr->lineLABCPtr, cfwPtr->obj); CFWordBC *xPtr = (CFWordBC *)Tcl_GetHashValue(hPtr); if (xPtr != cfwPtr) { Tcl_Panic("TclArgumentBC Enter/Release Mismatch"); } @@ -5743,11 +5958,11 @@ /* * First look for location information recorded in the argument * stack. That is nearest. */ - hPtr = Tcl_FindHashEntry(iPtr->lineLAPtr, (char *) obj); + hPtr = Tcl_FindHashEntry(iPtr->lineLAPtr, obj); if (hPtr) { CFWord *cfwPtr = (CFWord *)Tcl_GetHashValue(hPtr); *wordPtr = cfwPtr->word; *cfPtrPtr = cfwPtr->framePtr; @@ -5757,11 +5972,11 @@ /* * Check if the Tcl_Obj has location information as a bytecode literal, in * that stack. */ - hPtr = Tcl_FindHashEntry(iPtr->lineLABCPtr, (char *) obj); + hPtr = Tcl_FindHashEntry(iPtr->lineLABCPtr, obj); if (hPtr) { CFWordBC *cfwPtr = (CFWordBC *)Tcl_GetHashValue(hPtr); framePtr = cfwPtr->framePtr; framePtr->data.tebc.pc = (char *) (((ByteCode *) @@ -5844,20 +6059,21 @@ const CmdFrame *invoker, /* Frame of the command doing the eval. */ int word) /* Index of the word which is in objPtr. */ { Interp *iPtr = (Interp *) interp; int result; + int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS); /* * This function consists of three independent blocks for: direct * evaluation of canonical lists, compilation and bytecode execution and * finally direct evaluation. Precisely one of these blocks will be run. */ if (TclListObjIsCanonical(objPtr)) { CmdFrame *eoFramePtr = NULL; - int objc; + Tcl_Size objc; Tcl_Obj *listPtr, **objv; /* * Canonical List Optimization: In this case, we * can safely use Tcl_EvalObjv instead and get an appreciable @@ -5922,11 +6138,11 @@ TclMarkTailcall(interp); TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr, objPtr, NULL); - TclListObjGetElements(NULL, listPtr, &objc, &objv); + TclListObjGetElementsM(NULL, listPtr, &objc, &objv); return TclNREvalObjv(interp, objc, objv, flags, NULL); } if (!(flags & TCL_EVAL_DIRECT)) { /* @@ -5934,11 +6150,10 @@ * * TIP #280 The invoker provides us with the context for the script. * We transfer this to the byte code compiler. */ - int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS); ByteCode *codePtr; CallFrame *savedVarFramePtr = NULL; /* Saves old copy of * iPtr->varFramePtr in case * TCL_EVAL_GLOBAL was set. */ @@ -5961,13 +6176,11 @@ /* * We're not supposed to use the compiler or byte-code * interpreter. Let Tcl_EvalEx evaluate the command directly (and * probably more slowly). */ - - const char *script; - size_t numSrcBytes; + Tcl_Token *lastTokenPtr, *tokensPtr; /* * 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. @@ -5983,30 +6196,34 @@ * continuation line information of the caller, in case we are * executing nested commands in the eval/direct path. */ ContLineLoc *saveCLLocPtr = iPtr->scriptCLLocPtr; + Tcl_Obj *copyPtr = TclTokensCopy(objPtr); assert(invoker == NULL); iPtr->scriptCLLocPtr = TclContinuationsGet(objPtr); Tcl_IncrRefCount(objPtr); - script = TclGetStringFromObj(objPtr, &numSrcBytes); - result = Tcl_EvalEx(interp, script, numSrcBytes, flags); + tokensPtr = TclGetTokensFromObj(copyPtr, &lastTokenPtr); + result = TclEvalScriptTokens(interp, tokensPtr, + 1 + (Tcl_Size)(lastTokenPtr - tokensPtr), flags, 1, NULL, + tokensPtr[0].start); - TclDecrRefCount(objPtr); + Tcl_DecrRefCount(objPtr); + Tcl_DecrRefCount(copyPtr); iPtr->scriptCLLocPtr = saveCLLocPtr; return result; } } static int TEOEx_ByteCodeCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; CallFrame *savedVarFramePtr = (CallFrame *)data[0]; @@ -6017,15 +6234,15 @@ if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } if ((result != TCL_OK) && (result != TCL_ERROR) && !allowExceptions) { const char *script; - size_t numSrcBytes; + Tcl_Size numSrcBytes; ProcessUnexpectedResult(interp, result); result = TCL_ERROR; - script = TclGetStringFromObj(objPtr, &numSrcBytes); + script = Tcl_GetStringFromObj(objPtr, &numSrcBytes); Tcl_LogCommandInfo(interp, script, script, numSrcBytes); } /* * We are returning to level 0, so should call TclResetCancellation. @@ -6048,11 +6265,11 @@ return result; } static int TEOEx_ListCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *listPtr = (Tcl_Obj *)data[0]; @@ -6110,12 +6327,12 @@ "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); + snprintf(buf, sizeof(buf), "%d", returnCode); + Tcl_SetErrorCode(interp, "TCL", "UNEXPECTED_RESULT_CODE", buf, (void *)NULL); } /* *--------------------------------------------------------------------------- * @@ -6241,18 +6458,18 @@ long *ptr) /* Where to store long result. */ { Tcl_Obj *resultPtr; int result, type; double d; - ClientData internalPtr; + void *internalPtr; result = Tcl_ExprObj(interp, objPtr, &resultPtr); if (result != TCL_OK) { return TCL_ERROR; } - if (TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type)!=TCL_OK) { + if (Tcl_GetNumberFromObj(interp, resultPtr, &internalPtr, &type)!=TCL_OK) { return TCL_ERROR; } switch (type) { case TCL_NUMBER_DOUBLE: { @@ -6287,18 +6504,18 @@ Tcl_Obj *objPtr, /* Expression to evaluate. */ double *ptr) /* Where to store double result. */ { Tcl_Obj *resultPtr; int result, type; - ClientData internalPtr; + void *internalPtr; result = Tcl_ExprObj(interp, objPtr, &resultPtr); if (result != TCL_OK) { return TCL_ERROR; } - result = TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type); + result = Tcl_GetNumberFromObj(interp, resultPtr, &internalPtr, &type); if (result == TCL_OK) { switch (type) { case TCL_NUMBER_NAN: #ifndef ACCEPT_NAN result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr); @@ -6402,20 +6619,18 @@ int TclObjInvoke( Tcl_Interp *interp, /* Interpreter in which command is to be * invoked. */ - int objc, /* Count of arguments. */ + Tcl_Size objc, /* Count of arguments. */ Tcl_Obj *const objv[], /* Argument objects; objv[0] points to the * name of the command to invoke. */ int flags) /* Combination of flags controlling the call: * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN, * or TCL_INVOKE_NO_TRACEBACK. */ { - if (interp == NULL) { - return TCL_ERROR; - } + /* make whole thing a call to Tcl_EvalObjv */ if ((objc < 1) || (objv == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal argument vector", -1)); return TCL_ERROR; } @@ -6445,11 +6660,11 @@ } if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid hidden command name \"%s\"", cmdName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN", cmdName, - NULL); + (void *)NULL); return TCL_ERROR; } cmdPtr = (Command *)Tcl_GetHashValue(hPtr); /* @@ -6468,11 +6683,11 @@ return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NORESOLVE, cmdPtr); } static int NRPostInvoke( - TCL_UNUSED(ClientData *), + TCL_UNUSED(void **), Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *)interp; @@ -6551,12 +6766,12 @@ 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); + Tcl_Size length; + const char *message = Tcl_GetStringFromObj(objPtr, &length); Interp *iPtr = (Interp *) interp; Tcl_IncrRefCount(objPtr); /* @@ -6567,11 +6782,11 @@ iPtr->flags |= ERR_LEGACY_COPY; if (iPtr->errorInfo == NULL) { iPtr->errorInfo = iPtr->objResultPtr; Tcl_IncrRefCount(iPtr->errorInfo); if (!iPtr->errorCode) { - Tcl_SetErrorCode(interp, "NONE", NULL); + Tcl_SetErrorCode(interp, "NONE", (void *)NULL); } } /* * Now append "message" to the end of errorInfo. @@ -6652,18 +6867,18 @@ * None. * *---------------------------------------------------------------------- */ -int +Tcl_Size Tcl_SetRecursionLimit( Tcl_Interp *interp, /* Interpreter whose nesting limit is to be * set. */ - int depth) /* New value for maximimum depth. */ + Tcl_Size depth) /* New value for maximimum depth. */ { Interp *iPtr = (Interp *) interp; - int old; + Tcl_Size old; old = iPtr->maxNestingDepth; if (depth > 0) { iPtr->maxNestingDepth = depth; } @@ -6772,11 +6987,11 @@ return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d); #ifdef ACCEPT_NAN if (code != TCL_OK) { - const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType); if (irPtr) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } @@ -6812,11 +7027,11 @@ return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d); #ifdef ACCEPT_NAN if (code != TCL_OK) { - const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType); if (irPtr) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } @@ -6840,11 +7055,11 @@ TCL_UNUSED(void *), Tcl_Interp *interp, /* The interpreter in which to execute. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter list. */ { - ClientData ptr; + void *ptr; int type; double d; Tcl_WideInt w; mp_int big; int exact = 0; /* Flag ==1 if the argument can be represented @@ -6861,11 +7076,11 @@ /* * Make sure that the arg is a number. */ - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } switch (type) { case TCL_NUMBER_NAN: @@ -6935,11 +7150,11 @@ 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); + "domain error: argument not in valid range", (void *)NULL); return TCL_ERROR; } static int ExprSqrtFunc( @@ -6958,11 +7173,11 @@ return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d); #ifdef ACCEPT_NAN if (code != TCL_OK) { - const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType); if (irPtr) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } @@ -6969,11 +7184,11 @@ } #endif if (code != TCL_OK) { return TCL_ERROR; } - if ((d >= 0.0) && TclIsInfinite(d) + if ((d >= 0.0) && isinf(d) && (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK)) { mp_int root; mp_err err; err = mp_init(&root); @@ -6993,11 +7208,11 @@ return TCL_OK; } static int ExprUnaryFunc( - ClientData clientData, /* Contains the address of a function that + void *clientData, /* Contains the address of a function that * takes one double argument and returns a * double result. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ @@ -7012,11 +7227,11 @@ return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d); #ifdef ACCEPT_NAN if (code != TCL_OK) { - const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType); if (irPtr) { d = irPtr->doubleValue; Tcl_ResetResult(interp); code = TCL_OK; @@ -7034,16 +7249,16 @@ CheckDoubleResult( Tcl_Interp *interp, double dResult) { #ifndef ACCEPT_NAN - if (TclIsNaN(dResult)) { + if (isnan(dResult)) { TclExprFloatError(interp, dResult); return TCL_ERROR; } #endif - if ((errno == ERANGE) && ((dResult == 0.0) || TclIsInfinite(dResult))) { + if ((errno == ERANGE) && ((dResult == 0.0) || isinf(dResult))) { /* * When ERANGE signals under/overflow, just accept 0.0 or +/-Inf */ } else if (errno != 0) { /* @@ -7057,11 +7272,11 @@ return TCL_OK; } static int ExprBinaryFunc( - ClientData clientData, /* Contains the address of a function that + void *clientData, /* Contains the address of a function that * takes two double arguments and returns a * double result. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ @@ -7076,11 +7291,11 @@ return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d1); #ifdef ACCEPT_NAN if (code != TCL_OK) { - const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType); if (irPtr) { d1 = irPtr->doubleValue; Tcl_ResetResult(interp); code = TCL_OK; @@ -7091,11 +7306,11 @@ return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[2], &d2); #ifdef ACCEPT_NAN if (code != TCL_OK) { - const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objv[1], &tclDoubleType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objv[1], &tclDoubleType); if (irPtr) { d2 = irPtr->doubleValue; Tcl_ResetResult(interp); code = TCL_OK; @@ -7115,20 +7330,20 @@ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Parameter vector. */ { - ClientData ptr; + void *ptr; int type; mp_int big; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_INT) { Tcl_WideInt l = *((const Tcl_WideInt *) ptr); @@ -7135,12 +7350,12 @@ if (l > 0) { goto unChanged; } else if (l == 0) { if (TclHasStringRep(objv[1])) { - size_t numBytes; - const char *bytes = TclGetStringFromObj(objv[1], &numBytes); + Tcl_Size numBytes; + const char *bytes = Tcl_GetStringFromObj(objv[1], &numBytes); while (numBytes) { if (*bytes == '-') { Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0)); return TCL_OK; @@ -7148,11 +7363,20 @@ bytes++; numBytes--; } } goto unChanged; } else if (l == WIDE_MIN) { - if (mp_init_i64(&big, l) != MP_OKAY) { + 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)); @@ -7243,11 +7467,11 @@ MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetDoubleFromObj(interp, objv[1], &dResult) != TCL_OK) { #ifdef ACCEPT_NAN - if (TclHasIntRep(objv[1], &tclDoubleType)) { + if (TclHasInternalRep(objv[1], &tclDoubleType)) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } #endif return TCL_ERROR; @@ -7264,17 +7488,17 @@ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { double d; int type; - ClientData ptr; + void *ptr; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_DOUBLE) { d = *((const double *) ptr); @@ -7343,19 +7567,19 @@ int op) /* Comparison direction */ { Tcl_Obj *res; double d; int type, i; - ClientData ptr; + void *ptr; if (objc < 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } res = objv[1]; for (i = 1; i < objc; i++) { - if (TclGetNumberFromObj(interp, objv[i], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[i], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { /* * Get the error message for NaN. @@ -7420,19 +7644,19 @@ /* * To ensure different seeds in different threads (bug #416643), * take into consideration the thread this interp is running in. */ - iPtr->randSeed = TclpGetClicks() + (PTR2INT(Tcl_GetCurrentThread())<<12); + iPtr->randSeed = TclpGetClicks() + PTR2UINT(Tcl_GetCurrentThread())*4093U; /* * Make sure 1 <= randSeed <= (2^31) - 2. See below. */ - iPtr->randSeed &= 0x7FFFFFFF; - if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7FFFFFFF)) { - iPtr->randSeed ^= 123459876; + iPtr->randSeed &= 0x7FFFFFFFL; + if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7FFFFFFFL)) { + iPtr->randSeed ^= 123459876L; } } /* * Generate the random number using the linear congruential generator @@ -7495,19 +7719,19 @@ * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Parameter vector. */ { double d; - ClientData ptr; + void *ptr; int type; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_DOUBLE) { double fractPart, intPart; @@ -7763,19 +7987,19 @@ * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; - ClientData ptr; + void *ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + 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; @@ -7794,19 +8018,19 @@ * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; - ClientData ptr; + void *ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + 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; @@ -7824,19 +8048,19 @@ * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; - ClientData ptr; + void *ptr; int type, result = 1; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + 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; @@ -7854,19 +8078,19 @@ * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; - ClientData ptr; + void *ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + 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; @@ -7884,19 +8108,19 @@ * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; - ClientData ptr; + void *ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + 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; @@ -7914,29 +8138,29 @@ * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; - ClientData ptr; + void *ptr; int type, result = 0; if (objc != 3) { MathFuncWrongNumArgs(interp, 3, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + 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 (TclGetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { result |= 1; } else { @@ -7956,19 +8180,19 @@ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; Tcl_Obj *objPtr; - ClientData ptr; + void *ptr; int type; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "floatValue"); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { goto gotNaN; } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { @@ -8035,11 +8259,11 @@ } } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s arguments for math function \"%s\"", (found < expected ? "not enough" : "too many"), name)); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (void *)NULL); } #ifdef USE_DTRACE /* *---------------------------------------------------------------------- @@ -8160,11 +8384,11 @@ *---------------------------------------------------------------------- */ static int DTraceCmdReturn( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { char *cmdName = TclGetString((Tcl_Obj *) data[0]); @@ -8205,21 +8429,60 @@ int Tcl_NRCallObjProc( Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, - ClientData clientData, - int objc, + void *clientData, + Tcl_Size objc, Tcl_Obj *const objv[]) { NRE_callback *rootPtr = TOP_CB(interp); TclNRAddCallback(interp, Dispatch, objProc, clientData, INT2PTR(objc), objv); return TclNRRunCallbacks(interp, TCL_OK, rootPtr); } +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 -- * @@ -8230,11 +8493,11 @@ * future calls to Tcl_GetCommandName. * * Side effects: * If no command named "cmdName" already exists for interp, one is * created. Otherwise, if a command does exist, then if the object-based - * Tcl_ObjCmdProc is TclInvokeStringCommand, we assume Tcl_CreateCommand + * Tcl_ObjCmdProc is InvokeStringCommand, we assume Tcl_CreateCommand * was called previously for the same command and just set its * Tcl_ObjCmdProc to the argument "proc"; otherwise, we delete the old * command. * * In the future, during bytecode evaluation when "cmdName" is seen as @@ -8243,10 +8506,54 @@ * 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). */ @@ -8257,11 +8564,11 @@ Tcl_ObjCmdProc *proc, /* Object-based function to associate with * name, provides direct access for direct * calls. */ Tcl_ObjCmdProc *nreProc, /* Object-based function to associate with * name, provides NR implementation */ - ClientData clientData, /* Arbitrary value to pass to object + void *clientData, /* Arbitrary value to pass to object * function. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { @@ -8278,11 +8585,11 @@ Tcl_Interp *interp, const char *cmdName, Tcl_Namespace *nsPtr, Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc, - ClientData clientData, + void *clientData, Tcl_CmdDeleteProc *deleteProc) { Command *cmdPtr = (Command *) TclCreateObjCommandInNs(interp, cmdName, nsPtr, proc, clientData, deleteProc); @@ -8306,11 +8613,11 @@ int Tcl_NREvalObjv( Tcl_Interp *interp, /* Interpreter in which to evaluate the * command. Also used for error reporting. */ - int objc, /* Number of words in command. */ + Tcl_Size objc, /* Number of words in command. */ Tcl_Obj *const objv[], /* An array of pointers to objects that are * the words that make up the command. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and @@ -8321,11 +8628,11 @@ int Tcl_NRCmdSwap( Tcl_Interp *interp, Tcl_Command cmd, - int objc, + Tcl_Size objc, Tcl_Obj *const objv[], int flags) { return TclNREvalObjv(interp, objc, objv, flags|TCL_EVAL_NOERR, (Command *) cmd); @@ -8456,11 +8763,11 @@ } if (!(iPtr->varFramePtr->isProcCallFrame & 1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "tailcall can only be called from a proc, lambda or method", -1)); - Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", NULL); + Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", (void *)NULL); return TCL_ERROR; } /* * Invocation without args just clears a scheduled tailcall; invocation @@ -8506,21 +8813,21 @@ *---------------------------------------------------------------------- */ int TclNRTailcallEval( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *listPtr = (Tcl_Obj *)data[0], *nsObjPtr; Tcl_Namespace *nsPtr; - int objc; + Tcl_Size objc; Tcl_Obj **objv; - Tcl_ListObjGetElements(interp, listPtr, &objc, &objv); + TclListObjGetElementsM(interp, listPtr, &objc, &objv); nsObjPtr = objv[0]; if (result == TCL_OK) { result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); } @@ -8545,11 +8852,11 @@ return TclNREvalObjv(interp, objc-1, objv+1, 0, NULL); } int TclNRReleaseValues( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { int i = 0; @@ -8566,14 +8873,14 @@ void Tcl_NRAddCallback( Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, - ClientData data0, - ClientData data1, - ClientData data2, - ClientData data3) + void *data0, + void *data1, + void *data2, + void *data3) { if (!(postProcPtr)) { Tcl_Panic("Adding a callback without an objProc?!"); } TclNRAddCallback(interp, postProcPtr, data0, data1, data2, data3); @@ -8603,11 +8910,11 @@ #define iPtr ((Interp *) interp) int TclNRYieldObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; @@ -8618,11 +8925,11 @@ } if (!corPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "yield can only be called in a coroutine", -1)); - Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", (void *)NULL); return TCL_ERROR; } if (objc == 2) { Tcl_SetObjResult(interp, objv[1]); @@ -8651,19 +8958,19 @@ } if (!corPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "yieldto can only be called in a coroutine", -1)); - Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", (void *)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); + (void *)NULL); return TCL_ERROR; } /* * Add the tailcall in the caller env, then just yield. @@ -8678,19 +8985,21 @@ /* * Add the callback in the caller's env, then instruct TEBC to yield. */ iPtr->execEnvPtr = corPtr->callerEEPtr; + /* Not calling Tcl_IncrRefCount(listPtr) here because listPtr is private */ TclSetTailcall(interp, listPtr); + corPtr->yieldPtr = listPtr; iPtr->execEnvPtr = corPtr->eePtr; - return TclNRYieldObjCmd(INT2PTR(CORO_ACTIVATE_YIELDM), interp, 1, objv); + return TclNRYieldObjCmd(CORO_ACTIVATE_YIELDM, interp, 1, objv); } static int RewindCoroutineCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int) /*result*/) { return Tcl_RestoreInterpState(interp, (Tcl_InterpState)data[0]); } @@ -8713,11 +9022,11 @@ return TclNRInterpCoroutine(corPtr, interp, 0, NULL); } static void DeleteCoroutine( - ClientData clientData) + void *clientData) { CoroutineData *corPtr = (CoroutineData *)clientData; Tcl_Interp *interp = corPtr->eePtr->interp; NRE_callback *rootPtr = TOP_CB(interp); @@ -8726,11 +9035,11 @@ } } static int NRCoroutineCallerCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { CoroutineData *corPtr = (CoroutineData *)data[0]; Command *cmdPtr = corPtr->cmdPtr; @@ -8772,11 +9081,11 @@ return result; } static int NRCoroutineExitCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { CoroutineData *corPtr = (CoroutineData *)data[0]; Command *cmdPtr = corPtr->cmdPtr; @@ -8837,18 +9146,16 @@ *---------------------------------------------------------------------- */ int TclNRCoroutineActivateCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int) /*result*/) { CoroutineData *corPtr = (CoroutineData *)data[0]; - int type = PTR2INT(data[1]); - int numLevels, unused; - int *stackLevel = &unused; + void *stackLevel = TclGetCStackPtr(); if (!corPtr->stackLevel) { /* * -- Coroutine is suspended -- * Push the callback to restore the caller's context on yield or @@ -8862,11 +9169,11 @@ * 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; + Tcl_Size numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = iPtr->numLevels; SAVE_CONTEXT(corPtr->caller); corPtr->callerEEPtr = iPtr->execEnvPtr; RESTORE_CONTEXT(corPtr->running); @@ -8876,28 +9183,46 @@ /* * 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", - NULL); + (void *)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; - numLevels = iPtr->numLevels; + Tcl_Size numLevels = iPtr->numLevels; iPtr->numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels; iPtr->execEnvPtr = corPtr->callerEEPtr; } @@ -8916,23 +9241,23 @@ *---------------------------------------------------------------------- */ static int TclNREvalList( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int) /*result*/) { - int objc; + 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); - TclListObjGetElements(NULL, listPtr, &objc, &objv); + TclListObjGetElementsM(NULL, listPtr, &objc, &objv); return TclNREvalObjv(interp, objc, objv, 0, NULL); } /* *---------------------------------------------------------------------- @@ -8966,11 +9291,11 @@ 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); + TclGetString(objv[1]), (void *)NULL); return TCL_ERROR; } /* * An active coroutine is "active". Can't tell what it might do in the @@ -8996,11 +9321,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BAD_TYPE", (void *)NULL); return TCL_ERROR; } } /* @@ -9026,11 +9351,11 @@ 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); + TclGetString(objPtr), (void *)NULL); return NULL; } return (CoroutineData *)cmdPtr->objClientData; } @@ -9040,11 +9365,10 @@ 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 ...? */ @@ -9060,19 +9384,20 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", (void *)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; @@ -9085,13 +9410,10 @@ 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 ...? */ @@ -9108,19 +9430,20 @@ } 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); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", (void *)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; @@ -9137,12 +9460,12 @@ /* * Record the stackLevel at which the resume is happening, then swap * the interp's environment to make it suitable to run this coroutine. */ - corPtr->stackLevel = stackLevel; - numLevels = corPtr->auxNumLevels; + corPtr->stackLevel = &corPtr; + Tcl_Size numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = iPtr->numLevels; /* * Do the actual stack swap. */ @@ -9176,40 +9499,41 @@ *---------------------------------------------------------------------- */ static int InjectHandler( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int) /*result*/) { CoroutineData *corPtr = (CoroutineData *)data[0]; Tcl_Obj *listPtr = (Tcl_Obj *)data[1]; - int nargs = PTR2INT(data[2]); - ClientData isProbe = data[3]; - int objc; + Tcl_Size nargs = PTR2INT(data[2]); + void *isProbe = data[3]; + Tcl_Size objc; Tcl_Obj **objv; if (!isProbe) { - /* - * If this is [coroinject], add the extra arguments now. - */ - - if (nargs == COROUTINE_ARGUMENTS_SINGLE_OPTIONAL) { - Tcl_ListObjAppendElement(NULL, listPtr, - Tcl_NewStringObj("yield", -1)); - } else if (nargs == COROUTINE_ARGUMENTS_ARBITRARY) { - Tcl_ListObjAppendElement(NULL, listPtr, - Tcl_NewStringObj("yieldto", -1)); - } else { - /* - * I don't think this is reachable... - */ - - Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewIntObj(nargs)); - } - Tcl_ListObjAppendElement(NULL, listPtr, Tcl_GetObjResult(interp)); + /* + * If 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. */ @@ -9216,25 +9540,24 @@ Tcl_IncrRefCount(listPtr); TclMarkTailcall(interp); TclNRAddCallback(interp, InjectHandlerPostCall, corPtr, listPtr, INT2PTR(nargs), isProbe); - TclListObjGetElements(NULL, listPtr, &objc, &objv); + TclListObjGetElementsM(NULL, listPtr, &objc, &objv); return TclNREvalObjv(interp, objc, objv, 0, NULL); } static int InjectHandlerPostCall( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { CoroutineData *corPtr = (CoroutineData *)data[0]; Tcl_Obj *listPtr = (Tcl_Obj *)data[1]; - int nargs = PTR2INT(data[2]); - ClientData isProbe = data[3]; - int numLevels; + Tcl_Size nargs = PTR2INT(data[2]); + void *isProbe = data[3]; /* * Delete the command words for what we just executed. */ @@ -9252,11 +9575,11 @@ Tcl_AddErrorInfo(interp, "\n (injected coroutine probe command)"); } corPtr->nargs = nargs; corPtr->stackLevel = NULL; - numLevels = iPtr->numLevels; + Tcl_Size numLevels = iPtr->numLevels; iPtr->numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels; iPtr->execEnvPtr = corPtr->callerEEPtr; } return result; @@ -9298,11 +9621,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", (void *)NULL); return TCL_ERROR; } /* * Add the callback to the coro's execEnv, so that it is the first thing @@ -9317,11 +9640,11 @@ return TCL_OK; } int TclNRInterpCoroutine( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { CoroutineData *corPtr = (CoroutineData *)clientData; @@ -9328,11 +9651,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BUSY", (void *)NULL); return TCL_ERROR; } /* * Parse all the arguments to work out what to feed as the result of the @@ -9348,15 +9671,15 @@ Tcl_WrongNumArgs(interp, 1, objv, "?arg?"); return TCL_ERROR; } break; default: - if (corPtr->nargs != objc-1) { + 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", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (void *)NULL); return TCL_ERROR; } /* fallthrough */ case COROUTINE_ARGUMENTS_ARBITRARY: if (objc > 1) { @@ -9406,18 +9729,18 @@ if (nsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\": unknown namespace", procName)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", (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", procName, NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", procName, (void *)NULL); return TCL_ERROR; } /* * We ARE creating the coroutine command: allocate the corresponding @@ -9469,10 +9792,11 @@ 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. */ Index: generic/tclBinary.c ================================================================== --- generic/tclBinary.c +++ generic/tclBinary.c @@ -2,12 +2,12 @@ * tclBinary.c -- * * This file contains the implementation of the "binary" Tcl built-in * command and the Tcl binary data object. * - * Copyright (c) 1997 by Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -20,15 +20,15 @@ /* * The following constants are used by GetFormatSpec to indicate various * special conditions in the parsing of a format specifier. */ -#define BINARY_ALL ((size_t)-1) /* Use all elements in the argument. */ -#define BINARY_NOCOUNT ((size_t)-2) /* No count was specified in format. */ +#define BINARY_ALL -1 /* Use all elements in the argument. */ +#define BINARY_NOCOUNT -2 /* No count was specified in format. */ /* - * The following flags may be ORed together and returned by GetFormatSpec + * The following flags may be OR'ed together and returned by GetFormatSpec */ #define BINARY_SIGNED 0 /* Field to be read as signed data */ #define BINARY_UNSIGNED 1 /* Field to be read as unsigned data */ @@ -35,11 +35,11 @@ /* * The following defines the maximum number of different (integer) numbers * placed in the object cache by 'binary scan' before it bails out and * switches back to Plan A (creating a new object for each value.) * Theoretically, it would be possible to keep the cache about for the values - * that are already in it, but that makes the code slower in practise when + * that are already in it, but that makes the code slower in practice when * overflow happens, and makes little odds the rest of the time (as measured * on my machine.) It is also slower (on the sample I tried at least) to grow * the cache to hold all items we might want to put in it; presumably the * extra cost of managing the memory for the enlarged table outweighs the * benefit from allocating fewer objects. This is probably because as the @@ -53,55 +53,36 @@ /* * Prototypes for local procedures defined in this file: */ -static void DupByteArrayInternalRep(Tcl_Obj *srcPtr, - Tcl_Obj *copyPtr); static void DupProperByteArrayInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static int FormatNumber(Tcl_Interp *interp, int type, Tcl_Obj *src, unsigned char **cursorPtr); -static void FreeByteArrayInternalRep(Tcl_Obj *objPtr); static void FreeProperByteArrayInternalRep(Tcl_Obj *objPtr); static int GetFormatSpec(const char **formatPtr, char *cmdPtr, - size_t *countPtr, int *flagsPtr); + Tcl_Size *countPtr, int *flagsPtr); static Tcl_Obj * ScanNumber(unsigned char *buffer, int type, int flags, Tcl_HashTable **numberCachePtr); -static int SetByteArrayFromAny(Tcl_Interp *interp, +static int SetByteArrayFromAny(Tcl_Interp *interp, Tcl_Size limit, Tcl_Obj *objPtr); static void UpdateStringOfByteArray(Tcl_Obj *listPtr); static void DeleteScanNumberCache(Tcl_HashTable *numberCachePtr); static int NeedReversing(int format); static void CopyNumber(const void *from, void *to, size_t length, int type); /* Binary ensemble commands */ -static int BinaryFormatCmd(ClientData clientData, - Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]); -static int BinaryScanCmd(ClientData clientData, - Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]); +static Tcl_ObjCmdProc BinaryFormatCmd; +static Tcl_ObjCmdProc BinaryScanCmd; /* 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[]); +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 */ @@ -157,108 +138,34 @@ { "base64", BinaryDecode64, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, { NULL, NULL, NULL, NULL, NULL, 0 } }; /* - * The following object types represent an array of bytes. The intent is to + * The following Tcl_ObjType represents an array of bytes. The intent is to * allow arbitrary binary data to pass through Tcl as a Tcl value without loss * or damage. Such values are useful for things like encoded strings or Tk * images to name just two. * - * It's strange to have two Tcl_ObjTypes in place for this task when one would - * do, so a bit of detail and history how we got to this point and where we - * might go from here. - * * A bytearray is an ordered sequence of bytes. Each byte is an integer value * in the range [0-255]. To be a Tcl value type, we need a way to encode each - * value in the value set as a Tcl string. The simplest encoding is to + * value in the value set as a Tcl string. A simple encoding is to * represent each byte value as the same codepoint value. A bytearray of N * bytes is encoded into a Tcl string of N characters where the codepoint of * each character is the value of corresponding byte. This approach creates a * one-to-one map between all bytearray values and a subset of Tcl string - * values. - * - * 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. + * 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 -}; - -const Tcl_ObjType tclByteArrayType = { - "bytearray", - FreeByteArrayInternalRep, - DupByteArrayInternalRep, NULL, - SetByteArrayFromAny + 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 @@ -265,33 +172,33 @@ * the byte array to enable growing and shrinking of the ByteArray object with * fewer mallocs. */ typedef struct { - size_t bad; /* Index of the character that is a nonbyte. - * If all characters are bytes, bad = used, - * though then we should never read it. */ - size_t used; /* The number of bytes used in the byte + Tcl_Size used; /* The number of bytes used in the byte * array. */ - size_t allocated; /* The amount of space actually allocated + Tcl_Size allocated; /* The amount of space actually allocated * minus 1 byte. */ unsigned char bytes[TCLFLEXARRAY]; /* The array of bytes. The actual size of this * field depends on the 'allocated' field * above. */ } ByteArray; +#define BYTEARRAY_MAX_LEN (TCL_SIZE_MAX - (Tcl_Size)offsetof(ByteArray, bytes)) #define BYTEARRAY_SIZE(len) \ - (offsetof(ByteArray, bytes) + (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 TclHasIntRep(objPtr, &properByteArrayType); + return TclHasInternalRep(objPtr, &properByteArrayType); } /* *---------------------------------------------------------------------- * @@ -314,19 +221,19 @@ Tcl_Obj * Tcl_NewByteArrayObj( const unsigned char *bytes, /* The array of bytes used to initialize the * new object. */ - size_t length) /* Length of the array of bytes */ + Tcl_Size numBytes) /* Number of bytes in the array */ { #ifdef TCL_MEM_DEBUG - return Tcl_DbNewByteArrayObj(bytes, length, "unknown", 0); + return Tcl_DbNewByteArrayObj(bytes, numBytes, "unknown", 0); #else /* if not TCL_MEM_DEBUG */ Tcl_Obj *objPtr; TclNewObj(objPtr); - Tcl_SetByteArrayObj(objPtr, bytes, length); + Tcl_SetByteArrayObj(objPtr, bytes, numBytes); return objPtr; #endif /* TCL_MEM_DEBUG */ } /* @@ -343,11 +250,11 @@ * * When TCL_MEM_DEBUG is not defined, this procedure just returns the * result of calling Tcl_NewByteArrayObj. * * Results: - * The newly create object is returned. This object will have no initial + * The newly created object is returned. This object has no initial * string representation. The returned object has a ref count of 0. * * Side effects: * Memory allocated for new object and copy of byte array argument. * @@ -357,33 +264,32 @@ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewByteArrayObj( const unsigned char *bytes, /* The array of bytes used to initialize the * new object. */ - size_t length, /* Length of the array of bytes. */ + Tcl_Size numBytes, /* Number of bytes in the array */ const char *file, /* The name of the source file calling this * procedure; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); - Tcl_SetByteArrayObj(objPtr, bytes, length); + Tcl_SetByteArrayObj(objPtr, bytes, numBytes); return objPtr; } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewByteArrayObj( const unsigned char *bytes, /* The array of bytes used to initialize the * new object. */ - size_t length, /* Length of the array of bytes, which must be - * >= 0. */ + Tcl_Size numBytes, /* Number of bytes in the array */ TCL_UNUSED(const char *) /*file*/, TCL_UNUSED(int) /*line*/) { - return Tcl_NewByteArrayObj(bytes, length); + return Tcl_NewByteArrayObj(bytes, numBytes); } #endif /* TCL_MEM_DEBUG */ /* *--------------------------------------------------------------------------- @@ -405,145 +311,107 @@ void Tcl_SetByteArrayObj( Tcl_Obj *objPtr, /* Object to initialize as a ByteArray. */ const unsigned char *bytes, /* The array of bytes to use as the new value. - * May be NULL even if length > 0. */ - size_t length) /* Length of the array of bytes, which must - * be >= 0. */ + * May be NULL even if numBytes > 0. */ + Tcl_Size numBytes) /* Number of bytes in the array. + * Must be >= 0 */ { ByteArray *byteArrayPtr; - Tcl_ObjIntRep ir; + Tcl_ObjInternalRep ir; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayObj"); } TclInvalidateStringRep(objPtr); - byteArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(length)); - byteArrayPtr->bad = length; - byteArrayPtr->used = length; - byteArrayPtr->allocated = length; + assert(numBytes >= 0); + byteArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(numBytes)); + byteArrayPtr->used = numBytes; + byteArrayPtr->allocated = numBytes; - if ((bytes != NULL) && (length > 0)) { - memcpy(byteArrayPtr->bytes, bytes, length); + if ((bytes != NULL) && (numBytes > 0)) { + memcpy(byteArrayPtr->bytes, bytes, numBytes); } SET_BYTEARRAY(&ir, byteArrayPtr); - Tcl_StoreIntRep(objPtr, &properByteArrayType, &ir); + Tcl_StoreInternalRep(objPtr, &properByteArrayType, &ir); } /* *---------------------------------------------------------------------- * * TclGetBytesFromObj -- * * Attempt to extract the value from objPtr in the representation * of a byte sequence. On success return the extracted byte sequence. - * On failures, return NULL and record error message and code in + * On failure, return NULL and record error message and code in * interp (if not NULL). * * Results: - * Pointer to array of bytes, or NULL. representing the ByteArray object. - * Writes number of bytes in array to *lengthPtr. + * NULL or pointer to array of bytes representing the ByteArray object. + * Writes number of bytes in array to *numBytesPtr. * *---------------------------------------------------------------------- */ +#undef Tcl_GetBytesFromObj +unsigned char * +Tcl_GetBytesFromObj( + Tcl_Interp *interp, /* For error reporting */ + Tcl_Obj *objPtr, /* Value to extract from */ + Tcl_Size *numBytesPtr) /* If non-NULL, write the number of bytes + * in the array here */ +{ + ByteArray *baPtr; + const Tcl_ObjInternalRep *irPtr + = TclFetchInternalRep(objPtr, &properByteArrayType); + + if (irPtr == NULL) { + if (TCL_ERROR == SetByteArrayFromAny(interp, TCL_INDEX_NONE, objPtr)) { + return NULL; + } + irPtr = TclFetchInternalRep(objPtr, &properByteArrayType); + } + baPtr = GET_BYTEARRAY(irPtr); + + if (numBytesPtr != NULL) { + *numBytesPtr = baPtr->used; + } + return baPtr->bytes; +} + +#if !defined(TCL_NO_DEPRECATED) unsigned char * TclGetBytesFromObj( Tcl_Interp *interp, /* For error reporting */ Tcl_Obj *objPtr, /* Value to extract from */ - size_t *lengthPtr) /* If non-NULL, filled with length of the - * array of bytes in the ByteArray object. */ -{ - 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; + 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 -- @@ -566,104 +434,161 @@ */ unsigned char * Tcl_SetByteArrayLength( Tcl_Obj *objPtr, /* The ByteArray object. */ - size_t length) /* New length for internal byte array. */ + Tcl_Size numBytes) /* Number of bytes in resized array + * Must be >= 0 */ { ByteArray *byteArrayPtr; - Tcl_ObjIntRep *irPtr; + Tcl_ObjInternalRep *irPtr; + assert(numBytes >= 0); if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength"); } - irPtr = TclFetchIntRep(objPtr, &properByteArrayType); - if (irPtr == NULL) { - irPtr = TclFetchIntRep(objPtr, &tclByteArrayType); - if (irPtr == NULL) { - SetByteArrayFromAny(NULL, objPtr); - irPtr = TclFetchIntRep(objPtr, &properByteArrayType); - if (irPtr == NULL) { - irPtr = TclFetchIntRep(objPtr, &tclByteArrayType); - } - } + 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 (length > byteArrayPtr->allocated) { - byteArrayPtr = (ByteArray *)Tcl_Realloc(byteArrayPtr, BYTEARRAY_SIZE(length)); - byteArrayPtr->allocated = length; + if (numBytes > byteArrayPtr->allocated) { + byteArrayPtr = (ByteArray *)Tcl_Realloc(byteArrayPtr, + BYTEARRAY_SIZE(numBytes)); + byteArrayPtr->allocated = numBytes; SET_BYTEARRAY(irPtr, byteArrayPtr); } TclInvalidateStringRep(objPtr); - objPtr->typePtr = &properByteArrayType; - byteArrayPtr->bad = length; - byteArrayPtr->used = length; + 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 = Tcl_GetStringFromObj(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 = Tcl_UtfToUniChar(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: - * The return value is always TCL_OK. + * Tcl return code indicating OK or ERROR. * * Side effects: - * A ByteArray object is stored as the internal rep of objPtr. + * A ByteArray struct may be stored as the internal rep of objPtr. * *---------------------------------------------------------------------- */ static int SetByteArrayFromAny( - TCL_UNUSED(Tcl_Interp *), + Tcl_Interp *interp, /* For error reporting. */ + Tcl_Size limit, /* Create no more than this many bytes */ Tcl_Obj *objPtr) /* The object to convert to type ByteArray. */ { - size_t length, bad; - const char *src, *srcEnd; - unsigned char *dst; - Tcl_UniChar ch = 0; ByteArray *byteArrayPtr; - Tcl_ObjIntRep ir; - - 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); + Tcl_ObjInternalRep ir; + + if (0 == MakeByteArray(interp, objPtr, limit, 1, &byteArrayPtr)) { + return TCL_ERROR; } 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); - } - + Tcl_StoreInternalRep(objPtr, &properByteArrayType, &ir); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -680,22 +605,15 @@ * Frees memory. * *---------------------------------------------------------------------- */ -static void -FreeByteArrayInternalRep( - Tcl_Obj *objPtr) /* Object with internal rep to free. */ -{ - Tcl_Free(GET_BYTEARRAY(TclFetchIntRep(objPtr, &tclByteArrayType))); -} - static void FreeProperByteArrayInternalRep( Tcl_Obj *objPtr) /* Object with internal rep to free. */ { - Tcl_Free(GET_BYTEARRAY(TclFetchIntRep(objPtr, &properByteArrayType))); + Tcl_Free(GET_BYTEARRAY(TclFetchInternalRep(objPtr, &properByteArrayType))); } /* *---------------------------------------------------------------------- * @@ -712,51 +630,28 @@ * *---------------------------------------------------------------------- */ 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); +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); } /* *---------------------------------------------------------------------- * @@ -777,15 +672,15 @@ static void UpdateStringOfByteArray( Tcl_Obj *objPtr) /* ByteArray object whose string rep to * update. */ { - const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &properByteArrayType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &properByteArrayType); ByteArray *byteArrayPtr = GET_BYTEARRAY(irPtr); unsigned char *src = byteArrayPtr->bytes; - size_t i, length = byteArrayPtr->used; - size_t size = length; + Tcl_Size i, length = byteArrayPtr->used; + Tcl_Size size = length; /* * How much space will string rep need? */ @@ -804,11 +699,10 @@ TclOOM(dst, size); for (i = 0; i < length; i++) { dst += Tcl_UniCharToUtf(src[i], dst); } - (void) Tcl_InitStringRep(objPtr, NULL, size); } } /* *---------------------------------------------------------------------- @@ -831,20 +725,20 @@ void TclAppendBytesToByteArray( Tcl_Obj *objPtr, const unsigned char *bytes, - size_t len) + Tcl_Size len) { ByteArray *byteArrayPtr; - size_t needed; - Tcl_ObjIntRep *irPtr; + Tcl_Size needed; + Tcl_ObjInternalRep *irPtr; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray"); } - if (len == TCL_INDEX_NONE) { + if (len < 0) { Tcl_Panic("%s must be called with definite number of bytes to append", "TclAppendBytesToByteArray"); } if (len == 0) { /* @@ -852,75 +746,45 @@ */ 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); - } - } + 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 (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 ((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) { - 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; + 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); - objPtr->typePtr = &properByteArrayType; } /* *---------------------------------------------------------------------- * @@ -966,20 +830,20 @@ *---------------------------------------------------------------------- */ static int BinaryFormatCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int arg; /* Index of next argument to consume. */ int value = 0; /* Current integer value to be packed. * Initialized to avoid compiler warning. */ char cmd; /* Current format character. */ - size_t count; /* Count associated with current format + Tcl_Size count; /* Count associated with current format * character. */ int flags; /* Format field flags */ const char *format; /* Pointer to current position in format * string. */ Tcl_Obj *resultPtr = NULL; /* Object holding result buffer. */ @@ -987,12 +851,11 @@ 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; + Tcl_Size offset, size, length; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "formatString ?arg ...?"); return TCL_ERROR; } @@ -1027,11 +890,13 @@ if (arg >= objc) { goto badIndex; } if (count == BINARY_ALL) { - (void)TclGetByteArrayFromObj(objv[arg], &count); + if (Tcl_GetByteArrayFromObj(objv[arg], &count) == NULL) { + count = Tcl_GetCharLength(objv[arg]); + } } else if (count == BINARY_NOCOUNT) { count = 1; } arg++; if (cmd == 'a' || cmd == 'A') { @@ -1084,31 +949,35 @@ if (count == BINARY_NOCOUNT) { arg++; count = 1; } else { - int listc; + Tcl_Size listc; Tcl_Obj **listv; /* * The macro evals its args more than once: avoid arg++ */ - if (TclListObjGetElements(interp, objv[arg], &listc, - &listv) != TCL_OK) { + if (TclListObjLengthM(interp, objv[arg], &listc + ) != TCL_OK) { return TCL_ERROR; } - arg++; if (count == BINARY_ALL) { count = listc; - } else if (count > (size_t)listc) { + } else if (count > listc) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "number of elements in list does not match count", -1)); return TCL_ERROR; } + if (TclListObjGetElementsM(interp, objv[arg], &listc, + &listv) != TCL_OK) { + return TCL_ERROR; + } + arg++; } offset += count*size; break; case 'x': @@ -1123,20 +992,20 @@ break; case 'X': if (count == BINARY_NOCOUNT) { count = 1; } - if ((count > (size_t)offset) || (count == BINARY_ALL)) { + if ((count > offset) || (count == BINARY_ALL)) { count = offset; } - if (offset > (int)length) { + if (offset > length) { length = offset; } offset -= count; break; case '@': - if (offset > (int)length) { + if (offset > length) { length = offset; } if (count == BINARY_ALL) { offset = length; } else if (count == BINARY_NOCOUNT) { @@ -1148,19 +1017,19 @@ default: errorString = str; goto badField; } } - if (offset > (int)length) { + if (offset > length) { length = offset; } if (length == 0) { return TCL_OK; } /* - * Prepare the result object by preallocating the caclulated number of + * Prepare the result object by preallocating the calculated number of * bytes and filling with nulls. */ TclNewObj(resultPtr); buffer = Tcl_SetByteArrayLength(resultPtr, length); @@ -1190,13 +1059,14 @@ switch (cmd) { case 'a': case 'A': { char pad = (char) (cmd == 'a' ? '\0' : ' '); unsigned char *bytes; + Tcl_Obj *copy = TclNarrowToBytes(objv[arg++]); - bytes = TclGetByteArrayFromObj(objv[arg], &length); - arg++; + bytes = Tcl_GetByteArrayFromObj(copy, &length); + if (count == BINARY_ALL) { count = length; } else if (count == BINARY_NOCOUNT) { count = 1; } @@ -1205,17 +1075,18 @@ } 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); + str = Tcl_GetStringFromObj(objv[arg], &length); arg++; if (count == BINARY_ALL) { count = length; } else if (count == BINARY_NOCOUNT) { count = 1; @@ -1225,11 +1096,11 @@ count = length; } value = 0; errorString = "binary"; if (cmd == 'B') { - for (offset = 0; (size_t)offset < count; offset++) { + for (offset = 0; offset < count; offset++) { value <<= 1; if (str[offset] == '1') { value |= 1; } else if (str[offset] != '0') { errorValue = str; @@ -1240,11 +1111,11 @@ *cursor++ = UCHAR(value); value = 0; } } } else { - for (offset = 0; (size_t)offset < count; offset++) { + for (offset = 0; offset < count; offset++) { value >>= 1; if (str[offset] == '1') { value |= 128; } else if (str[offset] != '0') { errorValue = str; @@ -1273,11 +1144,11 @@ case 'h': case 'H': { unsigned char *last; int c; - str = TclGetStringFromObj(objv[arg], &length); + str = Tcl_GetStringFromObj(objv[arg], &length); arg++; if (count == BINARY_ALL) { count = length; } else if (count == BINARY_NOCOUNT) { count = 1; @@ -1287,11 +1158,11 @@ count = length; } value = 0; errorString = "hexadecimal"; if (cmd == 'H') { - for (offset = 0; (size_t)offset < count; offset++) { + for (offset = 0; offset < count; offset++) { value <<= 4; if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */ errorValue = str; Tcl_DecrRefCount(resultPtr); goto badValue; @@ -1308,11 +1179,11 @@ *cursor++ = (char) value; value = 0; } } } else { - for (offset = 0; (size_t)offset < count; offset++) { + for (offset = 0; offset < count; offset++) { value >>= 4; if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */ errorValue = str; Tcl_DecrRefCount(resultPtr); @@ -1360,11 +1231,11 @@ case 'R': case 'd': case 'q': case 'Q': case 'f': { - int listc, i; + Tcl_Size listc, i; Tcl_Obj **listv; if (count == BINARY_NOCOUNT) { /* * Note that we are casting away the const-ness of objv, but @@ -1373,17 +1244,17 @@ listv = (Tcl_Obj **) (objv + arg); listc = 1; count = 1; } else { - TclListObjGetElements(interp, objv[arg], &listc, &listv); + TclListObjGetElementsM(interp, objv[arg], &listc, &listv); if (count == BINARY_ALL) { count = listc; } } arg++; - for (i = 0; (size_t)i < count; i++) { + for (i = 0; i < count; i++) { if (FormatNumber(interp, cmd, listv[i], &cursor) != TCL_OK) { Tcl_DecrRefCount(resultPtr); return TCL_ERROR; } } @@ -1401,11 +1272,11 @@ maxPos = cursor; } if (count == BINARY_NOCOUNT) { count = 1; } - if ((count == BINARY_ALL) || (count > (size_t)(cursor - buffer))) { + if ((count == BINARY_ALL) || (count > (cursor - buffer))) { cursor = buffer; } else { cursor -= count; } break; @@ -1470,45 +1341,47 @@ * See the user documentation. * *---------------------------------------------------------------------- */ -int +static int BinaryScanCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int arg; /* Index of next argument to consume. */ int value = 0; /* Current integer value to be packed. * Initialized to avoid compiler warning. */ char cmd; /* Current format character. */ - size_t count; /* Count associated with current format + Tcl_Size count; /* Count associated with current format * character. */ int flags; /* Format field flags */ const char *format; /* Pointer to current position in format * string. */ Tcl_Obj *resultPtr = NULL; /* Object holding result buffer. */ unsigned char *buffer; /* Start of result buffer. */ const char *errorString; const char *str; - int offset, size, i; - size_t length = 0; + 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); - buffer = TclGetByteArrayFromObj(objv[1], &length); format = TclGetString(objv[2]); arg = 3; offset = 0; while (*format != '\0') { str = format; @@ -1516,11 +1389,12 @@ if (!GetFormatSpec(&format, &cmd, &count, &flags)) { goto done; } switch (cmd) { case 'a': - case 'A': { + case 'A': + case 'C': { unsigned char *src; if (arg >= objc) { DeleteScanNumberCache(numberCachePtr); goto badIndex; @@ -1538,14 +1412,22 @@ src = buffer + offset; size = count; /* - * Trim trailing nulls and spaces, if necessary. + * Apply C string semantics or trim trailing + * nulls and spaces, if necessary. */ - if (cmd == 'A') { + if (cmd == 'C') { + for (i = 0; i < size; i++) { + if (src[i] == '\0') { + size = i; + break; + } + } + } else if (cmd == 'A') { while (size > 0) { if (src[size - 1] != '\0' && src[size - 1] != ' ') { break; } size--; @@ -1588,30 +1470,30 @@ count = (length - offset) * 8; } else { if (count == BINARY_NOCOUNT) { count = 1; } - if (count > (size_t)(length - offset) * 8) { + if (count > (length - offset) * 8) { goto done; } } src = buffer + offset; TclNewObj(valuePtr); Tcl_SetObjLength(valuePtr, count); dest = TclGetString(valuePtr); if (cmd == 'b') { - for (i = 0; (size_t)i < count; i++) { + for (i = 0; i < count; i++) { if (i % 8) { value >>= 1; } else { value = *src++; } *dest++ = (char) ((value & 1) ? '1' : '0'); } } else { - for (i = 0; (size_t)i < count; i++) { + for (i = 0; i < count; i++) { if (i % 8) { value <<= 1; } else { value = *src++; } @@ -1653,20 +1535,20 @@ TclNewObj(valuePtr); Tcl_SetObjLength(valuePtr, count); dest = TclGetString(valuePtr); if (cmd == 'h') { - for (i = 0; (size_t)i < count; i++) { + for (i = 0; i < count; i++) { if (i % 2) { value >>= 4; } else { value = *src++; } *dest++ = hexdigit[value & 0xF]; } } else { - for (i = 0; (size_t)i < count; i++) { + for (i = 0; i < count; i++) { if (i % 2) { value <<= 4; } else { value = *src++; } @@ -1719,11 +1601,11 @@ if (arg >= objc) { DeleteScanNumberCache(numberCachePtr); goto badIndex; } if (count == BINARY_NOCOUNT) { - if ((length - offset) < (size_t)size) { + if (length < size + offset) { goto done; } valuePtr = ScanNumber(buffer+offset, cmd, flags, &numberCachePtr); offset += size; @@ -1734,11 +1616,11 @@ if ((length - offset) < (count * size)) { goto done; } TclNewObj(valuePtr); src = buffer + offset; - for (i = 0; (size_t)i < count; i++) { + for (i = 0; i < count; i++) { elementPtr = ScanNumber(src, cmd, flags, &numberCachePtr); src += size; Tcl_ListObjAppendElement(NULL, valuePtr, elementPtr); } offset += count * size; @@ -1755,21 +1637,21 @@ } case 'x': if (count == BINARY_NOCOUNT) { count = 1; } - if ((count == BINARY_ALL) || (count > length - offset)) { + if ((count == BINARY_ALL) || (count > (length - offset))) { offset = length; } else { offset += count; } break; case 'X': if (count == BINARY_NOCOUNT) { count = 1; } - if ((count == BINARY_ALL) || (count > (size_t)offset)) { + if ((count == BINARY_ALL) || (count > offset)) { offset = 0; } else { offset -= count; } break; @@ -1849,11 +1731,11 @@ static int GetFormatSpec( const char **formatPtr, /* Pointer to format string. */ char *cmdPtr, /* Pointer to location of command char. */ - size_t *countPtr, /* Pointer to repeat count value. */ + Tcl_Size *countPtr, /* Pointer to repeat count value. */ int *flagsPtr) /* Pointer to field flags */ { /* * Skip any leading blanks. */ @@ -1882,18 +1764,18 @@ } if (**formatPtr == '*') { (*formatPtr)++; *countPtr = BINARY_ALL; } else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */ - unsigned long int count; + unsigned long long count; errno = 0; - count = strtoul(*formatPtr, (char **) formatPtr, 10); - if (errno || (count > (unsigned long) INT_MAX)) { - *countPtr = INT_MAX; + count = strtoull(*formatPtr, (char **) formatPtr, 10); + if (errno || (count > TCL_SIZE_MAX)) { + *countPtr = TCL_SIZE_MAX; } else { - *countPtr = (int) count; + *countPtr = count; } } else { *countPtr = BINARY_NOCOUNT; } return 1; @@ -1904,11 +1786,11 @@ * * NeedReversing -- * * This routine determines, if bytes of a number need to be re-ordered, * and returns a numeric code indicating the re-ordering to be done. - * This depends on the endiannes of the machine and the desired format. + * This depends on the endianness of the machine and the desired format. * It is in effect a table (whose contents depend on the endianness of * the system) describing whether a value needs reversing or not. Anyone * porting the code to a big-endian platform should take care to make * sure that they define WORDS_BIGENDIAN though this is already done by * configure for the Unix build; little-endian platforms (including @@ -2117,11 +1999,11 @@ * returns TCL_ERROR for NaN, but we can check by comparing the * object's type pointer. */ if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) { - const Tcl_ObjIntRep *irPtr = TclFetchIntRep(src, &tclDoubleType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(src, &tclDoubleType); if (irPtr == NULL) { return TCL_ERROR; } dvalue = irPtr->doubleValue; } @@ -2137,11 +2019,11 @@ * returns TCL_ERROR for NaN, but we can check by comparing the * object's type pointer. */ if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) { - const Tcl_ObjIntRep *irPtr = TclFetchIntRep(src, &tclDoubleType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(src, &tclDoubleType); if (irPtr == NULL) { return TCL_ERROR; } dvalue = irPtr->doubleValue; @@ -2152,11 +2034,15 @@ * 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); @@ -2337,16 +2223,16 @@ case 'n': if (NeedReversing(type)) { value = (long) (buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) - + (((long)buffer[3]) << 24)); + + (((unsigned long)buffer[3]) << 24)); } else { value = (long) (buffer[3] + (buffer[2] << 8) + (buffer[1] << 16) - + (((long) buffer[0]) << 24)); + + (((unsigned long) buffer[0]) << 24)); } /* * Check to see if the value was sign extended properly on systems * where an int is more than 32-bits. @@ -2356,13 +2242,13 @@ */ if (flags & BINARY_UNSIGNED) { return Tcl_NewWideIntObj((Tcl_WideInt)(unsigned long)value); } - if ((value & (((unsigned) 1) << 31)) && (value > 0)) { - value -= (((unsigned) 1) << 31); - value -= (((unsigned) 1) << 31); + if ((value & (1U << 31)) && (value > 0)) { + value -= (1U << 31); + value -= (1U << 31); } returnNumericObject: if (*numberCachePtrPtr == NULL) { return Tcl_NewWideIntObj(value); @@ -2541,27 +2427,31 @@ *---------------------------------------------------------------------- */ static int BinaryEncodeHex( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj = NULL; unsigned char *data = NULL; unsigned char *cursor = NULL; - size_t offset = 0, count = 0; + Tcl_Size offset = 0, count = 0; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "data"); return TCL_ERROR; } + + data = Tcl_GetBytesFromObj(interp, objv[1], &count); + if (data == NULL) { + return TCL_ERROR; + } TclNewObj(resultObj); - data = TclGetByteArrayFromObj(objv[1], &count); cursor = Tcl_SetByteArrayLength(resultObj, count * 2); for (offset = 0; offset < count; ++offset) { *cursor++ = HexDigits[(data[offset] >> 4) & 0x0F]; *cursor++ = HexDigits[data[offset] & 0x0F]; } @@ -2585,20 +2475,20 @@ *---------------------------------------------------------------------- */ static int BinaryDecodeHex( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj = NULL; unsigned char *data, *datastart, *dataend; unsigned char *begin, *cursor, c; int i, index, value, pure = 1, strict = 0; - size_t size, cut = 0, count = 0; + Tcl_Size size, cut = 0, count = 0; int ucs4; enum {OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { @@ -2616,14 +2506,14 @@ break; } } TclNewObj(resultObj); - data = TclGetBytesFromObj(NULL, objv[objc - 1], &count); + data = Tcl_GetByteArrayFromObj(objv[objc - 1], &count); if (data == NULL) { pure = 0; - data = (unsigned char *) TclGetStringFromObj(objv[objc - 1], &count); + data = (unsigned char *) Tcl_GetStringFromObj(objv[objc - 1], &count); } datastart = data; dataend = data + count; size = (count + 1) / 2; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); @@ -2669,17 +2559,17 @@ badChar: if (pure) { ucs4 = c; } else { - TclUtfToUCS4((const char *)(data - 1), &ucs4); + Tcl_UtfToUniChar((const char *)(data - 1), &ucs4); } TclDecrRefCount(resultObj); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid hexadecimal digit \"%c\" (U+%06X) at position %" TCL_Z_MODIFIER "u", ucs4, ucs4, data - datastart - 1)); - Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", NULL); + Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -2710,22 +2600,22 @@ } \ } while (0) static int BinaryEncode64( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj; unsigned char *data, *limit; - int maxlen = 0; + Tcl_Size maxlen = 0; const char *wrapchar = "\n"; - size_t wrapcharlen = 1; - int i, index, size, outindex = 0, purewrap = 1; - size_t offset, count = 0; + Tcl_Size wrapcharlen = 1; + int index, purewrap = 1; + Tcl_Size i, offset, size, outindex = 0, count = 0; enum { OPT_MAXLEN, OPT_WRAPCHAR }; static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL }; if (objc < 2 || objc % 2 != 0) { Tcl_WrongNumArgs(interp, 1, objv, @@ -2737,37 +2627,40 @@ TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case OPT_MAXLEN: - if (Tcl_GetIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) { + if (TclGetSizeIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) { return TCL_ERROR; } if (maxlen < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "line length out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE", - "LINE_LENGTH", NULL); + "LINE_LENGTH", (void *)NULL); return TCL_ERROR; } break; case OPT_WRAPCHAR: - wrapchar = (const char *)TclGetBytesFromObj(NULL, + wrapchar = (const char *)Tcl_GetByteArrayFromObj( objv[i + 1], &wrapcharlen); if (wrapchar == NULL) { purewrap = 0; - wrapchar = TclGetStringFromObj(objv[i + 1], &wrapcharlen); + wrapchar = Tcl_GetStringFromObj(objv[i + 1], &wrapcharlen); } break; } } if (wrapcharlen == 0) { maxlen = 0; } + data = Tcl_GetBytesFromObj(interp, objv[objc - 1], &count); + if (data == NULL) { + return TCL_ERROR; + } TclNewObj(resultObj); - data = TclGetByteArrayFromObj(objv[objc - 1], &count); if (count > 0) { unsigned char *cursor = NULL; size = (((count * 4) / 3) + 3) & ~3; /* ensure 4 byte chunks */ if (maxlen > 0 && size > maxlen) { @@ -2833,22 +2726,23 @@ *---------------------------------------------------------------------- */ static int BinaryEncodeUu( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj; unsigned char *data, *start, *cursor; - int rawLength, n, i, bits, index; + int i, bits, index; + unsigned int n; int lineLength = 61; const unsigned char SingleNewline[] = { UCHAR('\n') }; const unsigned char *wrapchar = SingleNewline; - size_t j, offset, count = 0, wrapcharlen = sizeof(SingleNewline); + Tcl_Size j, rawLength, offset, count = 0, wrapcharlen = sizeof(SingleNewline); enum { OPT_MAXLEN, OPT_WRAPCHAR }; static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL }; if (objc < 2 || objc % 2 != 0) { Tcl_WrongNumArgs(interp, 1, objv, @@ -2868,21 +2762,21 @@ } if (lineLength < 5 || lineLength > 85) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "line length out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE", - "LINE_LENGTH", NULL); + "LINE_LENGTH", (void *)NULL); return TCL_ERROR; } lineLength = ((lineLength - 1) & -4) + 1; /* 5, 9, 13 ... */ break; case OPT_WRAPCHAR: - wrapchar = (const unsigned char *) TclGetStringFromObj( + wrapchar = (const unsigned char *) Tcl_GetStringFromObj( objv[i + 1], &wrapcharlen); { const unsigned char *p = wrapchar; - size_t numBytes = wrapcharlen; + Tcl_Size numBytes = wrapcharlen; while (numBytes) { switch (*p) { case '\t': case '\v': @@ -2897,11 +2791,11 @@ badwrap: Tcl_SetObjResult(interp, Tcl_NewStringObj( "invalid wrapchar; will defeat decoding", -1)); Tcl_SetErrorCode(interp, "TCL", "BINARY", - "ENCODE", "WRAPCHAR", NULL); + "ENCODE", "WRAPCHAR", (void *)NULL); return TCL_ERROR; } } if (numBytes) { goto badwrap; @@ -2914,13 +2808,16 @@ /* * Allocate the buffer. This is a little bit too long, but is "good * enough". */ - TclNewObj(resultObj); offset = 0; - data = TclGetByteArrayFromObj(objv[objc - 1], &count); + data = Tcl_GetBytesFromObj(interp, objv[objc - 1], &count); + if (data == NULL) { + return TCL_ERROR; + } + TclNewObj(resultObj); rawLength = (lineLength - 1) * 3 / 4; start = cursor = Tcl_SetByteArrayLength(resultObj, (lineLength + wrapcharlen) * ((count + (rawLength - 1)) / rawLength)); n = bits = 0; @@ -2931,11 +2828,11 @@ * the encoded data follows (encoding each 6 bits as one character). * Encoded lines are always terminated by a newline. */ while (offset < count) { - int lineLen = count - offset; + Tcl_Size lineLen = count - offset; if (lineLen > rawLength) { lineLen = rawLength; } *cursor++ = UueDigits[lineLen]; @@ -2981,20 +2878,20 @@ *---------------------------------------------------------------------- */ static int BinaryDecodeUu( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj = NULL; unsigned char *data, *datastart, *dataend; unsigned char *begin, *cursor; int i, index, pure = 1, strict = 0, lineLen; - size_t size, count = 0; + Tcl_Size size, count = 0; unsigned char c; int ucs4; enum { OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; @@ -3013,14 +2910,14 @@ break; } } TclNewObj(resultObj); - data = TclGetBytesFromObj(NULL, objv[objc - 1], &count); + data = Tcl_GetByteArrayFromObj(objv[objc - 1], &count); if (data == NULL) { pure = 0; - data = (unsigned char *) TclGetStringFromObj(objv[objc - 1], &count); + data = (unsigned char *) Tcl_GetStringFromObj(objv[objc - 1], &count); } datastart = data; dataend = data + count; size = ((count + 3) & ~3) * 3 / 4; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); @@ -3119,24 +3016,24 @@ Tcl_SetObjResult(interp, resultObj); return TCL_OK; shortUu: Tcl_SetObjResult(interp, Tcl_ObjPrintf("short uuencode data")); - Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "SHORT", NULL); + Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "SHORT", (void *)NULL); TclDecrRefCount(resultObj); return TCL_ERROR; badUu: if (pure) { ucs4 = c; } else { - TclUtfToUCS4((const char *)(data - 1), &ucs4); + Tcl_UtfToUniChar((const char *)(data - 1), &ucs4); } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid uuencode character \"%c\" (U+%06X) at position %" TCL_Z_MODIFIER "u", ucs4, ucs4, data - datastart - 1)); - Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", NULL); + Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", (void *)NULL); TclDecrRefCount(resultObj); return TCL_ERROR; } /* @@ -3155,11 +3052,11 @@ *---------------------------------------------------------------------- */ static int BinaryDecode64( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj = NULL; @@ -3166,11 +3063,11 @@ unsigned char *data, *datastart, *dataend, c = '\0'; unsigned char *begin = NULL; unsigned char *cursor = NULL; int pure = 1, strict = 0; int i, index, cut = 0; - size_t size, count = 0; + Tcl_Size size, count = 0; int ucs4; enum { OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { @@ -3188,14 +3085,14 @@ break; } } TclNewObj(resultObj); - data = TclGetBytesFromObj(NULL, objv[objc - 1], &count); + data = Tcl_GetByteArrayFromObj(objv[objc - 1], &count); if (data == NULL) { pure = 0; - data = (unsigned char *) TclGetStringFromObj(objv[objc - 1], &count); + data = (unsigned char *) Tcl_GetStringFromObj(objv[objc - 1], &count); } datastart = data; dataend = data + count; size = ((count + 3) & ~3) * 3 / 4; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); @@ -3302,17 +3199,17 @@ /* 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_UtfToUniChar((const char *)(data - 1), &ucs4); } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid base64 character \"%c\" (U+%06X) at position %" TCL_Z_MODIFIER "u", ucs4, ucs4, data - datastart - 1)); - Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", NULL); + Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", (void *)NULL); TclDecrRefCount(resultObj); return TCL_ERROR; } /* ADDED generic/tclBrodnik.c Index: generic/tclBrodnik.c ================================================================== --- /dev/null +++ generic/tclBrodnik.c @@ -0,0 +1,293 @@ +/* + * tclBrodnik.c -- + * + * This file contains the implementation of a BrodnikArray. + * + * Contributions from Don Porter, NIST, 2013. (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 "tclBrodnik.h" + +#if defined(HAVE_INTRIN_H) +# include +#ifdef _WIN64 +# pragma intrinsic(_BitScanReverse64) +#else +# pragma intrinsic(_BitScanReverse) +#endif +#endif + +/* + *---------------------------------------------------------------------- + * + * TclMSB -- + * + * Given a size_t non-zero value n, return the index of the most + * significant bit in n that is set. This is equivalent to returning + * trunc(log2(n)). It's also equivalent to the largest integer k + * such that 2^k <= n. + * + * This routine is adapted from Andrej Brodnik, "Computation of the + * Least Significant Set Bit", pp 7-10, Proceedings of the 2nd + * Electrotechnical and Computer Science Conference, Portoroz, + * Slovenia, 1993. The adaptations permit the computation to take + * place within size_t values without the need for double length + * buffers for calculation. They also fill in a number of details + * the paper omits or leaves unclear. + * + * Results: + * The index of the most significant set bit in n, a value between + * 0 and CHAR_BIT*sizeof(size_t) - 1, inclusive. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TclMSB( + size_t n) +{ + const int M = CHAR_BIT * sizeof(size_t); /* Bits in a size_t */ + + /* + * TODO: This function corresponds to a processor instruction on + * many platforms. Add here the various platform and compiler + * specific incantations to invoke those assembly instructions. + */ +#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))) + return n ? M - 1 - __builtin_clzll(n) : 0; +#endif + +#if defined(_MSC_VER) && _MSCVER >= 1300 + unsigned long result; + +#ifdef _WIN64 + (void) _BitScanReverse64(&result, n) +#else + (void) _BitScanReverse(&result, n) +#endif + + return result; +#endif + + if (M == 64) { + + /* + * For a byte, consider two masks, C1 = 10000000 selecting just + * the high bit, and C2 = 01111111 selecting all other bits. + * Then for any byte value n, the computation + * LEAD(n) = C1 & (n | (C2 + (n & C2))) + * will leave all bits but the high bit unset, and will have the + * high bit set iff n!=0. The whole thing is an 8-bit test + * for being non-zero. For an 8-byte size_t, each byte can have + * the test applied all at once, with combined masks. + */ + const size_t C1 = 0x8080808080808080; + const size_t C2 = 0x7F7F7F7F7F7F7F7F; +#define LEAD(n) (C1 & (n | (C2 + (n & C2)))) + + /* + * To shift a bit to a new place, multiplication by 2^k will do. + * To shift the top 7 bits produced by the LEAD test to the high + * 7 bits of the entire size_t, multiply by the right sum of + * powers of 2. In this case + * Q = 1 + 2^7 + 2^14 + 2^21 + 2^28 + 2^35 + 2^42 + * Then shift those 7 bits down to the low 7 bits of the size_t. + * The key to making this work is that none of the shifted bits + * collide with each other in the top 7-bit destination. + * Note that we lose the bit that indicates whether the low byte + * is non-zero. That doesn't matter because we require the original + * value n to be non-zero, so if all other bytes signal to be zero, + * we know the low byte is non-zero, and if one of the other bytes + * signals non-zero, we just don't care what the low byte is. + */ + const size_t Q = 0x0000040810204081; + + /* + * To place a copy of a 7-bit value in each of 7 bytes in + * a size_t, just multply by the right value. In this case + * P = 0x00 01 01 01 01 01 01 01 + * We don't put a copy in the high byte since analysis of the + * remaining steps in the algorithm indicates we do not need it. + */ + const size_t P = 0x0001010101010101; + + /* + * With 7 copies of the LEAD value, we can now apply 7 masks + * to it in a single step by an & against the right value. + * B = 00000000 01111111 01111110 01111100 + * 01111000 01110000 01100000 01000000 + * The higher the MSB of the copied value is, the more of the + * B-masked bytes stored in t will be non-zero. + */ + const size_t B = 0x007F7E7C78706040; + size_t t = B & P * (LEAD(n) * Q >> 57); + + /* + * We want to get a count of the non-zero bytes stored in t. + * First use LEAD(t) to create a set of high bits signaling + * non-zero values as before. Call this value + * X = x6*2^55 +x5*2^47 +x4*2^39 +x3*2^31 +x2*2^23 +x1*2^15 +x0*2^7 + * Then notice what multiplication by + * P = 2^48 + 2^40 + 2^32 + 2^24 + 2^16 + 2^8 + 1 + * produces: + * P*X = x0*2^7 + (x0 + x1)*2^15 + ... + * ... + (x0 + x1 + x2 + x3 + x4 + x5 + x6) * 2^55 + ... + * ... + (x5 + x6)*2^95 + x6*2^103 + * The high terms of this product are going to overflow the size_t + * and get lost, but we don't care about them. What we care is that + * the 2^55 term is exactly the sum we seek. We shift the product + * down by 55 bits and then mask away all but the bottom 3 bits + * (Max sum can be 7) we get exactly the count of non-zero B-masked + * bytes. By design of the mask, this count is the index of the + * MSB of the LEAD value. It indicates which byte of the original + * value contains the MSB of the original value. + */ +#define SUM(t) (0x7 & (int)(LEAD(t) * P >> 55)); + + /* + * Multiply by 8 to get the number of bits to shift to place + * that MSB-containing byte in the low byte. + */ + int k = 8 * SUM(t); + + /* + * Shift the MSB byte to the low byte. Then shift one more bit. + * Since we know the MSB byte is non-zero we only need to compute + * the MSB of the top 7 bits. If all top 7 bits are zero, we know + * the bottom bit is the 1 and the correct index is 0. Compute the + * MSB of that value by the same steps we did before. + */ + t = B & P * (n >> k >> 1); + + /* + * Add the index of the MSB of the byte to the index of the low + * bit of that byte computed before to get the final answer. + */ + return k + SUM(t); + + /* Total operations: 33 + * 10 bit-ands, 6 multiplies, 4 adds, 5 rightshifts, + * 3 assignments, 3 bit-ors, 2 typecasts. + * + * The whole task is one direct computation. + * No branches. No loops. + * + * 33 operations cannot beat one instruction, so assembly + * wins and should be used wherever possible, but this isn't bad. + */ + +#undef SUM + } else if (M == 32) { + + /* Same scheme as above, with adjustments to the 32-bit size */ + const size_t C1 = 0xA0820820; + const size_t C2 = 0x5F7DF7DF; + const size_t C3 = 0xC0820820; + const size_t C4 = 0x20000000; + const size_t Q = 0x00010841; + const size_t P = 0x01041041; + const size_t B = 0x1F79C610; + +#define SUM(t) (0x7 & (LEAD(t) * P >> 29)); + + size_t t = B & P * ((C3 & (LEAD(n) + C4)) * Q >> 27); + int k = 6 * SUM(t); + + t = B & P * (n >> k >> 1); + return k + SUM(t); + + /* Total operations: 33 + * 11 bit-ands, 6 multiplies, 5 adds, 5 rightshifts, + * 3 assignments, 3 bit-ors. + */ + +#undef SUM +#undef LEAD + + } else { + /* Simple and slow fallback for cases we haven't done yet. */ + int k = 0; + + while (n >>= 1) { + k++; + } + return k; + } +} + +/* + *---------------------------------------------------------------------- + * + * TclBAConvertIndices -- + * + * Given a size_t index into the sequence, convert into the + * corresponding index pair of the store[] of a BrodnikArray. + * + * store[] is an array of arrays, and as the total size grows + * larger, the size of the arrays store[i] grow in a way that + * each new array is of about size sqrt(N), yet the index conversion + * routine remains relatively simple to calculate. + * + * Results: + * The index pair is written to *hiPtr and *loPtr, which may not + * be NULL. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TclBAConvertIndices( + size_t index, + unsigned int *hiPtr, + unsigned int *loPtr) +{ + size_t r = index + 1; + int k = TclMSB(r); + int shift = (k + 1) >> 1; + unsigned int lobits = (1 << shift) - 1; + unsigned int hibits = 1 << (k - shift); + + *hiPtr = (lobits << 1) - ((k & 1) * hibits) + + ((r >> shift) & (hibits - 1)); + *loPtr = r & lobits; +} + +/* + *---------------------------------------------------------------------- + * + * TclBAInvertIndices -- + * + * Given a size_t index pair hi, lo into the store[] of a BrodnikArray, + * compute and return the size_t index of the element found there. + * + * Results: + * The size_t index value. + * + * Side effects: + * None. + *---------------------------------------------------------------------- + */ + +size_t +TclBAInvertIndices( + unsigned int hi, + unsigned int lo) +{ + size_t plus2 = hi + 2; + int n = TclMSB(plus2) - 1; + unsigned int bit = (((size_t)1)<hi = 0; \ + newPtr->lo = 0; \ + newPtr->dbsize = 1; \ + newPtr->count = 0; \ + newPtr->dbused = 1; \ + newPtr->dbavail = 1; \ + newPtr->store = (T **)Tcl_Alloc(sizeof(T *)); \ + newPtr->store[0] = (T *)Tcl_Alloc(sizeof(T)); \ + return newPtr; \ +} \ + \ +scope void \ +BA_ ## T ## _Destroy( \ + BA_ ## T *a) \ +{ \ + unsigned int i = a->dbused; \ + \ + while (i--) { \ + Tcl_Free(a->store[i]); \ + } \ + Tcl_Free(a->store); \ + Tcl_Free(a); \ +} \ + \ +scope Tcl_Size \ +BA_ ## T ## _Size( \ + BA_ ## T *a) \ +{ \ + if (a == NULL) { \ + return 0; \ + } \ + return TclBAInvertIndices(a->hi, a->lo); \ +} \ + \ +scope void \ +BA_ ## T ## _Grow( \ + BA_ ## T *a) \ +{ \ + if (a->dbused == a->dbavail) { \ + a->dbavail *= 2; \ + a->store = (T **)Tcl_Realloc(a->store, a->dbavail*sizeof(T *)); \ + } \ + a->store[a->dbused] = (T *)Tcl_Alloc(a->dbsize * sizeof(T)); \ + a->dbused++; \ +} \ + \ +scope void \ +BA_ ## T ## _Shrink( \ + BA_ ## T *a) \ +{ \ + a->dbused--; \ + Tcl_Free(a->store[a->dbused]); \ + if (a->dbavail / a->dbused >= 4) { \ + a->dbavail /= 2; \ + a->store = (T **)Tcl_Realloc(a->store, a->dbavail*sizeof(T *)); \ + } \ +} \ + \ +scope void \ +BA_ ## T ## _Copy( \ + T *p, \ + BA_ ## T *a) \ +{ \ + unsigned int i = 0, n = 1, m = 0; \ + if (a->hi == 0) { \ + return; \ + } \ + while (i < a->hi) { \ + memcpy(p, a->store[i++], n * sizeof(T)); \ + p += n; \ + if (m == 0) { \ + m = n; n *= 2; m += n; \ + } \ + m--; \ + } \ + if (a->lo) { \ + memcpy(p, a->store[a->hi], a->lo * sizeof(T)); \ + } \ +} \ + \ +scope T * \ +BA_ ## T ## _Append( \ + BA_ ## T *a) \ +{ \ + T *elemPtr; \ + if (a->hi == a->dbused) { \ + BA_ ## T ## _Grow(a); \ + } \ + elemPtr = a->store[a->hi] + a->lo; \ + a->lo++; \ + if (a->lo == a->dbsize) { \ + a->lo = 0; \ + a->hi++; \ + if (a->count == 0) { \ + a->count = a->dbsize; \ + a->dbsize *= 2; \ + a->count += a->dbsize; \ + } \ + a->count--; \ + } \ + return elemPtr; \ +} \ + \ +scope T * \ +BA_ ## T ## _Detach( \ + BA_ ## T *a) \ +{ \ + T *elemPtr; \ + if (a->hi == 0) { \ + return NULL; \ + } \ + if (a->lo) { \ + a->lo--; \ + } else { \ + a->hi--; \ + a->count++; \ + if (a->count == 3 * (a->dbsize / 2)) { \ + a->count = 0; \ + a->dbsize /= 2; \ + } \ + a->lo = a->dbsize - 1; \ + } \ + elemPtr = a->store[a->hi] + a->lo; \ + if (a->lo == 0 && (a->hi != a->dbused - 1)) { \ + BA_ ## T ## _Shrink(a); \ + } \ + return elemPtr; \ +} \ + \ +scope T * \ +BA_ ## T ## _Get( \ + BA_ ## T *a, \ + size_t index, \ + BP_ ## T *p) \ +{ \ + unsigned int hi, lo; \ + \ + TclBAConvertIndices(index, &hi, &lo); \ + if (hi > a->hi || (hi == a->hi && lo >= a->lo)) { \ + if (p) {p->ptr = NULL;} \ + return NULL; \ + } \ + if (p) { \ + size_t plus2 = hi + 2; \ + int n = TclMSB(plus2) - 1; \ + p->array = a; \ + p->hi = hi; \ + p->lo = lo; \ + p->dbsize = 1 << (n + ((plus2 >> n) & 1)); \ + p->count = 3 * p->dbsize - 3 - hi; \ + p->ptr = a->store[hi] + lo; \ + } \ + return a->store[hi] + lo; \ +} \ + \ +scope T * \ +BA_ ## T ## _At( \ + BA_ ## T *a, \ + size_t index) \ +{ \ + return BA_ ## T ## _Get(a, index, NULL); \ +} \ + \ +scope T * \ +BA_ ## T ## _First( \ + BA_ ## T *a, \ + BP_ ## T *p) \ +{ \ + p->array = a; \ + p->hi = 0; \ + p->lo = 0; \ + p->dbsize = 1; \ + p->count = 0; \ + p->ptr = (a->hi) ? a->store[0] : NULL; \ + return p->ptr; \ +} \ + \ +scope T * \ +BP_ ## T ## _Next( \ + BP_ ## T *p) \ +{ \ + if (p->ptr) { \ + p->lo++; \ + if (p->lo < p->dbsize) { \ + p->ptr++; \ + } else { \ + p->lo = 0; \ + p->hi++; \ + p->ptr = (p->hi < p->array->dbused) \ + ? p->array->store[p->hi] : NULL; \ + if (p->count == 0) { \ + p->count = p->dbsize; \ + p->dbsize *= 2; \ + p->count += p->dbsize; \ + } \ + p->count--; \ + } \ + if (p->hi > p->array->hi \ + || (p->hi == p->array->hi && p->lo >= p->array->lo)) { \ + p->ptr = NULL; \ + } \ + } \ + return p->ptr; \ +} \ + \ +scope T * \ +BP_ ## T ## _Plus( \ + BP_ ## T *p, \ + size_t incr) \ +{ \ + if (p->ptr) { \ + size_t index = TclBAInvertIndices(p->hi, p->lo); \ + index += incr; \ + return BA_ ## T ## _Get(p->array, index, p); \ + } \ + return p->ptr; \ +} \ + \ +scope T * \ +BP_ ## T ## _Minus( \ + BP_ ## T *p, \ + size_t incr) \ +{ \ + if (p->ptr) { \ + size_t index = TclBAInvertIndices(p->hi, p->lo); \ + if (index < incr) { \ + return p->ptr = NULL; \ + } \ + index -= incr; \ + return BA_ ## T ## _Get(p->array, index, p); \ + } \ + return p->ptr; \ +} + Index: generic/tclCkalloc.c ================================================================== --- generic/tclCkalloc.c +++ generic/tclCkalloc.c @@ -3,21 +3,22 @@ * * Interface to malloc and free that provides support for debugging * problems involving overwritten, double freeing memory and loss of * memory. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * This code contributed by Karl Lehenbauer and Mark Diekhans */ #include "tclInt.h" +#include #define FALSE 0 #define TRUE 1 #undef Tcl_Alloc @@ -34,16 +35,16 @@ */ typedef struct { size_t refCount; /* Number of mem_headers referencing this * tag. */ - char string[1]; /* Actual size of string will be as large as + char string[TCLFLEXARRAY]; /* Actual size of string will be as large as * needed for actual tag. This must be the * last field in the structure. */ } MemTag; -#define TAG_SIZE(bytesInString) ((offsetof(MemTag, string) + 1) + bytesInString) +#define TAG_SIZE(bytesInString) ((offsetof(MemTag, string) + 1U) + (bytesInString)) static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers (set * by "memory tag" command). */ /* @@ -63,17 +64,17 @@ int line; unsigned char low_guard[LOW_GUARD_SIZE]; /* Aligns body on 8-byte boundary, plus * provides at least 8 additional guard bytes * to detect underruns. */ - char body[1]; /* First byte of client's space. Actual size + char body[TCLFLEXARRAY]; /* First byte of client's space. Actual size * of this field will be larger than one. */ }; static struct mem_header *allocHead = NULL; /* List of allocated structures */ -#define GUARD_VALUE 0141 +#define GUARD_VALUE 0x61 /* * The following macro determines the amount of guard space *above* each chunk * of memory. */ @@ -87,18 +88,18 @@ */ #define BODY_OFFSET \ ((size_t) (&((struct mem_header *) 0)->body)) -static unsigned int total_mallocs = 0; -static unsigned int total_frees = 0; +static size_t total_mallocs = 0; +static size_t total_frees = 0; static size_t current_bytes_malloced = 0; static size_t maximum_bytes_malloced = 0; -static unsigned int current_malloc_packets = 0; -static unsigned int maximum_malloc_packets = 0; -static unsigned int break_on_malloc = 0; -static unsigned int trace_on_at_malloc = 0; +static size_t current_malloc_packets = 0; +static size_t maximum_malloc_packets = 0; +static size_t break_on_malloc = 0; +static size_t trace_on_at_malloc = 0; static int alloc_tracing = FALSE; static int init_malloced_bodies = TRUE; #ifdef MEM_VALIDATE static int validate_memory = TRUE; #else @@ -125,23 +126,10 @@ */ 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 -- * @@ -175,24 +163,24 @@ *---------------------------------------------------------------------- */ int TclDumpMemoryInfo( - ClientData clientData, + void *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" + snprintf(buf, sizeof(buf), + "total mallocs %10" TCL_Z_MODIFIER "u\n" + "total frees %10" TCL_Z_MODIFIER "u\n" + "current packets allocated %10" TCL_Z_MODIFIER "u\n" "current bytes allocated %10" TCL_Z_MODIFIER "u\n" - "maximum packets allocated %10u\n" + "maximum packets allocated %10" TCL_Z_MODIFIER "u\n" "maximum bytes allocated %10" TCL_Z_MODIFIER "u\n", total_mallocs, total_frees, current_malloc_packets, current_bytes_malloced, @@ -379,11 +367,11 @@ *---------------------------------------------------------------------- * * Tcl_DbCkalloc - debugging Tcl_Alloc * * Allocate the requested amount of space plus some extra for guard bands - * at both ends of the request, plus a size, panicing if there isn't + * at both ends of the request, plus a size, panicking if there isn't * enough space, then write in the guard bands and return the address of * the space in the middle that the user asked for. * * The second and third arguments are file and line, these contain the * filename and line number corresponding to the caller. These are sent @@ -404,13 +392,13 @@ if (validate_memory) { Tcl_ValidateAllMemory(file, line); } /* Don't let size argument to TclpAlloc overflow */ - if (size <= UINT_MAX - HIGH_GUARD_SIZE -sizeof(struct mem_header)) { + if (size <= (size_t)-2 - offsetof(struct mem_header, body) - HIGH_GUARD_SIZE) { result = (struct mem_header *) TclpAlloc(size + - sizeof(struct mem_header) + HIGH_GUARD_SIZE); + offsetof(struct mem_header, body) + 1U + HIGH_GUARD_SIZE); } if (result == NULL) { fflush(stdout); TclDumpMemoryInfo(stderr, 0); Tcl_Panic("unable to alloc %" TCL_Z_MODIFIER "u bytes, %s line %d", size, file, line); @@ -422,11 +410,11 @@ * allocated list. */ if (init_malloced_bodies) { memset(result, GUARD_VALUE, - size + sizeof(struct mem_header) + HIGH_GUARD_SIZE); + offsetof(struct mem_header, body) + 1U + HIGH_GUARD_SIZE + size); } else { memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE); memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE); } if (!ckallocInit) { @@ -449,11 +437,11 @@ allocHead = result; total_mallocs++; if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) { (void) fflush(stdout); - fprintf(stderr, "reached malloc trace enable point (%u)\n", + fprintf(stderr, "reached malloc trace enable point (%" TCL_Z_MODIFIER "u)\n", total_mallocs); fflush(stderr); alloc_tracing = TRUE; trace_on_at_malloc = 0; } @@ -464,11 +452,11 @@ } if (break_on_malloc && (total_mallocs >= break_on_malloc)) { break_on_malloc = 0; (void) fflush(stdout); - Tcl_Panic("reached malloc break limit (%u)", total_mallocs); + Tcl_Panic("reached malloc break limit (%" TCL_Z_MODIFIER "u)", total_mallocs); } current_malloc_packets++; if (current_malloc_packets > maximum_malloc_packets) { maximum_malloc_packets = current_malloc_packets; @@ -494,13 +482,13 @@ if (validate_memory) { Tcl_ValidateAllMemory(file, line); } /* Don't let size argument to TclpAlloc overflow */ - if (size <= UINT_MAX - HIGH_GUARD_SIZE - sizeof(struct mem_header)) { + if (size <= (size_t)-2 - offsetof(struct mem_header, body) - HIGH_GUARD_SIZE) { result = (struct mem_header *) TclpAlloc(size + - sizeof(struct mem_header) + HIGH_GUARD_SIZE); + offsetof(struct mem_header, body) + 1U + HIGH_GUARD_SIZE); } if (result == NULL) { fflush(stdout); TclDumpMemoryInfo(stderr, 0); return NULL; @@ -511,11 +499,11 @@ * with bogus bytes to detect uses of initialized data. Link into * allocated list. */ if (init_malloced_bodies) { memset(result, GUARD_VALUE, - size + sizeof(struct mem_header) + HIGH_GUARD_SIZE); + offsetof(struct mem_header, body) + 1U + HIGH_GUARD_SIZE + size); } else { memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE); memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE); } if (!ckallocInit) { @@ -538,11 +526,11 @@ allocHead = result; total_mallocs++; if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) { (void) fflush(stdout); - fprintf(stderr, "reached malloc trace enable point (%d)\n", + fprintf(stderr, "reached malloc trace enable point (%" TCL_Z_MODIFIER "u)\n", total_mallocs); fflush(stderr); alloc_tracing = TRUE; trace_on_at_malloc = 0; } @@ -553,11 +541,11 @@ } if (break_on_malloc && (total_mallocs >= break_on_malloc)) { break_on_malloc = 0; (void) fflush(stdout); - Tcl_Panic("reached malloc break limit (%d)", total_mallocs); + Tcl_Panic("reached malloc break limit (%" TCL_Z_MODIFIER "u)", total_mallocs); } current_malloc_packets++; if (current_malloc_packets > maximum_malloc_packets) { maximum_malloc_packets = current_malloc_packets; @@ -808,11 +796,11 @@ * *---------------------------------------------------------------------- */ static int MemoryCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Obj values of arguments. */ { const char *fileName; @@ -843,23 +831,23 @@ return TCL_ERROR; } return TCL_OK; } if (strcmp(TclGetString(objv[1]),"break_on_malloc") == 0) { - int value; + Tcl_WideInt value; if (objc != 3) { goto argError; } - if (Tcl_GetIntFromObj(interp, objv[2], &value) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, objv[2], &value) != TCL_OK) { return TCL_ERROR; } - break_on_malloc = (unsigned int) value; + break_on_malloc = value; return TCL_OK; } if (strcmp(TclGetString(objv[1]),"info") == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "%-25s %10u\n%-25s %10u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER"u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER "u\n", + "%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n%-25s %10" TCL_Z_MODIFIER "u\n", "total mallocs", total_mallocs, "total frees", total_frees, "current packets allocated", current_malloc_packets, "current bytes allocated", current_bytes_malloced, "maximum packets allocated", maximum_malloc_packets, "maximum bytes allocated", maximum_bytes_malloced)); @@ -928,15 +916,15 @@ alloc_tracing = (strcmp(TclGetString(objv[2]),"on") == 0); return TCL_OK; } if (strcmp(TclGetString(objv[1]),"trace_on_at_malloc") == 0) { - int value; + Tcl_WideInt value; if (objc != 3) { goto argError; } - if (Tcl_GetIntFromObj(interp, objv[2], &value) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, objv[2], &value) != TCL_OK) { return TCL_ERROR; } trace_on_at_malloc = value; return TCL_OK; } @@ -978,17 +966,13 @@ * Side effects: * None. * *---------------------------------------------------------------------- */ -static int CheckmemCmd(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); - static int CheckmemCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter for evaluation. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Obj values of arguments. */ { if (objc != 2) { @@ -1240,17 +1224,159 @@ { } int TclDumpMemoryInfo( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), TCL_UNUSED(int) /*flags*/) { return 1; } #endif /* TCL_MEM_DEBUG */ + +/* + *------------------------------------------------------------------------ + * + * TclAllocElemsEx -- + * + * See TclAttemptAllocElemsEx. This function differs in that it panics + * on failure. + * + * Results: + * Non-NULL pointer to allocated memory block. + * + * Side effects: + * Panics if memory of at least the requested size could not be + * allocated. + * + *------------------------------------------------------------------------ + */ +void * +TclAllocElemsEx( + Tcl_Size elemCount, /* Allocation will store at least these many... */ + Tcl_Size elemSize, /* ...elements of this size */ + Tcl_Size leadSize, /* Additional leading space in bytes */ + Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored + here if non-NULL. Only modified on success */ +{ + void *ptr = TclAttemptReallocElemsEx( + NULL, elemCount, elemSize, leadSize, capacityPtr); + if (ptr == NULL) { + Tcl_Panic("Failed to allocate %" TCL_SIZE_MODIFIER + "d elements of size %" TCL_SIZE_MODIFIER "d bytes.", + elemCount, + elemSize); + } + return ptr; +} + +/* + *------------------------------------------------------------------------ + * + * TclAttemptReallocElemsEx -- + * + * Attempts to allocate (oldPtr == NULL) or reallocate memory of the + * requested size plus some more for future growth. The amount of + * reallocation is adjusted depending on 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 -- Index: generic/tclClock.c ================================================================== --- generic/tclClock.c +++ generic/tclClock.c @@ -3,19 +3,20 @@ * * Contains the time and date related commands. This code is derived from * the time and date facilities of TclX, by Mark Diekhans and Karl * Lehenbauer. * - * Copyright 1991-1995 Karl Lehenbauer and Mark Diekhans. - * Copyright (c) 1995 Sun Microsystems, Inc. - * Copyright (c) 2004 by Kevin B. Kenny. All rights reserved. + * Copyright © 1991-1995 Karl Lehenbauer & Mark Diekhans. + * Copyright © 1995 Sun Microsystems, Inc. + * Copyright © 2004 Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" +#include "tclTomMath.h" /* * Windows has mktime. The configurators do not check. */ @@ -140,61 +141,41 @@ */ static int ConvertUTCToLocal(Tcl_Interp *, TclDateFields *, Tcl_Obj *, int); static int ConvertUTCToLocalUsingTable(Tcl_Interp *, - TclDateFields *, int, Tcl_Obj *const[]); + TclDateFields *, Tcl_Size, 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[]); + TclDateFields *, Tcl_Size, Tcl_Obj *const[]); static int ConvertLocalToUTCUsingC(Tcl_Interp *, TclDateFields *, int); static Tcl_Obj * LookupLastTransition(Tcl_Interp *, Tcl_WideInt, - int, Tcl_Obj *const *); + Tcl_Size, 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 Tcl_ObjCmdProc ClockClicksObjCmd; +static Tcl_ObjCmdProc ClockConvertlocaltoutcObjCmd; +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 ClockParseformatargsObjCmd; +static Tcl_ObjCmdProc ClockSecondsObjCmd; static struct tm * ThreadSafeLocalTime(const time_t *); static void TzsetIfNecessary(void); -static void ClockDeleteCmdProc(ClientData); +static void ClockDeleteCmdProc(void *); /* * Structure containing description of "native" clock commands to create. */ @@ -329,11 +310,11 @@ *---------------------------------------------------------------------- */ static int ClockConvertlocaltoutcObjCmd( - ClientData clientData, /* Client data */ + void *clientData, /* Client data */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { ClockClientData *data = (ClockClientData *)clientData; @@ -421,11 +402,11 @@ *---------------------------------------------------------------------- */ int ClockGetdatefieldsObjCmd( - ClientData clientData, /* Opaque pointer to literal pool, etc. */ + void *clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { TclDateFields fields; @@ -450,11 +431,11 @@ /* * fields.seconds could be an unsigned number that overflowed. Make sure * that it isn't. */ - if (TclHasIntRep(objv[1], &tclBignumType)) { + if (TclHasInternalRep(objv[1], &tclBignumType)) { Tcl_SetObjResult(interp, lit[LIT_INTEGER_VALUE_TOO_LARGE]); return TCL_ERROR; } /* @@ -464,15 +445,17 @@ if (ConvertUTCToLocal(interp, &fields, objv[2], changeover) != TCL_OK) { return TCL_ERROR; } /* - * Extract Julian day. + * Extract Julian day. Always round the quotient down by subtracting 1 + * when the remainder is negative (i.e. if the quotient was rounded up). */ - fields.julianDay = (int) ((fields.localSeconds + JULIAN_SEC_POSIX_EPOCH) - / SECONDS_PER_DAY); + fields.julianDay = (int) ((fields.localSeconds / SECONDS_PER_DAY) - + ((fields.localSeconds % SECONDS_PER_DAY) < 0) + + JULIAN_DAY_POSIX_EPOCH); /* * Convert to Julian or Gregorian calendar. */ @@ -575,11 +558,11 @@ return TclGetIntFromObj(interp, value, storePtr); } static int ClockGetjuliandayfromerayearmonthdayObjCmd( - ClientData clientData, /* Opaque pointer to literal pool, etc. */ + void *clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { TclDateFields fields; @@ -659,11 +642,11 @@ *---------------------------------------------------------------------- */ static int ClockGetjuliandayfromerayearweekdayObjCmd( - ClientData clientData, /* Opaque pointer to literal pool, etc. */ + void *clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { TclDateFields fields; @@ -745,18 +728,18 @@ 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_Size 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) { + if (TclListObjGetElementsM(interp, tzdata, &rowc, &rowv) != TCL_OK) { return TCL_ERROR; } /* * Special case: If the time zone is :localtime, the tzdata will be empty. @@ -790,15 +773,15 @@ 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_Size rowc, /* Number of points at which time changes */ Tcl_Obj *const rowv[]) /* Points at which time changes */ { Tcl_Obj *row; - int cellc; + Tcl_Size cellc; Tcl_Obj **cellv; int have[8]; int nHave = 0; int i; int found; @@ -817,11 +800,11 @@ fields->tzOffset = 0; fields->seconds = fields->localSeconds; while (!found) { row = LookupLastTransition(interp, fields->seconds, rowc, rowv); if ((row == NULL) - || TclListObjGetElements(interp, row, &cellc, + || TclListObjGetElementsM(interp, row, &cellc, &cellv) != TCL_OK || TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) { return TCL_ERROR; } @@ -948,18 +931,18 @@ 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_Size 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) { + if (TclListObjGetElementsM(interp, tzdata, &rowc, &rowv) != TCL_OK) { return TCL_ERROR; } /* * Special case: If the time zone is :localtime, the tzdata will be empty. @@ -993,25 +976,25 @@ static int ConvertUTCToLocalUsingTable( Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the date */ - int rowc, /* Number of rows in the conversion table + Tcl_Size rowc, /* Number of rows in the conversion table * (>= 1) */ Tcl_Obj *const rowv[]) /* Rows of the conversion table */ { Tcl_Obj *row; /* Row containing the current information */ - int cellc; /* Count of cells in the row (must be 4) */ + Tcl_Size cellc; /* Count of cells in the row (must be 4) */ Tcl_Obj **cellv; /* Pointers to the cells */ /* * Look up the nearest transition time. */ row = LookupLastTransition(interp, fields->seconds, rowc, rowv); if (row == NULL || - TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK || + TclListObjGetElementsM(interp, row, &cellc, &cellv) != TCL_OK || TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) { return TCL_ERROR; } /* @@ -1060,20 +1043,20 @@ 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); + Tcl_SetErrorCode(interp, "CLOCK", "argTooLarge", (void *)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); + Tcl_SetErrorCode(interp, "CLOCK", "localtimeFailed", (void *)NULL); return TCL_ERROR; } /* * Fill in the date in 'fields' and use it to derive Julian Day. @@ -1103,16 +1086,16 @@ *buffer = '-'; diff = -diff; } else { *buffer = '+'; } - sprintf(buffer+1, "%02d", diff / 3600); + snprintf(buffer+1, sizeof(buffer) - 1, "%02d", diff / 3600); diff %= 3600; - sprintf(buffer+3, "%02d", diff / 60); + snprintf(buffer+3, sizeof(buffer) - 3, "%02d", diff / 60); diff %= 60; if (diff > 0) { - sprintf(buffer+5, "%02d", diff); + snprintf(buffer+5, sizeof(buffer) - 5, "%02d", diff); } fields->tzName = Tcl_NewStringObj(buffer, -1); Tcl_IncrRefCount(fields->tzName); return TCL_OK; } @@ -1133,15 +1116,15 @@ 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_Size rowc, /* Number of rows of tzdata */ Tcl_Obj *const *rowv) /* Rows in tzdata */ { - int l; - int u; + Tcl_Size l; + Tcl_Size u; Tcl_Obj *compObj; Tcl_WideInt compVal; /* * Examine the first row to make sure we're in bounds. @@ -1518,13 +1501,13 @@ #else /* * Have to make sure quotient is truncated towards 0 when negative. * See above bug for details. The casts are necessary. */ - if (ym1 >= 0) + if (ym1 >= 0) { ym1o4 = ym1 / 4; - else { + } else { ym1o4 = - (int) (((unsigned int) -ym1) / 4); } #endif if (ym1 % 4 < 0) { ym1o4--; @@ -1643,28 +1626,46 @@ *---------------------------------------------------------------------- */ int ClockGetenvObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { +#ifdef _WIN32 + const WCHAR *varName; + const WCHAR *varValue; + Tcl_DString ds; +#else const char *varName; const char *varValue; +#endif if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } +#ifdef _WIN32 + Tcl_DStringInit(&ds); + varName = Tcl_UtfToWCharDString(TclGetString(objv[1]), -1, &ds); + varValue = _wgetenv(varName); + if (varValue == NULL) { + Tcl_DStringFree(&ds); + } else { + Tcl_DStringSetLength(&ds, 0); + Tcl_WCharToUtfDString(varValue, -1, &ds); + Tcl_DStringResult(interp, &ds); + } +#else varName = TclGetString(objv[1]); varValue = getenv(varName); - if (varValue == NULL) { - varValue = ""; + if (varValue != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1)); } - Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1)); +#endif return TCL_OK; } /* *---------------------------------------------------------------------- @@ -1692,21 +1693,21 @@ * Get a thread-local buffer to hold the returned time. */ struct tm *tmPtr = (struct tm *)Tcl_GetThreadData(&tmKey, sizeof(struct tm)); #ifdef HAVE_LOCALTIME_R - localtime_r(timePtr, tmPtr); + tmPtr = localtime_r(timePtr, tmPtr); #else struct tm *sysTmPtr; Tcl_MutexLock(&clockMutex); sysTmPtr = localtime(timePtr); if (sysTmPtr == NULL) { Tcl_MutexUnlock(&clockMutex); return NULL; } - memcpy(tmPtr, localtime(timePtr), sizeof(struct tm)); + memcpy(tmPtr, sysTmPtr, sizeof(struct tm)); Tcl_MutexUnlock(&clockMutex); #endif return tmPtr; } @@ -1728,11 +1729,11 @@ *---------------------------------------------------------------------- */ int ClockClicksObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter values */ { static const char *const clicksSwitches[] = { @@ -1760,17 +1761,17 @@ } switch (index) { case CLICKS_MILLIS: Tcl_GetTime(&now); - clicks = (Tcl_WideInt) now.sec * 1000 + now.usec / 1000; + clicks = (Tcl_WideInt)(unsigned long long)now.sec * 1000 + now.usec / 1000; break; case CLICKS_NATIVE: #ifdef TCL_WIDE_CLICKS clicks = TclpGetWideClicks(); #else - clicks = (Tcl_WideInt) TclpGetClicks(); + clicks = (Tcl_WideInt)TclpGetClicks(); #endif break; case CLICKS_MICROS: clicks = TclpGetMicroseconds(); break; @@ -1798,24 +1799,26 @@ *---------------------------------------------------------------------- */ int ClockMillisecondsObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter values */ { Tcl_Time now; + Tcl_Obj *timeObj; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_GetTime(&now); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) - now.sec * 1000 + now.usec / 1000)); + TclNewUIntObj(timeObj, (Tcl_WideUInt) + now.sec * 1000 + now.usec / 1000); + Tcl_SetObjResult(interp, timeObj); return TCL_OK; } /*---------------------------------------------------------------------- * @@ -1835,11 +1838,11 @@ *---------------------------------------------------------------------- */ int ClockMicrosecondsObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter values */ { if (objc != 1) { @@ -1868,11 +1871,11 @@ *----------------------------------------------------------------------------- */ static int ClockParseformatargsObjCmd( - ClientData clientData, /* Client data containing literal pool */ + 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; @@ -1900,11 +1903,11 @@ 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); + Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", (void *)NULL); return TCL_ERROR; } /* * Extract values for the keywords. @@ -1915,11 +1918,11 @@ 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); + TclGetString(objv[i]), (void *)NULL); return TCL_ERROR; } switch (optionIndex) { case CLOCK_FORMAT_FORMAT: formatObj = objv[i+1]; @@ -1947,11 +1950,11 @@ 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); + Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", (void *)NULL); return TCL_ERROR; } if (gmtFlag) { timezoneObj = litPtr[LIT_GMT]; } @@ -1986,23 +1989,26 @@ *---------------------------------------------------------------------- */ int ClockSecondsObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter values */ { Tcl_Time now; + Tcl_Obj *timeObj; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_GetTime(&now); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) now.sec)); + TclNewUIntObj(timeObj, (Tcl_WideUInt)now.sec); + + Tcl_SetObjResult(interp, timeObj); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2018,31 +2024,57 @@ * 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 static void TzsetIfNecessary(void) { - static char* tzWas = (char *)INT2PTR(-1); /* Previous value of TZ, protected by - * clockMutex. */ - const char *tzIsNow; /* Current value of TZ */ + static WCHAR* tzWas = (WCHAR *)INT2PTR(-1); /* Previous value of TZ, protected by + * clockMutex. */ + static long long tzLastRefresh = 0; /* Used for latency before next refresh */ + static size_t tzEnvEpoch = 0; /* Last env epoch, for faster signaling, + that TZ changed via TCL */ + const WCHAR *tzIsNow; /* Current value of TZ */ + + /* + * Prevent performance regression on some platforms by resolving of system time zone: + * small latency for check whether environment was changed (once per second) + * no latency if environment was changed with tcl-env (compare both epoch values) + */ + Tcl_Time now; + Tcl_GetTime(&now); + if (now.sec == tzLastRefresh && tzEnvEpoch == TclEnvEpoch) { + return; + } + + tzEnvEpoch = TclEnvEpoch; + tzLastRefresh = now.sec; Tcl_MutexLock(&clockMutex); tzIsNow = getenv("TZ"); - if (tzIsNow != NULL && (tzWas == NULL || tzWas == INT2PTR(-1) - || strcmp(tzIsNow, tzWas) != 0)) { + if (tzIsNow != NULL && (tzWas == NULL || tzWas == (WCHAR *)INT2PTR(-1) + || wcscmp(tzIsNow, tzWas) != 0)) { tzset(); - if (tzWas != NULL && tzWas != INT2PTR(-1)) { + if (tzWas != NULL && tzWas != (WCHAR *)INT2PTR(-1)) { Tcl_Free(tzWas); } - tzWas = (char *)Tcl_Alloc(strlen(tzIsNow) + 1); - strcpy(tzWas, tzIsNow); + tzWas = (WCHAR *)Tcl_Alloc(sizeof(WCHAR) * (wcslen(tzIsNow) + 1)); + wcscpy(tzWas, tzIsNow); } else if (tzIsNow == NULL && tzWas != NULL) { tzset(); - if (tzWas != INT2PTR(-1)) Tcl_Free(tzWas); + if (tzWas != (WCHAR *)INT2PTR(-1)) Tcl_Free(tzWas); tzWas = NULL; } Tcl_MutexUnlock(&clockMutex); } @@ -2060,11 +2092,11 @@ *---------------------------------------------------------------------- */ static void ClockDeleteCmdProc( - ClientData clientData) /* Opaque pointer to the client data */ + void *clientData) /* Opaque pointer to the client data */ { ClockClientData *data = (ClockClientData *)clientData; int i; if (data->refCount-- <= 1) { Index: generic/tclCmdAH.c ================================================================== --- generic/tclCmdAH.c +++ generic/tclCmdAH.c @@ -2,18 +2,20 @@ * tclCmdAH.c -- * * This file contains the top-level command routines for most of the Tcl * built-in commands whose names begin with the letters A to H. * - * Copyright (c) 1987-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1987-1993 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" +#include "tclIO.h" +#include "tclTomMath.h" #ifdef _WIN32 # include "tclWinInt.h" #endif /* @@ -22,18 +24,18 @@ * freed in a single step. */ struct ForeachState { Tcl_Obj *bodyPtr; /* The script body of the command. */ - int bodyIdx; /* The argument index of the body. */ - int j, maxj; /* Number of loop iterations. */ - int numLists; /* Count of value lists. */ - int *index; /* Array of value list indices. */ - int *varcList; /* # loop variables per list. */ + Tcl_Size bodyIdx; /* The argument index of the body. */ + Tcl_Size j, maxj; /* Number of loop iterations. */ + Tcl_Size numLists; /* Count of value lists. */ + Tcl_Size *index; /* Array of value list indices. */ + Tcl_Size *varcList; /* # loop variables per list. */ Tcl_Obj ***varvList; /* Array of var name lists. */ Tcl_Obj **vCopyList; /* Copies of var name list arguments. */ - int *argcList; /* Array of value list sizes. */ + Tcl_Size *argcList; /* Array of value list sizes. */ Tcl_Obj ***argvList; /* Array of value lists. */ Tcl_Obj **aCopyList; /* Copies of value list arguments. */ Tcl_Obj *resultList; /* List of result values from the loop body, * or NULL if we're not collecting them * ([lmap] vs [foreach]). */ @@ -47,10 +49,11 @@ 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); @@ -117,11 +120,11 @@ *---------------------------------------------------------------------- */ int Tcl_BreakObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 1) { @@ -148,21 +151,21 @@ *---------------------------------------------------------------------- */ int Tcl_CatchObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRCatchObjCmd, clientData, objc, objv); } int TclNRCatchObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *varNamePtr = NULL; @@ -192,11 +195,11 @@ return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1); } static int CatchObjCmdCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int objc = PTR2INT(data[0]); @@ -253,11 +256,11 @@ *---------------------------------------------------------------------- */ int Tcl_CdObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *dir; @@ -269,11 +272,14 @@ } if (objc == 2) { dir = objv[1]; } else { - TclNewLiteralStringObj(dir, "~"); + dir = TclGetHomeDirObj(interp, NULL); + if (dir == NULL) { + return TCL_ERROR; + } Tcl_IncrRefCount(dir); } if (Tcl_FSConvertToPathType(interp, dir) != TCL_OK) { result = TCL_ERROR; } else { @@ -308,11 +314,11 @@ *---------------------------------------------------------------------- */ int Tcl_ConcatObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc >= 2) { @@ -342,11 +348,11 @@ *---------------------------------------------------------------------- */ int Tcl_ContinueObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 1) { @@ -375,21 +381,128 @@ Tcl_Command TclInitEncodingCmd( Tcl_Interp* interp) /* Tcl interpreter */ { static const EnsembleImplMap encodingImplMap[] = { - {"convertfrom", EncodingConvertfromObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, - {"convertto", EncodingConverttoObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, + {"convertfrom", EncodingConvertfromObjCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, + {"convertto", EncodingConverttoObjCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"dirs", EncodingDirsObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 1}, {"names", EncodingNamesObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, + {"profiles", EncodingProfilesObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"system", EncodingSystemObjCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 1}, {NULL, NULL, NULL, NULL, NULL, 0} }; return TclMakeEnsemble(interp, "encoding", encodingImplMap); } +/* + *------------------------------------------------------------------------ + * + * EncodingConvertParseOptions -- + * + * Common routine for parsing arguments passed to encoding convertfrom + * and encoding convertto. + * + * Results: + * TCL_OK or TCL_ERROR. + * + * Side effects: + * On success, + * - *encPtr is set to the encoding. Must be freed with Tcl_FreeEncoding + * if non-NULL + * - *dataObjPtr is set to the Tcl_Obj containing the data to encode or + * decode + * - *profilePtr is set to encoding error handling profile + * - *failVarPtr is set to -failindex option value or NULL + * On error, all of the above are uninitialized. + * + *------------------------------------------------------------------------ + */ +static int +EncodingConvertParseOptions ( + Tcl_Interp *interp, /* For error messages. May be NULL */ + int objc, /* Number of arguments */ + Tcl_Obj *const objv[], /* Argument objects as passed to command. */ + Tcl_Encoding *encPtr, /* Where to store the encoding */ + Tcl_Obj **dataObjPtr, /* Where to store ptr to Tcl_Obj containing data */ + int *profilePtr, /* Bit mask of encoding option profile */ + Tcl_Obj **failVarPtr /* Where to store -failindex option value */ +) +{ + static const char *const options[] = {"-profile", "-failindex", NULL}; + enum convertfromOptions { PROFILE, FAILINDEX } optIndex; + Tcl_Encoding encoding; + Tcl_Obj *dataObj; + Tcl_Obj *failVarObj; + int profile = TCL_ENCODING_PROFILE_TCL8; + + /* + * 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 -- * @@ -402,50 +515,88 @@ *---------------------------------------------------------------------- */ int EncodingConvertfromObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *data; /* Byte array to convert */ Tcl_DString ds; /* Buffer to hold the string */ Tcl_Encoding encoding; /* Encoding to use */ - size_t length = 0; /* Length of the byte array being converted */ + Tcl_Size length = 0; /* Length of the byte array being converted */ const char *bytesPtr; /* Pointer to the first byte of the array */ + int flags; + int result; + Tcl_Obj *failVarObj; + Tcl_Size errorLocation; - if (objc == 2) { - encoding = Tcl_GetEncoding(interp, NULL); - data = objv[1]; - } else if (objc == 3) { - if (Tcl_GetEncodingFromObj(interp, objv[1], &encoding) != TCL_OK) { + 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; } - data = objv[2]; - } else { - Tcl_WrongNumArgs(interp, 1, objv, "?encoding? data"); - return TCL_ERROR; + break; } /* - * Convert the string into a byte array in 'ds' + * TCL_OK or a TCL_CONVERT_* error where the caller wants back as much + * data as was converted. */ - bytesPtr = (char *) TclGetByteArrayFromObj(data, &length); - Tcl_ExternalToUtfDString(encoding, bytesPtr, length, &ds); - + if (failVarObj) { + Tcl_Obj *failIndex; + TclNewIndexObj(failIndex, errorLocation); + if (Tcl_ObjSetVar2(interp, + failVarObj, + NULL, + failIndex, + TCL_LEAVE_ERR_MSG) == NULL) { + Tcl_DStringFree(&ds); + return TCL_ERROR; + } + } /* * Note that we cannot use Tcl_DStringResult here because it will * truncate the string at the first null byte. */ - Tcl_SetObjResult(interp, TclDStringToObj(&ds)); + Tcl_SetObjResult(interp, Tcl_DStringToObj(&ds)); - /* - * We're done with the encoding - */ + /* We're done with the encoding */ Tcl_FreeEncoding(encoding); return TCL_OK; } @@ -464,50 +615,84 @@ *---------------------------------------------------------------------- */ int EncodingConverttoObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *data; /* String to convert */ Tcl_DString ds; /* Buffer to hold the byte array */ Tcl_Encoding encoding; /* Encoding to use */ - size_t length; /* Length of the string being converted */ + Tcl_Size length; /* Length of the string being converted */ const char *stringPtr; /* Pointer to the first byte of the string */ - - /* 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"); + 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); - Tcl_UtfToExternalDString(encoding, stringPtr, length, &ds); + stringPtr = Tcl_GetStringFromObj(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 - */ + /* We're done with the encoding */ Tcl_FreeEncoding(encoding); return TCL_OK; } @@ -528,11 +713,11 @@ *---------------------------------------------------------------------- */ int EncodingDirsObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *dirListObj; @@ -550,11 +735,11 @@ 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); + (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, dirListObj); return TCL_OK; } @@ -572,11 +757,11 @@ *----------------------------------------------------------------------------- */ int EncodingNamesObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp* interp, /* Tcl interpreter */ int objc, /* Number of command line args */ Tcl_Obj* const objv[]) /* Vector of command line args */ { if (objc > 1) { @@ -584,10 +769,38 @@ 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 -- @@ -603,11 +816,11 @@ *----------------------------------------------------------------------------- */ int EncodingSystemObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp* interp, /* Tcl interpreter */ int objc, /* Number of command line args */ Tcl_Obj* const objv[]) /* Vector of command line args */ { if (objc > 2) { @@ -640,11 +853,11 @@ *---------------------------------------------------------------------- */ int Tcl_ErrorObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *options, *optName; @@ -689,11 +902,11 @@ *---------------------------------------------------------------------- */ static int EvalCmdErrMsg( - TCL_UNUSED(ClientData *), + TCL_UNUSED(void **), Tcl_Interp *interp, int result) { if (result == TCL_ERROR) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( @@ -702,21 +915,21 @@ return result; } int Tcl_EvalObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNREvalObjCmd, clientData, objc, objv); } int TclNREvalObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *objPtr; @@ -771,11 +984,11 @@ *---------------------------------------------------------------------- */ int Tcl_ExitObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_WideInt value; @@ -818,21 +1031,21 @@ *---------------------------------------------------------------------- */ int Tcl_ExprObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRExprObjCmd, clientData, objc, objv); } int TclNRExprObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *resultPtr, *objPtr; @@ -855,11 +1068,11 @@ return Tcl_NRExprObj(interp, objPtr, resultPtr); } static int ExprCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Obj *resultPtr = (Tcl_Obj *)data[0]; Tcl_Obj *objPtr = (Tcl_Obj *)data[1]; @@ -914,10 +1127,11 @@ {"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}, @@ -937,10 +1151,11 @@ {"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} }; @@ -964,11 +1179,11 @@ *---------------------------------------------------------------------- */ static int FileAttrAccessTimeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; @@ -982,14 +1197,14 @@ return TCL_ERROR; } #if defined(_WIN32) /* We use a value of 0 to indicate the access time not available */ if (Tcl_GetAccessTimeFromStat(&buf) == 0) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "could not get access time for file \"%s\"", - TclGetString(objv[1]))); - return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "could not get access time for file \"%s\"", + TclGetString(objv[1]))); + return TCL_ERROR; } #endif if (objc == 3) { /* @@ -1046,11 +1261,11 @@ *---------------------------------------------------------------------- */ static int FileAttrModifyTimeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; @@ -1064,14 +1279,14 @@ return TCL_ERROR; } #if defined(_WIN32) /* We use a value of 0 to indicate the modification time not available */ if (Tcl_GetModificationTimeFromStat(&buf) == 0) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "could not get modification time for file \"%s\"", - TclGetString(objv[1]))); - return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "could not get modification time for file \"%s\"", + TclGetString(objv[1]))); + return TCL_ERROR; } #endif if (objc == 3) { /* * Need separate variable for reading longs from an object on 64-bit @@ -1125,25 +1340,29 @@ *---------------------------------------------------------------------- */ static int FileAttrLinkStatCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "name varName"); + if (objc < 2 || objc > 3) { + Tcl_WrongNumArgs(interp, 1, objv, "name ?varName?"); return TCL_ERROR; } if (GetStatBuf(interp, objv[1], Tcl_FSLstat, &buf) != TCL_OK) { return TCL_ERROR; } - return StoreStatData(interp, objv[2], &buf); + if (objc == 2) { + return StoreStatData(interp, NULL, &buf); + } else { + return StoreStatData(interp, objv[2], &buf); + } } /* *---------------------------------------------------------------------- * @@ -1161,25 +1380,29 @@ *---------------------------------------------------------------------- */ static int FileAttrStatCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "name varName"); + if (objc < 2 || objc > 3) { + Tcl_WrongNumArgs(interp, 1, objv, "name ?varName?"); return TCL_ERROR; } if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) { return TCL_ERROR; } - return StoreStatData(interp, objv[2], &buf); + if (objc == 2) { + return StoreStatData(interp, NULL, &buf); + } else { + return StoreStatData(interp, objv[2], &buf); + } } /* *---------------------------------------------------------------------- * @@ -1197,11 +1420,11 @@ *---------------------------------------------------------------------- */ static int FileAttrTypeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; @@ -1235,11 +1458,11 @@ *---------------------------------------------------------------------- */ static int FileAttrSizeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; @@ -1272,11 +1495,11 @@ *---------------------------------------------------------------------- */ static int FileAttrIsDirectoryCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; @@ -1310,11 +1533,11 @@ *---------------------------------------------------------------------- */ static int FileAttrIsExecutableCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 2) { @@ -1341,11 +1564,11 @@ *---------------------------------------------------------------------- */ static int FileAttrIsExistingCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 2) { @@ -1372,11 +1595,11 @@ *---------------------------------------------------------------------- */ static int FileAttrIsFileCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; @@ -1410,11 +1633,11 @@ *---------------------------------------------------------------------- */ static int FileAttrIsOwnedCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { #ifdef __CYGWIN__ @@ -1427,10 +1650,25 @@ 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(Tcl_GetString(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); @@ -1457,11 +1695,11 @@ *---------------------------------------------------------------------- */ static int FileAttrIsReadableCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 2) { @@ -1488,11 +1726,11 @@ *---------------------------------------------------------------------- */ static int FileAttrIsWritableCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 2) { @@ -1519,11 +1757,11 @@ *---------------------------------------------------------------------- */ static int PathDirNameCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *dirPtr; @@ -1558,11 +1796,11 @@ *---------------------------------------------------------------------- */ static int PathExtensionCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *dirPtr; @@ -1597,11 +1835,11 @@ *---------------------------------------------------------------------- */ static int PathRootNameCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *dirPtr; @@ -1636,11 +1874,11 @@ *---------------------------------------------------------------------- */ static int PathTailCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *dirPtr; @@ -1675,11 +1913,11 @@ *---------------------------------------------------------------------- */ static int PathFilesystemCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *fsInfo; @@ -1690,11 +1928,11 @@ } fsInfo = Tcl_FSFileSystemInfo(objv[1]); if (fsInfo == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("unrecognised path", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "FILESYSTEM", - TclGetString(objv[1]), NULL); + TclGetString(objv[1]), (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, fsInfo); return TCL_OK; } @@ -1716,11 +1954,11 @@ *---------------------------------------------------------------------- */ static int PathJoinCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc < 2) { @@ -1748,11 +1986,11 @@ *---------------------------------------------------------------------- */ static int PathNativeNameCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_DString ds; @@ -1762,11 +2000,11 @@ return TCL_ERROR; } if (Tcl_TranslateFileName(interp, TclGetString(objv[1]), &ds) == NULL) { return TCL_ERROR; } - Tcl_SetObjResult(interp, TclDStringToObj(&ds)); + Tcl_SetObjResult(interp, Tcl_DStringToObj(&ds)); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -1785,11 +2023,11 @@ *---------------------------------------------------------------------- */ static int PathNormalizeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *fileName; @@ -1823,11 +2061,11 @@ *---------------------------------------------------------------------- */ static int PathSplitCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *res; @@ -1840,11 +2078,11 @@ 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); + (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, res); return TCL_OK; } @@ -1866,11 +2104,11 @@ *---------------------------------------------------------------------- */ static int PathTypeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *typeName; @@ -1914,11 +2152,11 @@ *---------------------------------------------------------------------- */ static int FilesystemSeparatorCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc < 1 || objc > 2) { @@ -1942,11 +2180,11 @@ if (separatorObj == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unrecognised path", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "FILESYSTEM", - TclGetString(objv[1]), NULL); + TclGetString(objv[1]), (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, separatorObj); } return TCL_OK; @@ -1969,11 +2207,11 @@ *---------------------------------------------------------------------- */ static int FilesystemVolumesCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 1) { @@ -2075,11 +2313,11 @@ * * StoreStatData -- * * This is a utility procedure that breaks out the fields of a "stat" * structure and stores them in textual form into the elements of an - * associative array. + * associative array (if given) or returns a dictionary. * * Results: * Returns a standard Tcl return value. If an error occurs then a message * is left in interp's result. * @@ -2095,16 +2333,45 @@ Tcl_Obj *varName, /* Name of associative array variable in which * to store stat results. */ Tcl_StatBuf *statPtr) /* Pointer to buffer containing stat data to * store in varName. */ { - Tcl_Obj *field, *value; + Tcl_Obj *field, *value, *result; unsigned short mode; + + 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; + } /* - * 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. */ @@ -2122,23 +2389,29 @@ * Watch out porters; the inode is meant to be an *unsigned* value, so the * cast might fail when there isn't a real arithmetic 'long long' type... */ STORE_ARY("dev", Tcl_NewWideIntObj((long)statPtr->st_dev)); - STORE_ARY("ino", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino)); + STORE_ARY("ino", Tcl_NewWideIntObj(statPtr->st_ino)); STORE_ARY("nlink", Tcl_NewWideIntObj((long)statPtr->st_nlink)); STORE_ARY("uid", Tcl_NewWideIntObj((long)statPtr->st_uid)); STORE_ARY("gid", Tcl_NewWideIntObj((long)statPtr->st_gid)); - STORE_ARY("size", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size)); + STORE_ARY("size", Tcl_NewWideIntObj(statPtr->st_size)); #ifdef HAVE_STRUCT_STAT_ST_BLOCKS - STORE_ARY("blocks", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks)); + STORE_ARY("blocks", Tcl_NewWideIntObj(statPtr->st_blocks)); #endif #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE STORE_ARY("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize)); +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + if (S_ISCHR(statPtr->st_mode) || S_ISBLK(statPtr->st_mode)) { + STORE_ARY("rdev", Tcl_NewWideIntObj((long) statPtr->st_rdev)); + } #endif STORE_ARY("atime", Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(statPtr))); - STORE_ARY("mtime", Tcl_NewWideIntObj(Tcl_GetModificationTimeFromStat(statPtr))); + STORE_ARY("mtime", Tcl_NewWideIntObj( + Tcl_GetModificationTimeFromStat(statPtr))); STORE_ARY("ctime", Tcl_NewWideIntObj(Tcl_GetChangeTimeFromStat(statPtr))); mode = (unsigned short) statPtr->st_mode; STORE_ARY("mode", Tcl_NewWideIntObj(mode)); STORE_ARY("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1)); #undef STORE_ARY @@ -2229,21 +2502,21 @@ *---------------------------------------------------------------------- */ int Tcl_ForObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRForObjCmd, clientData, objc, objv); } int TclNRForObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -2270,11 +2543,11 @@ return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1); } static int ForSetupCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { ForIterData *iterPtr = (ForIterData *)data[0]; @@ -2289,11 +2562,11 @@ return TCL_OK; } int TclNRForIterCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { ForIterData *iterPtr = (ForIterData *)data[0]; Tcl_Obj *boolObj; @@ -2324,11 +2597,11 @@ return result; } static int ForCondCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; ForIterData *iterPtr = (ForIterData *)data[0]; @@ -2362,11 +2635,11 @@ return result; } static int ForNextCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; ForIterData *iterPtr = (ForIterData *)data[0]; @@ -2387,11 +2660,11 @@ return result; } static int ForPostNextCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { ForIterData *iterPtr = (ForIterData *)data[0]; @@ -2423,41 +2696,41 @@ *---------------------------------------------------------------------- */ int Tcl_ForeachObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRForeachCmd, clientData, objc, objv); } int TclNRForeachCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { return EachloopCmd(interp, TCL_EACH_KEEP_NONE, objc, objv); } int Tcl_LmapObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRLmapCmd, clientData, objc, objv); } int TclNRLmapCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { return EachloopCmd(interp, TCL_EACH_COLLECT, objc, objv); @@ -2472,11 +2745,12 @@ int objc, /* The arguments being passed in... */ Tcl_Obj *const objv[]) { int numLists = (objc-2) / 2; struct ForeachState *statePtr; - int i, j, result; + int i, result; + Tcl_Size j; if (objc < 4 || (objc%2 != 0)) { Tcl_WrongNumArgs(interp, 1, objv, "varList list ?varList list ...? command"); return TCL_ERROR; @@ -2496,20 +2770,20 @@ * the rest of this code to be simple and for us to use a single memory * allocation for better performance. */ statePtr = (struct ForeachState *)TclStackAlloc(interp, - sizeof(struct ForeachState) + 3 * numLists * sizeof(int) + sizeof(struct ForeachState) + 3 * numLists * sizeof(Tcl_Size) + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *))); memset(statePtr, 0, - sizeof(struct ForeachState) + 3 * numLists * sizeof(int) + sizeof(struct ForeachState) + 3 * numLists * sizeof(Tcl_Size) + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *))); statePtr->varvList = (Tcl_Obj ***) (statePtr + 1); statePtr->argvList = statePtr->varvList + numLists; statePtr->vCopyList = (Tcl_Obj **) (statePtr->argvList + numLists); statePtr->aCopyList = statePtr->vCopyList + numLists; - statePtr->index = (int *) (statePtr->aCopyList + numLists); + statePtr->index = (Tcl_Size *) (statePtr->aCopyList + numLists); statePtr->varcList = statePtr->index + numLists; statePtr->argcList = statePtr->varcList + numLists; statePtr->numLists = numLists; statePtr->bodyPtr = objv[objc - 1]; @@ -2524,36 +2798,60 @@ /* * Break up the value lists and variable lists into elements. */ for (i=0 ; ivCopyList[i] = TclListObjCopy(interp, objv[1+i*2]); if (statePtr->vCopyList[i] == NULL) { result = TCL_ERROR; goto done; } - TclListObjGetElements(NULL, statePtr->vCopyList[i], - &statePtr->varcList[i], &statePtr->varvList[i]); + result = TclListObjLengthM(interp, statePtr->vCopyList[i], + &statePtr->varcList[i]); + if (result != TCL_OK) { + result = TCL_ERROR; + goto done; + } if (statePtr->varcList[i] < 1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "%s varlist is empty", - (statePtr->resultList != NULL ? "lmap" : "foreach"))); + "%s varlist is empty", + (statePtr->resultList != NULL ? "lmap" : "foreach"))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", - (statePtr->resultList != NULL ? "LMAP" : "FOREACH"), - "NEEDVARS", NULL); + (statePtr->resultList != NULL ? "LMAP" : "FOREACH"), + "NEEDVARS", (void *)NULL); result = TCL_ERROR; goto done; } + TclListObjGetElementsM(NULL, statePtr->vCopyList[i], + &statePtr->varcList[i], &statePtr->varvList[i]); - statePtr->aCopyList[i] = TclListObjCopy(interp, objv[2+i*2]); - if (statePtr->aCopyList[i] == NULL) { - result = TCL_ERROR; - goto done; - } - TclListObjGetElements(NULL, statePtr->aCopyList[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 = TclListObjGetElementsM(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) { @@ -2592,11 +2890,11 @@ * Post-body processing handler. */ static int ForeachLoopStep( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { struct ForeachState *statePtr = (struct ForeachState *)data[0]; @@ -2609,12 +2907,16 @@ case TCL_CONTINUE: result = TCL_OK; break; case TCL_OK: if (statePtr->resultList != NULL) { - Tcl_ListObjAppendElement(interp, statePtr->resultList, - Tcl_GetObjResult(interp)); + result = Tcl_ListObjAppendElement( + interp, statePtr->resultList, Tcl_GetObjResult(interp)); + if (result != TCL_OK) { + /* e.g. memory alloc failure on big data tests */ + goto done; + } } break; case TCL_BREAK: result = TCL_OK; goto finish; @@ -2667,19 +2969,32 @@ static inline int ForeachAssignments( Tcl_Interp *interp, struct ForeachState *statePtr) { - int i, v, k; + int i; + Tcl_Size v, k; Tcl_Obj *valuePtr, *varValuePtr; for (i=0 ; inumLists ; i++) { + int isAbstractList = + TclObjTypeHasProc(statePtr->aCopyList[i],indexProc) != NULL; + for (v=0 ; vvarcList[i] ; v++) { k = statePtr->index[i]++; - if (k < statePtr->argcList[i]) { - valuePtr = statePtr->argvList[i][k]; + 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], @@ -2740,11 +3055,11 @@ *---------------------------------------------------------------------- */ int Tcl_FormatObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *resultPtr; /* Where result is stored finally. */ Index: generic/tclCmdIL.c ================================================================== --- generic/tclCmdIL.c +++ generic/tclCmdIL.c @@ -4,23 +4,26 @@ * This file contains the top-level command routines for most of the Tcl * built-in commands whose names begin with the letters I through L. It * contains only commands in the generic core (i.e., those that don't * depend much upon UNIX facilities). * - * Copyright (c) 1987-1993 The Regents of the University of California. - * Copyright (c) 1993-1997 Lucent Technologies. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. - * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. - * Copyright (c) 2005 Donal K. Fellows. + * Copyright © 1987-1993 The Regents of the University of California. + * Copyright © 1993-1997 Lucent Technologies. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. + * Copyright © 2001 Kevin B. Kenny. All rights reserved. + * Copyright © 2005 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclRegexp.h" +#include "tclTomMath.h" +#include +#include /* * 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. @@ -45,11 +48,11 @@ * These function pointer types are used with the "lsearch" and "lsort" * commands to facilitate the "-nocase" option. */ typedef int (*SortStrCmpFn_t) (const char *, const char *); -typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t); +typedef int (*SortMemCmpFn_t) (const void *, const void *, Tcl_Size); /* * The "lsort" command needs to pass certain information down to the function * that compares two list elements, and the comparison function needs to pass * success or failure information back up to the top-level "lsort" command. @@ -59,20 +62,20 @@ typedef struct { int isIncreasing; /* Nonzero means sort in increasing order. */ int sortMode; /* The sort mode. One of SORTMODE_* values * defined below. */ Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode is - * SORTMODE_COMMAND. Pre-initialized to hold + * SORTMODE_COMMAND. Preinitialized to hold * base of command. */ int *indexv; /* If the -index option was specified, this * holds an encoding of the indexes contained * in the list supplied as an argument to * that option. * NULL if no indexes supplied, and points to * singleIndex field when only one * supplied. */ - int indexc; /* Number of indexes in indexv array. */ + Tcl_Size indexc; /* Number of indexes in indexv array. */ int singleIndex; /* Static space for common index case. */ int unique; int numElements; Tcl_Interp *interp; /* The interpreter in which the sort is being * done. */ @@ -91,10 +94,27 @@ #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); @@ -183,21 +203,21 @@ *---------------------------------------------------------------------- */ int Tcl_IfObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRIfObjCmd, clientData, objc, objv); } int TclNRIfObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *boolObj; @@ -204,11 +224,11 @@ if (objc <= 1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: no expression after \"%s\" argument", TclGetString(objv[0]))); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (void *)NULL); return TCL_ERROR; } /* * At this point, objv[1] refers to the main expression to test. The @@ -216,17 +236,17 @@ * to execute if the expression is true. */ TclNewObj(boolObj); Tcl_NRAddCallback(interp, IfConditionCallback, INT2PTR(objc), - (ClientData) objv, INT2PTR(1), boolObj); + (void *) objv, INT2PTR(1), boolObj); return Tcl_NRExprObj(interp, objv[1], boolObj); } static int IfConditionCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int objc = PTR2INT(data[0]); @@ -295,11 +315,11 @@ if (i >= objc) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: no expression after \"%s\" argument", clause)); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (void *)NULL); return TCL_ERROR; } if (!thenScriptIndex) { TclNewObj(boolObj); Tcl_NRAddCallback(interp, IfConditionCallback, data[0], data[1], @@ -322,11 +342,11 @@ } if (i < objc - 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "wrong # args: extra words after \"else\" clause in \"if\" command", -1)); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (void *)NULL); return TCL_ERROR; } if (thenScriptIndex) { /* * TIP #280. Make invoking context available to branch/else. @@ -339,11 +359,11 @@ missingScript: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: no script following \"%s\" argument", TclGetString(objv[i-1]))); - Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -366,11 +386,11 @@ *---------------------------------------------------------------------- */ int Tcl_IncrObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *newValuePtr, *incrPtr; @@ -447,11 +467,11 @@ *---------------------------------------------------------------------- */ static int InfoArgsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -468,11 +488,11 @@ name = TclGetString(objv[1]); procPtr = TclFindProc(iPtr, name); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't a procedure", name)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, (void *)NULL); return TCL_ERROR; } /* * Build a return list containing the arguments. @@ -510,19 +530,19 @@ *---------------------------------------------------------------------- */ static int InfoBodyCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; const char *name, *bytes; Proc *procPtr; - size_t numBytes; + Tcl_Size numBytes; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "procname"); return TCL_ERROR; } @@ -530,11 +550,11 @@ name = TclGetString(objv[1]); procPtr = TclFindProc(iPtr, name); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't a procedure", name)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, (void *)NULL); return TCL_ERROR; } /* * Here we used to return procPtr->bodyPtr, except when the body was @@ -543,11 +563,11 @@ * compiler/engine subsystem, we now always return a copy of the string * rep. It is important to return a copy so that later manipulations of * the object do not invalidate the internal rep. */ - bytes = TclGetStringFromObj(procPtr->bodyPtr, &numBytes); + bytes = Tcl_GetStringFromObj(procPtr->bodyPtr, &numBytes); Tcl_SetObjResult(interp, Tcl_NewStringObj(bytes, numBytes)); return TCL_OK; } /* @@ -571,11 +591,11 @@ *---------------------------------------------------------------------- */ static int InfoCmdCountCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -613,11 +633,11 @@ *---------------------------------------------------------------------- */ static int InfoCommandsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *cmdName, *pattern; @@ -628,11 +648,11 @@ Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp); Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); Tcl_Obj *listPtr, *elemObjPtr; int specificNsInPattern = 0;/* Init. to avoid compiler warning. */ Tcl_Command cmd; - size_t i; + Tcl_Size i; /* * Get the pattern and find the "effective namespace" in which to list * commands. */ @@ -689,11 +709,11 @@ entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern); if (entryPtr != NULL) { if (specificNsInPattern) { cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr); - elemObjPtr = Tcl_NewObj(); + TclNewObj(elemObjPtr); Tcl_GetCommandFullName(interp, cmd, elemObjPtr); } else { cmdName = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr); elemObjPtr = Tcl_NewStringObj(cmdName, -1); } @@ -740,11 +760,11 @@ cmdName = (const char *)Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr); if ((simplePattern == NULL) || Tcl_StringMatch(cmdName, simplePattern)) { if (specificNsInPattern) { cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr); - elemObjPtr = Tcl_NewObj(); + TclNewObj(elemObjPtr); Tcl_GetCommandFullName(interp, cmd, elemObjPtr); } else { elemObjPtr = Tcl_NewStringObj(cmdName, -1); } Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); @@ -890,11 +910,11 @@ *---------------------------------------------------------------------- */ static int InfoCompleteCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 2) { @@ -927,11 +947,11 @@ *---------------------------------------------------------------------- */ static int InfoDefaultCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -951,11 +971,11 @@ 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); + (void *)NULL); return TCL_ERROR; } for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; localPtr = localPtr->nextPtr) { @@ -967,11 +987,12 @@ if (valueObjPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1)); } else { - Tcl_Obj *nullObjPtr = Tcl_NewObj(); + Tcl_Obj *nullObjPtr; + TclNewObj(nullObjPtr); valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL, nullObjPtr, TCL_LEAVE_ERR_MSG); if (valueObjPtr == NULL) { return TCL_ERROR; @@ -983,11 +1004,11 @@ } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "procedure \"%s\" doesn't have an argument \"%s\"", procName, argName)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARGUMENT", argName, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARGUMENT", argName, (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -1009,11 +1030,11 @@ *---------------------------------------------------------------------- */ static int InfoErrorStackCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Interp *target; @@ -1058,11 +1079,11 @@ *---------------------------------------------------------------------- */ int TclInfoExistsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *varName; @@ -1103,11 +1124,11 @@ *---------------------------------------------------------------------- */ static int InfoFrameCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -1166,11 +1187,11 @@ if ((level > topLevel) || (level <= - topLevel)) { levelError: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad level \"%s\"", TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", - TclGetString(objv[1]), NULL); + TclGetString(objv[1]), (void *)NULL); code = TCL_ERROR; goto done; } /* @@ -1238,11 +1259,11 @@ Tcl_Interp *interp, /* Current interpreter. */ CmdFrame *framePtr) /* Frame to get info for. */ { Interp *iPtr = (Interp *) interp; Tcl_Obj *tmpObj; - Tcl_Obj *lv[20]; /* Keep uptodate when more keys are added to + Tcl_Obj *lv[20] = {NULL}; /* Keep uptodate when more keys are added to * the dict. */ int lc = 0; /* * This array is indexed by the TCL_LOCATION_... values, except * for _LAST. @@ -1373,11 +1394,11 @@ Tcl_GetCommandFullName(interp, (Tcl_Command) procPtr->cmdPtr, procNameObj); ADD_PAIR("proc", procNameObj); } else if (procPtr->cmdPtr->clientData) { ExtraFrameInfo *efiPtr = (ExtraFrameInfo *)procPtr->cmdPtr->clientData; - size_t i; + Tcl_Size i; /* * This is a non-standard command. Luckily, it's told us how to * render extra information about its frame. */ @@ -1443,11 +1464,11 @@ *---------------------------------------------------------------------- */ static int InfoFunctionsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *script; @@ -1508,11 +1529,11 @@ *---------------------------------------------------------------------- */ static int InfoHostnameCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *name; @@ -1528,11 +1549,11 @@ return TCL_OK; } Tcl_SetObjResult(interp, Tcl_NewStringObj( "unable to determine name of host", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "HOSTNAME", "UNKNOWN", NULL); + Tcl_SetErrorCode(interp, "TCL", "OPERATION", "HOSTNAME", "UNKNOWN", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -1554,19 +1575,19 @@ *---------------------------------------------------------------------- */ static int InfoLevelCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; if (objc == 1) { /* Just "info level" */ - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iPtr->varFramePtr->level)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj((int)iPtr->varFramePtr->level)); return TCL_OK; } if (objc == 2) { int level; @@ -1581,11 +1602,11 @@ } level += iPtr->varFramePtr->level; } for (framePtr=iPtr->varFramePtr ; framePtr!=rootFramePtr; framePtr=framePtr->callerVarPtr) { - if (framePtr->level == level) { + if ((int)framePtr->level == level) { break; } } if (framePtr == rootFramePtr) { goto levelError; @@ -1601,11 +1622,11 @@ levelError: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad level \"%s\"", TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", - TclGetString(objv[1]), NULL); + TclGetString(objv[1]), (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -1628,11 +1649,11 @@ *---------------------------------------------------------------------- */ static int InfoLibraryCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *libDirName; @@ -1648,11 +1669,11 @@ return TCL_OK; } Tcl_SetObjResult(interp, Tcl_NewStringObj( "no library has been specified for Tcl", -1)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", "tcl_library",NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", "tcl_library", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -1675,11 +1696,11 @@ *---------------------------------------------------------------------- */ static int InfoLoadedCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *interpName, *packageName; @@ -1697,11 +1718,11 @@ 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); + return TclGetLoadedLibraries(interp, interpName, packageName); } /* *---------------------------------------------------------------------- * @@ -1723,11 +1744,11 @@ *---------------------------------------------------------------------- */ static int InfoNameOfExecutableCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 1) { @@ -1759,11 +1780,11 @@ *---------------------------------------------------------------------- */ static int InfoPatchLevelCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *patchlevel; @@ -1806,11 +1827,11 @@ *---------------------------------------------------------------------- */ static int InfoProcsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *cmdName, *pattern; @@ -1883,11 +1904,11 @@ goto simpleProcOK; } } else { simpleProcOK: if (specificNsInPattern) { - elemObjPtr = Tcl_NewObj(); + TclNewObj(elemObjPtr); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, elemObjPtr); } else { elemObjPtr = Tcl_NewStringObj(simplePattern, -1); } @@ -1911,11 +1932,11 @@ goto procOK; } } else { procOK: if (specificNsInPattern) { - elemObjPtr = Tcl_NewObj(); + TclNewObj(elemObjPtr); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, elemObjPtr); } else { elemObjPtr = Tcl_NewStringObj(cmdName, -1); } @@ -1993,11 +2014,11 @@ *---------------------------------------------------------------------- */ static int InfoScriptCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -2041,11 +2062,11 @@ *---------------------------------------------------------------------- */ static int InfoSharedlibCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 1) { @@ -2079,11 +2100,11 @@ *---------------------------------------------------------------------- */ static int InfoTclVersionCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *version; @@ -2122,11 +2143,11 @@ *---------------------------------------------------------------------- */ static int InfoCmdTypeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Command command; @@ -2146,11 +2167,11 @@ * aliases as they're part of the security mechanisms. */ if (Tcl_IsSafe(interp) && (((Command *) command)->objProc == TclAliasObjCmd)) { - Tcl_AppendResult(interp, "native", NULL); + Tcl_AppendResult(interp, "native", (void *)NULL); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj(TclGetCommandTypeName(command), -1)); } return TCL_OK; @@ -2173,17 +2194,17 @@ *---------------------------------------------------------------------- */ int Tcl_JoinObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { - size_t length; - int listLen; + Tcl_Size length, listLen; + int isAbstractList = 0; Tcl_Obj *resObjPtr = NULL, *joinObjPtr, **elemPtrs; if ((objc < 2) || (objc > 3)) { Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?"); return TCL_ERROR; @@ -2192,11 +2213,19 @@ /* * 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, + 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 (TclListObjGetElementsM(interp, objv[1], &listLen, &elemPtrs) != TCL_OK) { return TCL_ERROR; } if (listLen == 0) { @@ -2203,24 +2232,33 @@ /* No elements to join; default empty result is correct. */ return TCL_OK; } if (listLen == 1) { /* One element; return it */ - Tcl_SetObjResult(interp, elemPtrs[0]); + 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); + (void) Tcl_GetStringFromObj(joinObjPtr, &length); if (length == 0) { resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0); } else { - int i; + Tcl_Size i; - resObjPtr = Tcl_NewObj(); + TclNewObj(resObjPtr); for (i = 0; i < listLen; i++) { if (i > 0) { /* * NOTE: This code is relying on Tcl_AppendObjToObj() **NOT** @@ -2259,65 +2297,103 @@ *---------------------------------------------------------------------- */ int Tcl_LassignObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tcl_Obj *listCopyPtr; - Tcl_Obj **listObjv; /* The contents of the list. */ - int listObjc; /* The length of the list. */ - int code = TCL_OK; + 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; } - listCopyPtr = TclListObjCopy(interp, objv[1]); - if (listCopyPtr == NULL) { + /* + * 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 (TclListObjLengthM(interp, listPtr, &listObjc) != TCL_OK) { return TCL_ERROR; } - - TclListObjGetElements(NULL, listCopyPtr, &listObjc, &listObjv); + origListObjc = listObjc; 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) { + 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 (code == TCL_OK && objc-- > 0) { + while (objc-- > 0) { if (Tcl_ObjSetVar2(interp, *objv++, NULL, emptyObj, TCL_LEAVE_ERR_MSG) == NULL) { - code = TCL_ERROR; + Tcl_DecrRefCount(emptyObj); + return TCL_ERROR; } } Tcl_DecrRefCount(emptyObj); } - if (code == TCL_OK && listObjc > 0) { - Tcl_SetObjResult(interp, Tcl_NewListObj(listObjc, listObjv)); - } - - Tcl_DecrRefCount(listCopyPtr); - return code; -} - + 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 -- * @@ -2333,11 +2409,11 @@ *---------------------------------------------------------------------- */ int Tcl_LindexObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *elemPtr; /* Pointer to the element being extracted. */ @@ -2391,25 +2467,25 @@ *---------------------------------------------------------------------- */ int Tcl_LinsertObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *listPtr; - size_t index; - int len, result; + Tcl_Size len, index; + int copied = 0, result; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "list index ?element ...?"); return TCL_ERROR; } - result = TclListObjLength(interp, objv[1], &len); + result = TclListObjLengthM(interp, objv[1], &len); if (result != TCL_OK) { return result; } /* @@ -2420,11 +2496,11 @@ result = TclGetIntForIndexM(interp, objv[2], /*end*/ len, &index); if (result != TCL_OK) { return result; } - if (index + 1 > (size_t)len + 1) { + if (index > len) { index = len; } /* * If the list object is unshared we can modify it directly. Otherwise we @@ -2432,21 +2508,31 @@ */ listPtr = objv[1]; if (Tcl_IsShared(listPtr)) { listPtr = TclListObjCopy(NULL, listPtr); + copied = 1; } - if ((objc == 4) && (index == (size_t)len)) { + if ((objc == 4) && (index == len)) { /* * Special case: insert one element at the end of the list. */ - Tcl_ListObjAppendElement(NULL, listPtr, objv[3]); + result = Tcl_ListObjAppendElement(NULL, listPtr, objv[3]); + if (result != TCL_OK) { + if (copied) { + Tcl_DecrRefCount(listPtr); + } + return result; + } } else { if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, index, 0, (objc-3), &(objv[3]))) { + if (copied) { + Tcl_DecrRefCount(listPtr); + } return TCL_ERROR; } } /* @@ -2474,11 +2560,11 @@ *---------------------------------------------------------------------- */ int Tcl_ListObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { @@ -2510,34 +2596,37 @@ *---------------------------------------------------------------------- */ int Tcl_LlengthObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int listLen, result; + 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); + result = TclListObjLengthM(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)); + TclNewUIntObj(objPtr, listLen); + Tcl_SetObjResult(interp, objPtr); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2556,19 +2645,20 @@ *---------------------------------------------------------------------- */ int Tcl_LpopObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int listLen, result; + Tcl_Size listLen; + int copied = 0, result; Tcl_Obj *elemPtr, *stored; - Tcl_Obj *listPtr, **elemPtrs; + Tcl_Obj *listPtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "listvar ?index?"); return TCL_ERROR; } @@ -2576,11 +2666,11 @@ listPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG); if (listPtr == NULL) { return TCL_ERROR; } - result = TclListObjGetElements(interp, listPtr, &listLen, &elemPtrs); + result = TclListObjLengthM(interp, listPtr, &listLen); if (result != TCL_OK) { return result; } /* @@ -2592,14 +2682,19 @@ 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); + "OUTOFRANGE", (void *)NULL); return TCL_ERROR; } - elemPtr = elemPtrs[listLen - 1]; + + result = Tcl_ListObjIndex(interp, listPtr, (listLen-1), &elemPtr); + if (result != TCL_OK) { + return result; + } + Tcl_IncrRefCount(elemPtr); } else { elemPtr = TclLindexFlat(interp, listPtr, objc-2, objv+2); if (elemPtr == NULL) { @@ -2615,26 +2710,39 @@ */ 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; } - Tcl_IncrRefCount(listPtr); } else { - listPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL); - - if (listPtr == NULL) { + Tcl_Obj *newListPtr; + Tcl_ObjTypeSetElement *proc = TclObjTypeHasProc(listPtr, setElementProc); + if (proc) { + newListPtr = proc(interp, listPtr, objc-2, objv+2, NULL); + } else { + newListPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL); + } + if (newListPtr == NULL) { + if (copied) { + Tcl_DecrRefCount(listPtr); + } return TCL_ERROR; + } else { + listPtr = newListPtr; + TclUndoRefCount(listPtr); } } stored = Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG); - Tcl_DecrRefCount(listPtr); if (stored == NULL) { return TCL_ERROR; } return TCL_OK; @@ -2657,25 +2765,24 @@ *---------------------------------------------------------------------- */ int Tcl_LrangeObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int listLen, result; - size_t first, last; - + int result; + Tcl_Size listLen, first, last; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "list first last"); return TCL_ERROR; } - result = TclListObjLength(interp, objv[1], &listLen); + result = TclListObjLengthM(interp, objv[1], &listLen); if (result != TCL_OK) { return result; } result = TclGetIntForIndexM(interp, objv[2], /*endValue*/ listLen - 1, @@ -2688,11 +2795,25 @@ &last); if (result != TCL_OK) { return result; } - Tcl_SetObjResult(interp, TclListObjRange(objv[1], first, last)); + 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; } /* *---------------------------------------------------------------------- @@ -2714,12 +2835,12 @@ static int LremoveIndexCompare( const void *el1Ptr, const void *el2Ptr) { - size_t idx1 = *((const size_t *) el1Ptr); - size_t idx2 = *((const size_t *) el2Ptr); + Tcl_Size idx1 = *((const Tcl_Size *) el1Ptr); + Tcl_Size idx2 = *((const Tcl_Size *) el2Ptr); /* * This will put the larger element first. */ @@ -2726,18 +2847,19 @@ return (idx1 < idx2) ? 1 : (idx1 > idx2) ? -1 : 0; } int Tcl_LremoveObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int i, idxc, listLen, prevIdx, first, num; - size_t *idxv; + Tcl_Size i, idxc, prevIdx, first, num; + Tcl_Size *idxv, listLen; Tcl_Obj *listObj; + int copied = 0, status = TCL_OK; /* * Parse the arguments. */ @@ -2745,48 +2867,49 @@ Tcl_WrongNumArgs(interp, 1, objv, "list ?index ...?"); return TCL_ERROR; } listObj = objv[1]; - if (TclListObjLength(interp, listObj, &listLen) != TCL_OK) { + if (TclListObjLengthM(interp, listObj, &listLen) != TCL_OK) { return TCL_ERROR; } idxc = objc - 2; if (idxc == 0) { Tcl_SetObjResult(interp, listObj); return TCL_OK; } - idxv = (size_t *)Tcl_Alloc((objc - 2) * sizeof(size_t)); + idxv = (Tcl_Size *)Tcl_Alloc((objc - 2) * sizeof(*idxv)); for (i = 2; i < objc; i++) { - if (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1, - &idxv[i - 2]) != TCL_OK) { - Tcl_Free(idxv); - return TCL_ERROR; + 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(size_t), LremoveIndexCompare); + qsort(idxv, idxc, sizeof(*idxv), LremoveIndexCompare); } /* * Make our working copy, then do the actual removes piecemeal. */ if (Tcl_IsShared(listObj)) { listObj = TclListObjCopy(NULL, listObj); + copied = 1; } num = 0; first = listLen; for (i = 0, prevIdx = -1 ; i < idxc ; i++) { - int idx = idxv[i]; + Tcl_Size idx = idxv[i]; /* * Repeated index and sanity check. */ @@ -2812,22 +2935,32 @@ /* * Note that this operation can't fail now; we know we have a list * and we're only ever contracting that list. */ - (void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL); + status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL); + if (status != TCL_OK) { + goto done; + } listLen -= num; num = 1; first = idx; } } if (num != 0) { - (void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL); + status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL); + if (status != TCL_OK) { + if (copied) { + Tcl_DecrRefCount(listObj); + } + goto done; + } } - Tcl_Free(idxv); Tcl_SetObjResult(interp, listObj); - return TCL_OK; +done: + Tcl_Free(idxv); + return status; } /* *---------------------------------------------------------------------- * @@ -2845,17 +2978,18 @@ *---------------------------------------------------------------------- */ int Tcl_LrepeatObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { - int elementCount, i, totalElems; + Tcl_WideInt elementCount, i; + Tcl_Size totalElems; Tcl_Obj *listPtr, **dataArray = NULL; /* * Check arguments for legality: * lrepeat count ?value ...? @@ -2863,18 +2997,18 @@ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "count ?value ...?"); return TCL_ERROR; } - if (TCL_OK != TclGetIntFromObj(interp, objv[1], &elementCount)) { + if (TCL_OK != TclGetWideIntFromObj(interp, objv[1], &elementCount)) { return TCL_ERROR; } if (elementCount < 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad count \"%d\": must be integer >= 0", elementCount)); + "bad count \"%" TCL_LL_MODIFIER "d\": must be integer >= 0", elementCount)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPEAT", "NEGARG", - NULL); + (void *)NULL); return TCL_ERROR; } /* * Skip forward to the interesting arguments now we've finished parsing. @@ -2885,12 +3019,12 @@ /* Final sanity check. Do not exceed limits on max list length. */ if (elementCount && objc > LIST_MAX/elementCount) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "max length of a Tcl list (%d elements) exceeded", LIST_MAX)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + "max length of a Tcl list (%" TCL_SIZE_MODIFIER "d elements) exceeded", LIST_MAX)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); return TCL_ERROR; } totalElems = objc * elementCount; /* @@ -2898,14 +3032,19 @@ * init value elementCount times. */ listPtr = Tcl_NewListObj(totalElems, NULL); if (totalElems) { - List *listRepPtr = ListRepPtr(listPtr); - - listRepPtr->elemCount = elementCount*objc; - dataArray = &listRepPtr->elements; + 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 @@ -2920,11 +3059,11 @@ tmpPtr->refCount += elementCount; for (i=0 ; i (size_t)listLen) { + } else if (first > listLen) { first = listLen; } - if (last + 1 > (size_t)listLen) { + if (last >= listLen) { last = listLen - 1; } - if (first + 1 <= last + 1) { - numToDelete = last - first + 1; + if (first <= last) { + numToDelete = (size_t)last - (size_t)first + 1; /* See [3d3124d01d] */ } else { numToDelete = 0; } /* @@ -3025,10 +3164,11 @@ * 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. @@ -3055,23 +3195,37 @@ *---------------------------------------------------------------------- */ int Tcl_LreverseObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument values. */ { Tcl_Obj **elemv; - int elemc, i, j; + Tcl_Size elemc, i, j; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "list"); return TCL_ERROR; } - if (TclListObjGetElements(interp, objv[1], &elemc, &elemv) != TCL_OK) { + + /* + * Handle AbstractList special case - do not shimmer into a list, if it + * supports a private Reverse function, just to reverse it. + */ + if (TclObjTypeHasProc(objv[1], reverseProc)) { + Tcl_Obj *resultObj; + + if (TclObjTypeReverse(interp, objv[1], &resultObj) == TCL_OK) { + Tcl_SetObjResult(interp, resultObj); + return TCL_OK; + } + } /* end Abstract List */ + + if (TclListObjLengthM(interp, objv[1], &elemc) != TCL_OK) { return TCL_ERROR; } /* * If the list is empty, just return it. [Bug 1876793] @@ -3079,20 +3233,30 @@ if (!elemc) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } + if (TclListObjGetElementsM(interp, objv[1], &elemc, &elemv) != TCL_OK) { + return TCL_ERROR; + } if (Tcl_IsShared(objv[1]) - || (ListRepPtr(objv[1])->refCount > 1)) { /* Bug 1675044 */ + || ListObjRepIsShared(objv[1])) { /* Bug 1675044 */ Tcl_Obj *resultObj, **dataArray; - List *listRepPtr; + ListRep listRep; resultObj = Tcl_NewListObj(elemc, NULL); - listRepPtr = ListRepPtr(resultObj); - listRepPtr->elemCount = elemc; - dataArray = &listRepPtr->elements; + + /* Modify the internal rep in-place */ + ListObjGetRep(resultObj, &listRep); + listRep.storePtr->numUsed = elemc; + dataArray = ListRepElementsBase(&listRep); + if (listRep.spanPtr) { + /* Future proofing */ + listRep.spanPtr->spanStart = listRep.storePtr->firstUsed; + listRep.spanPtr->spanLength = listRep.storePtr->numUsed; + } for (i=0,j=elemc-1 ; i objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing starting index", -1)); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (void *)NULL); result = TCL_ERROR; goto done; } i++; if (objv[i] == objv[objc - 2]) { @@ -3296,11 +3462,11 @@ case LSEARCH_STRIDE: /* -stride */ if (i > objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-stride\" option must be " "followed by stride length", -1)); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (void *)NULL); result = TCL_ERROR; goto done; } if (Tcl_GetWideIntFromObj(interp, objv[i+1], &wide) != TCL_OK) { result = TCL_ERROR; @@ -3308,30 +3474,30 @@ } if (wide < 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "stride length must be at least 1", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH", - "BADSTRIDE", NULL); + "BADSTRIDE", (void *)NULL); result = TCL_ERROR; goto done; } groupSize = wide; i++; break; case LSEARCH_INDEX: { /* -index */ Tcl_Obj **indices; - int j; + Tcl_Size j; if (allocatedIndexVector) { TclStackFree(interp, sortInfo.indexv); allocatedIndexVector = 0; } if (i > objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-index\" option must be followed by list index", -1)); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (void *)NULL); result = TCL_ERROR; goto done; } /* @@ -3339,11 +3505,11 @@ * extraction. Note that we don't do this using objects because * that has shimmering problems. */ i++; - if (TclListObjGetElements(interp, objv[i], + if (TclListObjGetElementsM(interp, objv[i], &sortInfo.indexc, &indices) != TCL_OK) { result = TCL_ERROR; goto done; } switch (sortInfo.indexc) { @@ -3375,16 +3541,16 @@ 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); + "OUTOFRANGE", (void *)NULL); result = TCL_ERROR; } if (result == TCL_ERROR) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( - "\n (-index option item number %d)", j)); + "\n (-index option item number %" TCL_Z_MODIFIER "u)", j)); goto done; } sortInfo.indexv[j] = encoded; } break; @@ -3398,20 +3564,20 @@ if (returnSubindices && sortInfo.indexc==0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "-subindices cannot be used without -index option", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH", - "BAD_OPTION_MIX", NULL); + "BAD_OPTION_MIX", (void *)NULL); result = TCL_ERROR; goto done; } if (bisect && (allMatches || negatedMatch)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "-bisect is not compatible with -all or -not", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH", - "BAD_OPTION_MIX", NULL); + "BAD_OPTION_MIX", (void *)NULL); result = TCL_ERROR; goto done; } if (mode == REGEXP) { @@ -3445,11 +3611,11 @@ /* * Make sure the list argument is a list object and get its length and a * pointer to its array of element pointers. */ - result = TclListObjGetElements(interp, objv[objc - 2], &listc, &listv); + result = TclListObjGetElementsM(interp, objv[objc - 2], &listc, &listv); if (result != TCL_OK) { goto done; } /* @@ -3461,11 +3627,11 @@ 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); + (void *)NULL); result = TCL_ERROR; goto done; } if (sortInfo.indexc > 0) { /* @@ -3472,16 +3638,16 @@ * Use the first value in the list supplied to -index as the * offset of the element within each group by which to sort. */ groupOffset = TclIndexDecode(sortInfo.indexv[0], groupSize - 1); - if (groupOffset >= groupSize) { + if (groupOffset < 0 || groupOffset >= groupSize) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "when used with \"-stride\", the leading \"-index\"" " value must be within the group", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH", - "BADINDEX", NULL); + "BADINDEX", (void *)NULL); result = TCL_ERROR; goto done; } if (sortInfo.indexc == 1) { sortInfo.indexc = 0; @@ -3512,15 +3678,15 @@ /* * If the search started past the end of the list, we just return a * "did not match anything at all" result straight away. [Bug 1374778] */ - if (start >= (size_t)listc) { + if (start >= listc) { if (allMatches || inlineReturn) { Tcl_ResetResult(interp); } else { - TclNewIndexObj(itemPtr, TCL_INDEX_NONE); + TclNewIntObj(itemPtr, -1); Tcl_SetObjResult(interp, itemPtr); } goto done; } @@ -3534,14 +3700,14 @@ } patObj = objv[objc - 1]; patternBytes = NULL; if (mode == EXACT || mode == SORTED) { - switch ((enum datatypes) dataType) { + switch (dataType) { case ASCII: case DICTIONARY: - patternBytes = TclGetStringFromObj(patObj, &length); + patternBytes = Tcl_GetStringFromObj(patObj, &length); break; case INTEGER: result = TclGetWideIntFromObj(interp, patObj, &patWide); if (result != TCL_OK) { goto done; @@ -3550,11 +3716,11 @@ /* * List representation might have been shimmered; restore it. [Bug * 1844789] */ - TclListObjGetElements(NULL, objv[objc - 2], &listc, &listv); + TclListObjGetElementsM(NULL, objv[objc - 2], &listc, &listv); break; case REAL: result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble); if (result != TCL_OK) { goto done; @@ -3563,15 +3729,15 @@ /* * List representation might have been shimmered; restore it. [Bug * 1844789] */ - TclListObjGetElements(NULL, objv[objc - 2], &listc, &listv); + TclListObjGetElementsM(NULL, objv[objc - 2], &listc, &listv); break; } } else { - patternBytes = TclGetStringFromObj(patObj, &length); + patternBytes = Tcl_GetStringFromObj(patObj, &length); } /* * Set default index value to -1, indicating failure; if we find the item * in the course of our search, index will be set to the correct value. @@ -3592,23 +3758,28 @@ * With -stride, lower, upper and i are kept as multiples of groupSize. */ lower = start - groupSize; upper = listc; + itemPtr = NULL; while (lower + groupSize != upper && sortInfo.resultCode == TCL_OK) { i = (lower + upper)/2; i -= i % groupSize; + + Tcl_BounceRefCount(itemPtr); + itemPtr = NULL; + if (sortInfo.indexc != 0) { itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo); if (sortInfo.resultCode != TCL_OK) { result = sortInfo.resultCode; goto done; } } else { itemPtr = listv[i+groupOffset]; } - switch ((enum datatypes) dataType) { + switch (dataType) { case ASCII: bytes = TclGetString(itemPtr); match = strCmpFn(patternBytes, bytes); break; case DICTIONARY: @@ -3693,10 +3864,13 @@ 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); @@ -3709,13 +3883,13 @@ } switch (mode) { case SORTED: case EXACT: - switch ((enum datatypes) dataType) { + switch (dataType) { case ASCII: - bytes = TclGetStringFromObj(itemPtr, &elemLen); + bytes = Tcl_GetStringFromObj(itemPtr, &elemLen); if (length == elemLen) { /* * This split allows for more optimal compilation of * memcmp/strcasecmp. */ @@ -3792,22 +3966,24 @@ /* * Note that these appends are not expected to fail. */ if (returnSubindices && (sortInfo.indexc != 0)) { + Tcl_BounceRefCount(itemPtr); itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo); Tcl_ListObjAppendElement(interp, listPtr, itemPtr); } else if (groupSize > 1) { Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, groupSize, &listv[i]); } else { + Tcl_BounceRefCount(itemPtr); itemPtr = listv[i]; Tcl_ListObjAppendElement(interp, listPtr, itemPtr); } } else if (returnSubindices) { - int j; + Tcl_Size j; TclNewIndexObj(itemPtr, i+groupOffset); for (j=0 ; j 6) { + /* Too many arguments */ + arg_key=0; + } else for (i=1; i=0) { + if (numValues[value_i]) Tcl_DecrRefCount(numValues[value_i]); + } + + // Free constants + Tcl_DecrRefCount(zero); + Tcl_DecrRefCount(one); + + return status; +} /* *---------------------------------------------------------------------- * * Tcl_LsetObjCmd -- @@ -3929,12 +4501,20 @@ */ if (objc == 4) { finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]); } else { - finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2, - objv[objc-1]); + 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. */ @@ -3979,22 +4559,22 @@ *---------------------------------------------------------------------- */ int Tcl_LsortObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument values. */ { - int i, index, indices, length, nocase = 0, indexc; + int indices, nocase = 0, indexc; int sortMode = SORTMODE_ASCII; int group, allocatedIndexVector = 0; - size_t j, idx, groupSize, groupOffset; - Tcl_WideInt wide; + Tcl_Size j, idx, groupOffset, length; + Tcl_WideInt wide, groupSize; Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr; - size_t elmArrSize; + Tcl_Size i, elmArrSize; SortElement *elementArray = NULL, *elementPtr; SortInfo sortInfo; /* Information about this sort that needs to * be passed to the comparison function. */ # define MAXCALLOC 1024000 # define NUM_LISTS 30 @@ -4010,11 +4590,11 @@ }; 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; } @@ -4040,20 +4620,20 @@ if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0, &index) != TCL_OK) { sortInfo.resultCode = TCL_ERROR; goto done; } - switch ((enum Lsort_Switches) index) { + switch (index) { case LSORT_ASCII: sortInfo.sortMode = SORTMODE_ASCII; break; case LSORT_COMMAND: if (i == objc-2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-command\" option must be followed " "by comparison command", -1)); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (void *)NULL); sortInfo.resultCode = TCL_ERROR; goto done; } sortInfo.sortMode = SORTMODE_COMMAND; cmdPtr = objv[i+1]; @@ -4067,22 +4647,22 @@ break; case LSORT_INCREASING: sortInfo.isIncreasing = 1; break; case LSORT_INDEX: { - int sortindex; + Tcl_Size sortindex; Tcl_Obj **indexv; if (i == objc-2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-index\" option must be followed by list index", -1)); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (void *)NULL); sortInfo.resultCode = TCL_ERROR; goto done; } - if (TclListObjGetElements(interp, objv[i+1], &sortindex, + if (TclListObjGetElementsM(interp, objv[i+1], &sortindex, &indexv) != TCL_OK) { sortInfo.resultCode = TCL_ERROR; goto done; } @@ -4092,26 +4672,26 @@ * know if this is the only -index option yet and so we can't * allocate any space; that happens after the scan through all the * options is done. */ - for (j=0 ; j<(size_t)sortindex ; j++) { + for (j=0 ; j 0) { @@ -4260,16 +4843,16 @@ * Use the first value in the list supplied to -index as the * offset of the element within each group by which to sort. */ groupOffset = TclIndexDecode(sortInfo.indexv[0], groupSize - 1); - if (groupOffset >= groupSize) { + if (groupOffset < 0 || groupOffset >= groupSize) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "when used with \"-stride\", the leading \"-index\"" " value must be within the group", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT", - "BADINDEX", NULL); + "BADINDEX", (void *)NULL); sortInfo.resultCode = TCL_ERROR; goto done; } if (sortInfo.indexc == 1) { sortInfo.indexc = 0; @@ -4326,12 +4909,12 @@ } else { elementArray = (SortElement *)malloc(elmArrSize); } if (!elementArray) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "no enough memory to proccess sort of %d items", length)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + "no enough memory to proccess sort of %" TCL_Z_MODIFIER "u items", length)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); sortInfo.resultCode = TCL_ERROR; goto done; } for (i=0; i < length; i++) { @@ -4385,11 +4968,11 @@ } else { elementArray[i].payload.objPtr = listObjPtrs[idx]; } /* - * Merge this element in the pre-existing sublists (and merge together + * Merge this element in the preexisting sublists (and merge together * sublists when we have two of the same size). */ elementArray[i].nextPtr = NULL; elementPtr = &elementArray[i]; @@ -4415,16 +4998,16 @@ /* * Now store the sorted elements in the result list. */ if (sortInfo.resultCode == TCL_OK) { - List *listRepPtr; + ListRep listRep; Tcl_Obj **newArray, *objPtr; resultPtr = Tcl_NewListObj(sortInfo.numElements * groupSize, NULL); - listRepPtr = ListRepPtr(resultPtr); - newArray = &listRepPtr->elements; + ListObjGetRep(resultPtr, &listRep); + newArray = ListRepElementsBase(&listRep); if (group) { for (i=0; elementPtr!=NULL ; elementPtr=elementPtr->nextPtr) { idx = elementPtr->payload.index; for (j = 0; j < groupSize; j++) { if (indices) { @@ -4449,11 +5032,15 @@ objPtr = elementPtr->payload.objPtr; newArray[i++] = objPtr; Tcl_IncrRefCount(objPtr); } } - listRepPtr->elemCount = i; + 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) { @@ -4471,10 +5058,119 @@ 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 = TclListObjLengthM(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 - @@ -4581,11 +5277,11 @@ * * This procedure is invoked by MergeLists to determine the proper * ordering between two elements. * * Results: - * A negative results means the the first element comes before the + * A negative results means the first element comes before the * second, and a positive results means that the second element should * come first. A result of zero means the two elements are equal and it * doesn't matter which comes first. * * Side effects: @@ -4624,11 +5320,11 @@ a = elemPtr1->collationKey.doubleValue; b = elemPtr2->collationKey.doubleValue; order = ((a >= b) - (a <= b)); } else { Tcl_Obj **objv, *paramObjv[2]; - int objc; + Tcl_Size objc; Tcl_Obj *objPtr1, *objPtr2; if (infoPtr->resultCode != TCL_OK) { /* * Once an error has occurred, skip any future comparisons so as @@ -4648,14 +5344,14 @@ /* * We made space in the command list for the two things to compare. * Replace them and evaluate the result. */ - TclListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc); + TclListObjLengthM(infoPtr->interp, infoPtr->compareCmdPtr, &objc); Tcl_ListObjReplace(infoPtr->interp, infoPtr->compareCmdPtr, objc - 2, 2, 2, paramObjv); - TclListObjGetElements(infoPtr->interp, infoPtr->compareCmdPtr, + TclListObjGetElementsM(infoPtr->interp, infoPtr->compareCmdPtr, &objc, &objv); infoPtr->resultCode = Tcl_EvalObjv(infoPtr->interp, objc, objv, 0); if (infoPtr->resultCode != TCL_OK) { @@ -4670,11 +5366,11 @@ if (TclGetIntFromObj(infoPtr->interp, Tcl_GetObjResult(infoPtr->interp), &order) != TCL_OK) { Tcl_SetObjResult(infoPtr->interp, Tcl_NewStringObj( "-compare command returned non-integer result", -1)); Tcl_SetErrorCode(infoPtr->interp, "TCL", "OPERATION", "LSORT", - "COMPARISONFAILED", NULL); + "COMPARISONFAILED", (void *)NULL); infoPtr->resultCode = TCL_ERROR; return 0; } } if (!infoPtr->isIncreasing) { @@ -4778,16 +5474,16 @@ * string is at the terminating null, do a byte-wise comparison and * bail out immediately. */ if ((*left != '\0') && (*right != '\0')) { - left += TclUtfToUCS4(left, &uniLeft); - right += TclUtfToUCS4(right, &uniRight); + left += Tcl_UtfToUniChar(left, &uniLeft); + right += Tcl_UtfToUniChar(right, &uniRight); /* * Convert both chars to lower for the comparison, because - * dictionary sorts are case insensitve. Covert to lower, not + * dictionary sorts are case-insensitive. Covert to lower, not * upper, so chars between Z and a will sort before A (where most * other interesting punctuations occur). */ uniLeftLower = Tcl_UniCharToLower(uniLeft); @@ -4842,11 +5538,11 @@ SelectObjFromSublist( Tcl_Obj *objPtr, /* Obj to select sublist from. */ SortInfo *infoPtr) /* Information passed from the top-level * "lsearch" or "lsort" command. */ { - int i; + Tcl_Size i; /* * Quick check for case when no "-index" option is there. */ @@ -4858,14 +5554,15 @@ * Iterate over the indices, traversing through the nested sublists as we * go. */ for (i=0 ; iindexc ; i++) { - int listLen, index; - Tcl_Obj *currentObj; + Tcl_Size listLen; + int index; + Tcl_Obj *currentObj, *lastObj=NULL; - if (TclListObjLength(infoPtr->interp, objPtr, &listLen) != TCL_OK) { + if (TclListObjLengthM(infoPtr->interp, objPtr, &listLen) != TCL_OK) { infoPtr->resultCode = TCL_ERROR; return NULL; } index = TclIndexDecode(infoPtr->indexv[i], listLen - 1); @@ -4874,11 +5571,11 @@ ¤tObj) != TCL_OK) { infoPtr->resultCode = TCL_ERROR; return NULL; } if (currentObj == NULL) { - if (index == (int)TCL_INDEX_NONE) { + if (index == TCL_INDEX_NONE) { index = TCL_INDEX_END - infoPtr->indexv[i]; Tcl_SetObjResult(infoPtr->interp, Tcl_ObjPrintf( "element end-%d missing from sublist \"%s\"", index, TclGetString(objPtr))); } else { @@ -4885,15 +5582,17 @@ Tcl_SetObjResult(infoPtr->interp, Tcl_ObjPrintf( "element %d missing from sublist \"%s\"", index, TclGetString(objPtr))); } Tcl_SetErrorCode(infoPtr->interp, "TCL", "OPERATION", "LSORT", - "INDEXFAILED", NULL); + "INDEXFAILED", (void *)NULL); infoPtr->resultCode = TCL_ERROR; return NULL; } objPtr = currentObj; + Tcl_BounceRefCount(lastObj); + lastObj = currentObj; } return objPtr; } /* Index: generic/tclCmdMZ.c ================================================================== --- generic/tclCmdMZ.c +++ generic/tclCmdMZ.c @@ -4,65 +4,69 @@ * This file contains the top-level command routines for most of the Tcl * built-in commands whose names begin with the letters M to Z. It * contains only commands in the generic core (i.e. those that don't * depend much upon UNIX facilities). * - * Copyright (c) 1987-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 Scriptics Corporation. - * Copyright (c) 2002 ActiveState Corporation. - * Copyright (c) 2003-2009 Donal K. Fellows. + * Copyright © 1987-1993 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Scriptics Corporation. + * Copyright © 2002 ActiveState Corporation. + * Copyright © 2003-2009 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include "tclRegexp.h" #include "tclStringTrim.h" +#include "tclTomMath.h" static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode, Tcl_Obj *oldOptions, Tcl_Obj *errorInfo); static Tcl_NRPostProc SwitchPostProc; static Tcl_NRPostProc TryPostBody; static Tcl_NRPostProc TryPostFinal; static Tcl_NRPostProc TryPostHandler; static int UniCharIsAscii(int character); static int UniCharIsHexDigit(int character); +static int StringCmpOpts(Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[], int *nocase, + Tcl_Size *reqlength); /* * Default set of characters to trim in [string trim] and friends. This is a * UTF-8 literal string containing all Unicode space characters [TIP #413] */ const char tclDefaultTrimSet[] = - "\x09\x0a\x0b\x0c\x0d " /* ASCII */ - "\xc0\x80" /* nul (U+0000) */ - "\xc2\x85" /* next line (U+0085) */ - "\xc2\xa0" /* non-breaking space (U+00a0) */ - "\xe1\x9a\x80" /* ogham space mark (U+1680) */ - "\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */ - "\xe2\x80\x80" /* en quad (U+2000) */ - "\xe2\x80\x81" /* em quad (U+2001) */ - "\xe2\x80\x82" /* en space (U+2002) */ - "\xe2\x80\x83" /* em space (U+2003) */ - "\xe2\x80\x84" /* three-per-em space (U+2004) */ - "\xe2\x80\x85" /* four-per-em space (U+2005) */ - "\xe2\x80\x86" /* six-per-em space (U+2006) */ - "\xe2\x80\x87" /* figure space (U+2007) */ - "\xe2\x80\x88" /* punctuation space (U+2008) */ - "\xe2\x80\x89" /* thin space (U+2009) */ - "\xe2\x80\x8a" /* hair space (U+200a) */ - "\xe2\x80\x8b" /* zero width space (U+200b) */ - "\xe2\x80\xa8" /* line separator (U+2028) */ - "\xe2\x80\xa9" /* paragraph separator (U+2029) */ - "\xe2\x80\xaf" /* narrow no-break space (U+202f) */ - "\xe2\x81\x9f" /* medium mathematical space (U+205f) */ - "\xe2\x81\xa0" /* word joiner (U+2060) */ - "\xe3\x80\x80" /* ideographic space (U+3000) */ - "\xef\xbb\xbf" /* zero width no-break space (U+feff) */ + "\x09\x0A\x0B\x0C\x0D " /* ASCII */ + "\xC0\x80" /* nul (U+0000) */ + "\xC2\x85" /* next line (U+0085) */ + "\xC2\xA0" /* non-breaking space (U+00a0) */ + "\xE1\x9A\x80" /* ogham space mark (U+1680) */ + "\xE1\xA0\x8E" /* mongolian vowel separator (U+180e) */ + "\xE2\x80\x80" /* en quad (U+2000) */ + "\xE2\x80\x81" /* em quad (U+2001) */ + "\xE2\x80\x82" /* en space (U+2002) */ + "\xE2\x80\x83" /* em space (U+2003) */ + "\xE2\x80\x84" /* three-per-em space (U+2004) */ + "\xE2\x80\x85" /* four-per-em space (U+2005) */ + "\xE2\x80\x86" /* six-per-em space (U+2006) */ + "\xE2\x80\x87" /* figure space (U+2007) */ + "\xE2\x80\x88" /* punctuation space (U+2008) */ + "\xE2\x80\x89" /* thin space (U+2009) */ + "\xE2\x80\x8A" /* hair space (U+200a) */ + "\xE2\x80\x8B" /* zero width space (U+200b) */ + "\xE2\x80\xA8" /* line separator (U+2028) */ + "\xE2\x80\xA9" /* paragraph separator (U+2029) */ + "\xE2\x80\xAF" /* narrow no-break space (U+202f) */ + "\xE2\x81\x9F" /* medium mathematical space (U+205f) */ + "\xE2\x81\xA0" /* word joiner (U+2060) */ + "\xE3\x80\x80" /* ideographic space (U+3000) */ + "\xEF\xBB\xBF" /* zero width no-break space (U+feff) */ ; /* *---------------------------------------------------------------------- * @@ -80,11 +84,11 @@ *---------------------------------------------------------------------- */ int Tcl_PwdObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *retVal; @@ -120,16 +124,16 @@ *---------------------------------------------------------------------- */ int Tcl_RegexpObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t offset, stringLength, matchLength, cflags, eflags; + Tcl_Size offset, stringLength, matchLength, cflags, eflags; int i, indices, match, about, all, doinline, numMatchesSaved; Tcl_RegExp regExpr; Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL; Tcl_RegExpInfo info; static const char *const options[] = { @@ -139,11 +143,11 @@ }; 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; @@ -150,21 +154,20 @@ all = 0; doinline = 0; for (i = 1; i < objc; i++) { const char *name; - int index; name = TclGetString(objv[i]); if (name[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", TCL_EXACT, &index) != TCL_OK) { goto optionError; } - switch ((enum regexpoptions) index) { + switch (index) { case REGEXP_ALL: all = 1; break; case REGEXP_INDICES: indices = 1; @@ -189,15 +192,15 @@ break; case REGEXP_LINEANCHOR: cflags |= TCL_REG_NLANCH; break; case REGEXP_START: { - size_t temp; + Tcl_Size temp; if (++i >= objc) { goto endOfForLoop; } - if (TclGetIntForIndexM(interp, objv[i], (size_t)WIDE_MAX - 1, &temp) != TCL_OK) { + if (TclGetIntForIndexM(interp, objv[i], TCL_SIZE_MAX - 1, &temp) != TCL_OK) { goto optionError; } if (startIndex) { Tcl_DecrRefCount(startIndex); } @@ -227,11 +230,11 @@ if (doinline && ((objc - 2) != 0)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "regexp match variables not allowed when using -inline", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGEXP", - "MIX_VAR_INLINE", NULL); + "MIX_VAR_INLINE", (void *)NULL); goto optionError; } /* * Handle the odd about case separately. @@ -259,11 +262,11 @@ stringLength = Tcl_GetCharLength(objPtr); if (startIndex) { TclGetIntForIndexM(interp, startIndex, stringLength, &offset); Tcl_DecrRefCount(startIndex); - if (offset == TCL_INDEX_NONE) { + if (offset < 0) { offset = TCL_INDEX_START; } } regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags); @@ -306,11 +309,11 @@ * start of the string unless the previous character is a newline. */ if (offset == TCL_INDEX_START) { eflags = 0; - } else if (offset + 1 > stringLength + 1) { + } else if (offset > stringLength) { eflags = TCL_REG_NOTBOL; } else if (Tcl_GetUniChar(objPtr, offset-1) == '\n') { eflags = 0; } else { eflags = TCL_REG_NOTBOL; @@ -355,35 +358,35 @@ * index 0 */ objc = info.nsubs + 1; if (all <= 1) { - resultPtr = Tcl_NewObj(); + TclNewObj(resultPtr); } } for (i = 0; i < objc; i++) { Tcl_Obj *newPtr; if (indices) { - size_t start, end; + Tcl_Size start, end; Tcl_Obj *objs[2]; /* * Only adjust the match area if there was a match for that * area. (Scriptics Bug 4391/SF Bug #219232) */ - if (i <= (int)info.nsubs && info.matches[i].start != TCL_INDEX_NONE) { + if (i <= (int)info.nsubs && info.matches[i].start >= 0) { start = offset + info.matches[i].start; end = offset + info.matches[i].end; /* * Adjust index so it refers to the last character in the * match instead of the first character after the match. */ - if (end + 1 >= offset + 1) { + if (end >= offset) { end--; } } else { start = TCL_INDEX_NONE; end = TCL_INDEX_NONE; @@ -392,16 +395,16 @@ TclNewIndexObj(objs[0], start); TclNewIndexObj(objs[1], end); newPtr = Tcl_NewListObj(2, objs); } else { - if (i <= (int)info.nsubs) { + if ((i <= (int)info.nsubs) && (info.matches[i].end > 0)) { newPtr = Tcl_GetRange(objPtr, offset + info.matches[i].start, offset + info.matches[i].end - 1); } else { - newPtr = Tcl_NewObj(); + TclNewObj(newPtr); } } if (doinline) { if (Tcl_ListObjAppendElement(interp, resultPtr, newPtr) != TCL_OK) { @@ -425,11 +428,11 @@ * Adjust the offset to the character just after the last one in the * matchVar and increment all to count how many times we are making a * match. We always increment the offset by at least one to prevent * endless looping (as in the case: regexp -all {a*} a). Otherwise, * when we match the NULL string at the end of the input string, we - * will loop indefinately (because the length of the match is 0, so + * will loop indefinitely (because the length of the match is 0, so * offset never changes). */ matchLength = (info.matches[0].end - info.matches[0].start); @@ -442,11 +445,11 @@ if (matchLength == 0) { offset++; } all++; - if (offset + 1 >= stringLength + 1) { + if (offset >= stringLength) { break; } } /* @@ -480,18 +483,18 @@ *---------------------------------------------------------------------- */ int Tcl_RegsubObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int result, cflags, all, match, command, numParts; - size_t idx, wlen, wsublen = 0, offset, numMatches; - size_t start, end, subStart, subEnd; + int result, cflags, all, match, command; + Tcl_Size idx, wlen, wsublen = 0, offset, numMatches, numParts; + Tcl_Size start, end, subStart, subEnd; Tcl_RegExp regExpr; Tcl_RegExpInfo info; Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL; Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec = 0, *wend; @@ -502,31 +505,30 @@ }; enum regsubobjoptions { REGSUB_ALL, REGSUB_COMMAND, REGSUB_EXPANDED, REGSUB_LINE, REGSUB_LINESTOP, REGSUB_LINEANCHOR, REGSUB_NOCASE, REGSUB_START, REGSUB_LAST - }; + } index; cflags = TCL_REG_ADVANCED; all = 0; offset = TCL_INDEX_START; command = 0; resultPtr = NULL; - for (idx = 1; idx < (size_t)objc; idx++) { + for (idx = 1; idx < objc; idx++) { const char *name; - int index; name = TclGetString(objv[idx]); if (name[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[idx], options, "option", TCL_EXACT, &index) != TCL_OK) { goto optionError; } - switch ((enum regsubobjoptions) index) { + switch (index) { case REGSUB_ALL: all = 1; break; case REGSUB_NOCASE: cflags |= TCL_REG_NOCASE; @@ -545,15 +547,15 @@ break; case REGSUB_LINEANCHOR: cflags |= TCL_REG_NLANCH; break; case REGSUB_START: { - size_t temp; - if (++idx >= (size_t)objc) { + Tcl_Size temp; + if (++idx >= objc) { goto endOfForLoop; } - if (TclGetIntForIndexM(interp, objv[idx], (size_t)WIDE_MAX - 1, &temp) != TCL_OK) { + if (TclGetIntForIndexM(interp, objv[idx], TCL_SIZE_MAX - 1, &temp) != TCL_OK) { goto optionError; } if (startIndex) { Tcl_DecrRefCount(startIndex); } @@ -566,11 +568,11 @@ goto endOfForLoop; } } endOfForLoop: - if ((size_t)objc < idx + 3 || (size_t)objc > idx + 4) { + if (objc < idx + 3 || objc > idx + 4) { Tcl_WrongNumArgs(interp, 1, objv, "?-option ...? exp string subSpec ?varName?"); optionError: if (startIndex) { Tcl_DecrRefCount(startIndex); @@ -580,39 +582,39 @@ objc -= idx; objv += idx; if (startIndex) { - size_t stringLength = Tcl_GetCharLength(objv[1]); + Tcl_Size stringLength = Tcl_GetCharLength(objv[1]); TclGetIntForIndexM(interp, startIndex, stringLength, &offset); Tcl_DecrRefCount(startIndex); - if (offset == TCL_INDEX_NONE) { - offset = TCL_INDEX_START; + if (offset < 0) { + offset = 0; } } - if (all && (offset == TCL_INDEX_START) && (command == 0) + if (all && (offset == 0) && (command == 0) && (strpbrk(TclGetString(objv[2]), "&\\") == NULL) && (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) { /* * This is a simple one pair string map situation. We make use of a * slightly modified version of the one pair STR_MAP code. */ - size_t slen; + Tcl_Size slen; int nocase, wsrclc; int (*strCmpFn)(const Tcl_UniChar*,const Tcl_UniChar*,size_t); Tcl_UniChar *p; numMatches = 0; nocase = (cflags & TCL_REG_NOCASE); strCmpFn = nocase ? TclUniCharNcasecmp : TclUniCharNcmp; - wsrc = TclGetUnicodeFromObj(objv[0], &slen); - wstring = TclGetUnicodeFromObj(objv[1], &wlen); - wsubspec = TclGetUnicodeFromObj(objv[2], &wsublen); + wsrc = Tcl_GetUnicodeFromObj(objv[0], &slen); + wstring = Tcl_GetUnicodeFromObj(objv[1], &wlen); + wsubspec = Tcl_GetUnicodeFromObj(objv[2], &wsublen); wend = wstring + wlen - (slen ? slen - 1 : 0); result = TCL_OK; if (slen == 0) { /* @@ -622,12 +624,12 @@ if (wstring < wend) { resultPtr = Tcl_NewUnicodeObj(wstring, 0); Tcl_IncrRefCount(resultPtr); for (; wstring < wend; wstring++) { - TclAppendUnicodeToObj(resultPtr, wsubspec, wsublen); - TclAppendUnicodeToObj(resultPtr, wstring, 1); + Tcl_AppendUnicodeToObj(resultPtr, wsubspec, wsublen); + Tcl_AppendUnicodeToObj(resultPtr, wstring, 1); numMatches++; } wlen = 0; } } else { @@ -639,18 +641,18 @@ if (numMatches == 0) { resultPtr = Tcl_NewUnicodeObj(wstring, 0); Tcl_IncrRefCount(resultPtr); } if (p != wstring) { - TclAppendUnicodeToObj(resultPtr, p, wstring - p); + Tcl_AppendUnicodeToObj(resultPtr, p, wstring - p); p = wstring + slen; } else { p += slen; } wstring = p - 1; - TclAppendUnicodeToObj(resultPtr, wsubspec, wsublen); + Tcl_AppendUnicodeToObj(resultPtr, wsubspec, wsublen); numMatches++; } } if (numMatches) { wlen = wfirstChar + wlen - p; @@ -673,19 +675,19 @@ * argument be a list, so we enforce that here. Afterwards, we fetch * the RE compilation again in case objv[0] and objv[2] are the same * object. (If they aren't, that's cheap to do.) */ - if (Tcl_ListObjLength(interp, objv[2], &numParts) != TCL_OK) { + if (TclListObjLengthM(interp, objv[2], &numParts) != TCL_OK) { return TCL_ERROR; } if (numParts < 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command prefix must be a list of at least one element", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGSUB", - "CMDEMPTY", NULL); + "CMDEMPTY", (void *)NULL); return TCL_ERROR; } regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags); } @@ -698,18 +700,18 @@ if (objv[1] == objv[0]) { objPtr = Tcl_DuplicateObj(objv[1]); } else { objPtr = objv[1]; } - wstring = TclGetUnicodeFromObj(objPtr, &wlen); + wstring = Tcl_GetUnicodeFromObj(objPtr, &wlen); if (objv[2] == objv[0]) { subPtr = Tcl_DuplicateObj(objv[2]); } else { subPtr = objv[2]; } if (!command) { - wsubspec = TclGetUnicodeFromObj(subPtr, &wsublen); + wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen); } result = TCL_OK; /* @@ -749,11 +751,11 @@ /* * Copy the initial portion of the string in if an offset was * specified. */ - TclAppendUnicodeToObj(resultPtr, wstring, offset); + Tcl_AppendUnicodeToObj(resultPtr, wstring, offset); } } numMatches++; /* @@ -762,11 +764,11 @@ */ Tcl_RegExpGetInfo(regExpr, &info); start = info.matches[0].start; end = info.matches[0].end; - TclAppendUnicodeToObj(resultPtr, wstring + offset, start); + Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, start); /* * In command-prefix mode, the substitutions are added as quoted * arguments to the subSpec to form a command, that is then executed * and the result used as the string to substitute in. Actually, @@ -773,21 +775,21 @@ * everything is passed through Tcl_EvalObjv, as that's much faster. */ if (command) { Tcl_Obj **args = NULL, **parts; - int numArgs; + Tcl_Size numArgs; - Tcl_ListObjGetElements(interp, subPtr, &numParts, &parts); + TclListObjGetElementsM(interp, subPtr, &numParts, &parts); numArgs = numParts + info.nsubs + 1; args = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj*) * numArgs); memcpy(args, parts, sizeof(Tcl_Obj*) * numParts); for (idx = 0 ; idx <= info.nsubs ; idx++) { subStart = info.matches[idx].start; subEnd = info.matches[idx].end; - if ((subStart != TCL_INDEX_NONE) && (subEnd != TCL_INDEX_NONE)) { + if ((subStart >= 0) && (subEnd >= 0)) { args[idx + numParts] = Tcl_NewUnicodeObj( wstring + offset + subStart, subEnd - subStart); } else { args[idx + numParts] = Tcl_NewObj(); } @@ -825,11 +827,11 @@ /* * Refetch the unicode, in case the representation was smashed by * the user code. */ - wstring = TclGetUnicodeFromObj(objPtr, &wlen); + wstring = Tcl_GetUnicodeFromObj(objPtr, &wlen); offset += end; if (end == 0 || start == end) { /* * Always consume at least one character of the input string @@ -837,11 +839,11 @@ * technically matched the empty string; we must not match * again at the same spot. */ if (offset < wlen) { - TclAppendUnicodeToObj(resultPtr, wstring + offset, 1); + Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1); } offset++; } if (all) { continue; @@ -866,11 +868,11 @@ ch = wsrc[1]; if ((ch >= '0') && (ch <= '9')) { idx = ch - '0'; } else if ((ch == '\\') || (ch == '&')) { *wsrc = ch; - TclAppendUnicodeToObj(resultPtr, wfirstChar, + Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar + 1); *wsrc = '\\'; wfirstChar = wsrc + 2; wsrc++; continue; @@ -880,19 +882,19 @@ } else { continue; } if (wfirstChar != wsrc) { - TclAppendUnicodeToObj(resultPtr, wfirstChar, + Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar); } if (idx <= info.nsubs) { subStart = info.matches[idx].start; subEnd = info.matches[idx].end; - if ((subStart != TCL_INDEX_NONE) && (subEnd != TCL_INDEX_NONE)) { - TclAppendUnicodeToObj(resultPtr, + if ((subStart >= 0) && (subEnd >= 0)) { + Tcl_AppendUnicodeToObj(resultPtr, wstring + offset + subStart, subEnd - subStart); } } if (*wsrc == '\\') { @@ -900,21 +902,21 @@ } wfirstChar = wsrc + 1; } if (wfirstChar != wsrc) { - TclAppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar); + Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar); } if (end == 0) { /* * Always consume at least one character of the input string in * order to prevent infinite loops. */ if (offset < wlen) { - TclAppendUnicodeToObj(resultPtr, wstring + offset, 1); + Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1); } offset++; } else { offset += end; if (start == end) { @@ -922,11 +924,11 @@ * We matched an empty string, which means we must go forward * one more step so we don't match again at the same spot. */ if (offset < wlen) { - TclAppendUnicodeToObj(resultPtr, wstring + offset, 1); + Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1); } offset++; } } if (!all) { @@ -947,11 +949,11 @@ */ resultPtr = objv[1]; Tcl_IncrRefCount(resultPtr); } else if (offset < wlen) { - TclAppendUnicodeToObj(resultPtr, wstring + offset, wlen - offset); + Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, wlen - offset); } if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr, TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; @@ -1001,11 +1003,11 @@ *---------------------------------------------------------------------- */ int Tcl_RenameObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *oldName, *newName; @@ -1037,11 +1039,11 @@ *---------------------------------------------------------------------- */ int Tcl_ReturnObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int code, level; @@ -1084,21 +1086,21 @@ *---------------------------------------------------------------------- */ int Tcl_SourceObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRSourceObjCmd, clientData, objc, objv); } int TclNRSourceObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *encodingName = NULL; @@ -1168,36 +1170,36 @@ *---------------------------------------------------------------------- */ int Tcl_SplitObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int ch = 0; int len; const char *splitChars; const char *stringPtr; const char *end; - size_t splitCharLen, stringLen; + Tcl_Size splitCharLen, stringLen; Tcl_Obj *listPtr, *objPtr; if (objc == 2) { splitChars = " \n\t\r"; splitCharLen = 4; } else if (objc == 3) { - splitChars = TclGetStringFromObj(objv[2], &splitCharLen); + splitChars = Tcl_GetStringFromObj(objv[2], &splitCharLen); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?splitChars?"); return TCL_ERROR; } - stringPtr = TclGetStringFromObj(objv[1], &stringLen); + stringPtr = Tcl_GetStringFromObj(objv[1], &stringLen); end = stringPtr + stringLen; - listPtr = Tcl_NewObj(); + TclNewObj(listPtr); if (stringLen == 0) { /* * Do nothing. */ @@ -1216,11 +1218,11 @@ */ Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS); for ( ; stringPtr < end; stringPtr += len) { - len = TclUtfToUCS4(stringPtr, &ch); + len = Tcl_UtfToUniChar(stringPtr, &ch); hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR(ch), &isNew); if (isNew) { TclNewStringObj(objPtr, stringPtr, len); /* @@ -1238,11 +1240,11 @@ } else if (splitCharLen == 1) { const char *p; /* * Handle the special case of splitting on a single character. This is - * only true for the one-char ASCII case, as one unicode char is > 1 + * only true for the one-char ASCII case, as one Unicode char is > 1 * byte in length. */ while (*stringPtr && (p=strchr(stringPtr,*splitChars)) != NULL) { objPtr = Tcl_NewStringObj(stringPtr, p - stringPtr); @@ -1251,11 +1253,11 @@ } TclNewStringObj(objPtr, stringPtr, end - stringPtr); Tcl_ListObjAppendElement(NULL, listPtr, objPtr); } else { const char *element, *p, *splitEnd; - size_t splitLen; + Tcl_Size splitLen; int splitChar; /* * Normal case: split on any of a given set of characters. Discard * instances of the split characters. @@ -1262,13 +1264,13 @@ */ splitEnd = splitChars + splitCharLen; for (element = stringPtr; stringPtr < end; stringPtr += len) { - len = TclUtfToUCS4(stringPtr, &ch); + len = Tcl_UtfToUniChar(stringPtr, &ch); for (p = splitChars; p < splitEnd; p += splitLen) { - splitLen = TclUtfToUCS4(p, &splitChar); + splitLen = Tcl_UtfToUniChar(p, &splitChar); if (ch == splitChar) { TclNewStringObj(objPtr, element, stringPtr - element); Tcl_ListObjAppendElement(NULL, listPtr, objPtr); element = stringPtr + len; break; @@ -1301,25 +1303,25 @@ *---------------------------------------------------------------------- */ static int StringFirstCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t start = TCL_INDEX_START; + Tcl_Size start = TCL_INDEX_START; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "needleString haystackString ?startIndex?"); return TCL_ERROR; } if (objc == 4) { - size_t end = Tcl_GetCharLength(objv[2]) - 1; + Tcl_Size end = Tcl_GetCharLength(objv[2]) - 1; if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &start)) { return TCL_ERROR; } } @@ -1345,25 +1347,25 @@ *---------------------------------------------------------------------- */ static int StringLastCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t last = TCL_INDEX_END; + Tcl_Size last = TCL_SIZE_MAX; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "needleString haystackString ?lastIndex?"); return TCL_ERROR; } if (objc == 4) { - size_t end = Tcl_GetCharLength(objv[2]) - 1; + Tcl_Size end = Tcl_GetCharLength(objv[2]) - 1; if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &last)) { return TCL_ERROR; } } @@ -1389,16 +1391,16 @@ *---------------------------------------------------------------------- */ static int StringIndexCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t index, end; + Tcl_Size index, end; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string charIndex"); return TCL_ERROR; } @@ -1410,11 +1412,11 @@ end = Tcl_GetCharLength(objv[1]) - 1; if (TclGetIntForIndexM(interp, objv[2], end, &index) != TCL_OK) { return TCL_ERROR; } - if ((index != TCL_INDEX_NONE) && (index + 1 <= end + 1)) { + if ((index >= 0) && (index <= end)) { int ch = Tcl_GetUniChar(objv[1], index); if (ch == -1) { return TCL_OK; } @@ -1430,13 +1432,10 @@ 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; } @@ -1459,17 +1458,17 @@ *---------------------------------------------------------------------- */ static int StringInsertCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter */ int objc, /* Number of arguments */ Tcl_Obj *const objv[]) /* Argument objects */ { - size_t length; /* String length */ - size_t index; /* Insert index */ + Tcl_Size length; /* String length */ + Tcl_Size index; /* Insert index */ Tcl_Obj *outObj; /* Output object */ if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "string index insertString"); return TCL_ERROR; @@ -1478,11 +1477,11 @@ length = Tcl_GetCharLength(objv[1]); if (TclGetIntForIndexM(interp, objv[2], length, &index) != TCL_OK) { return TCL_ERROR; } - if (index == TCL_INDEX_NONE) { + if (index < 0) { index = TCL_INDEX_START; } if (index > length) { index = length; } @@ -1516,45 +1515,44 @@ *---------------------------------------------------------------------- */ static int StringIsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *end, *stop; int (*chcomp)(int) = NULL; /* The UniChar comparison function. */ - int i, result = 1, strict = 0, index, length3; - size_t failat = 0; - size_t length1, length2; + 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 + "space", "true", "upper", "unicode", + "wideinteger", "wordchar", "xdigit", NULL }; enum isClassesEnum { STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL, STR_IS_BOOL, STR_IS_DICT, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_ENTIER, STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, STR_IS_LIST, STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, - STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER, STR_IS_WIDE, - STR_IS_WORD, STR_IS_XDIGIT - }; + STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER, STR_IS_UNICODE, + 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; @@ -1564,17 +1562,15 @@ return TCL_ERROR; } if (objc != 3) { for (i = 2; i < objc-1; i++) { - int idx2; - if (Tcl_GetIndexFromObj(interp, objv[i], isOptions, "option", 0, &idx2) != TCL_OK) { return TCL_ERROR; } - switch ((enum isOptionsEnum) idx2) { + switch (idx2) { case OPT_STRICT: strict = 1; break; case OPT_FAILIDX: if (i+1 >= objc-1) { @@ -1589,21 +1585,21 @@ } /* * We get the objPtr so that we can short-cut for some classes by checking * the object type (int and double), but we need the string otherwise, - * because we don't want any conversion of type occuring (as, for example, + * because we don't want any conversion of type occurring (as, for example, * Tcl_Get*FromObj would do). */ objPtr = objv[objc-1]; /* * When entering here, result == 1 and failat == 0. */ - switch ((enum isClassesEnum) index) { + switch (index) { case STR_IS_ALNUM: chcomp = Tcl_UniCharIsAlnum; break; case STR_IS_ALPHA: chcomp = Tcl_UniCharIsAlpha; @@ -1612,16 +1608,16 @@ chcomp = UniCharIsAscii; break; case STR_IS_BOOL: case STR_IS_TRUE: case STR_IS_FALSE: - if (!TclHasIntRep(objPtr, &tclBooleanType) + if (!TclHasInternalRep(objPtr, &tclBooleanType) && (TCL_OK != TclSetBooleanFromAny(NULL, objPtr))) { if (strict) { result = 0; } else { - string1 = TclGetStringFromObj(objPtr, &length1); + string1 = Tcl_GetStringFromObj(objPtr, &length1); result = length1 == 0; } } else if ((objPtr->internalRep.wideValue != 0) ? (index == STR_IS_FALSE) : (index == STR_IS_TRUE)) { result = 0; @@ -1629,11 +1625,12 @@ break; case STR_IS_CONTROL: chcomp = Tcl_UniCharIsControl; break; case STR_IS_DICT: { - int dresult, dsize; + int dresult; + Tcl_Size dsize; dresult = Tcl_DictObjSize(interp, objPtr, &dsize); Tcl_ResetResult(interp); result = (dresult == TCL_OK) ? 1 : 0; if (dresult != TCL_OK && failVarObj != NULL) { @@ -1642,15 +1639,14 @@ * fairly expensive. This is adapted from the core of * SetDictFromAny(). */ const char *elemStart, *nextElem; - int lenRemain; - size_t elemSize; + Tcl_Size lenRemain, elemSize; const char *p; - string1 = TclGetStringFromObj(objPtr, &length1); + string1 = Tcl_GetStringFromObj(objPtr, &length1); end = string1 + length1; failat = -1; for (p=string1, lenRemain=length1; lenRemain > 0; p=nextElem, lenRemain=end-nextElem) { if (TCL_ERROR == TclFindElement(NULL, p, lenRemain, @@ -1681,54 +1677,54 @@ } case STR_IS_DIGIT: chcomp = Tcl_UniCharIsDigit; break; case STR_IS_DOUBLE: { - if (TclHasIntRep(objPtr, &tclDoubleType) || - TclHasIntRep(objPtr, &tclIntType) || - TclHasIntRep(objPtr, &tclBignumType)) { + if (TclHasInternalRep(objPtr, &tclDoubleType) || + TclHasInternalRep(objPtr, &tclIntType) || + TclHasInternalRep(objPtr, &tclBignumType)) { break; } - string1 = TclGetStringFromObj(objPtr, &length1); + string1 = Tcl_GetStringFromObj(objPtr, &length1); if (length1 == 0) { if (strict) { result = 0; } goto str_is_done; } end = string1 + length1; - if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, + if (TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE, (const char **) &stop, 0) != TCL_OK) { result = 0; failat = 0; } else { failat = stop - string1; if (stop < end) { result = 0; - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); } } break; } case STR_IS_GRAPH: chcomp = Tcl_UniCharIsGraph; break; case STR_IS_INT: case STR_IS_ENTIER: - if (TclHasIntRep(objPtr, &tclIntType) || - TclHasIntRep(objPtr, &tclBignumType)) { + if (TclHasInternalRep(objPtr, &tclIntType) || + TclHasInternalRep(objPtr, &tclBignumType)) { break; } - string1 = TclGetStringFromObj(objPtr, &length1); + string1 = Tcl_GetStringFromObj(objPtr, &length1); if (length1 == 0) { if (strict) { result = 0; } goto str_is_done; } end = string1 + length1; - if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, + if (TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE, (const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) { if (stop == end) { /* * Entire string parses as an integer. */ @@ -1742,11 +1738,11 @@ * *objPtr in an inconsistent state. */ result = 0; failat = stop - string1; - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); } } else { /* * No prefix is a valid integer. Fail at beginning. */ @@ -1758,11 +1754,11 @@ case STR_IS_WIDE: if (TCL_OK == TclGetWideIntFromObj(NULL, objPtr, &w)) { break; } - string1 = TclGetStringFromObj(objPtr, &length1); + string1 = Tcl_GetStringFromObj(objPtr, &length1); if (length1 == 0) { if (strict) { result = 0; } goto str_is_done; @@ -1775,11 +1771,11 @@ */ break; } end = string1 + length1; - if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, + if (TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE, (const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) { if (stop == end) { /* * Entire string parses as an integer, but rejected by * Tcl_Get(Wide)IntFromObj() so we must have overflowed the @@ -1795,11 +1791,11 @@ * Clear out the internal rep, since keeping it would leave * *objPtr in an inconsistent state. */ failat = stop - string1; - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); } } else { /* * No prefix is a valid integer. Fail at beginning. */ @@ -1811,11 +1807,11 @@ /* * We ignore the strictness here, since empty strings are always * well-formed lists. */ - if (TCL_OK == TclListObjLength(NULL, objPtr, &length3)) { + if (TCL_OK == TclListObjLengthM(NULL, objPtr, &length3)) { break; } if (failVarObj != NULL) { /* @@ -1823,15 +1819,15 @@ * fairly expensive. This is adapted from the core of * SetListFromAny(). */ const char *elemStart, *nextElem; - size_t lenRemain; - size_t elemSize; + Tcl_Size lenRemain; + Tcl_Size elemSize; const char *p; - string1 = TclGetStringFromObj(objPtr, &length1); + string1 = Tcl_GetStringFromObj(objPtr, &length1); end = string1 + length1; failat = -1; for (p=string1, lenRemain=length1; lenRemain > 0; p=nextElem, lenRemain=end-nextElem) { if (TCL_ERROR == TclFindElement(NULL, p, lenRemain, @@ -1873,20 +1869,23 @@ chcomp = Tcl_UniCharIsSpace; break; case STR_IS_UPPER: chcomp = Tcl_UniCharIsUpper; break; + case STR_IS_UNICODE: + chcomp = Tcl_UniCharIsUnicode; + break; case STR_IS_WORD: chcomp = Tcl_UniCharIsWordChar; break; case STR_IS_XDIGIT: chcomp = UniCharIsHexDigit; break; } if (chcomp != NULL) { - string1 = TclGetStringFromObj(objPtr, &length1); + string1 = Tcl_GetStringFromObj(objPtr, &length1); if (length1 == 0) { if (strict) { result = 0; } goto str_is_done; @@ -1893,11 +1892,11 @@ } end = string1 + length1; for (; string1 < end; string1 += length2, failat++) { int ucs4; - length2 = TclUtfToUCS4(string1, &ucs4); + length2 = Tcl_UtfToUniChar(string1, &ucs4); if (!chcomp(ucs4)) { result = 0; break; } } @@ -1951,16 +1950,16 @@ *---------------------------------------------------------------------- */ static int StringMapCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t length1, length2, mapElemc, index; + Tcl_Size length1, length2, mapElemc, index; int nocase = 0, mapWithDict = 0, copySource = 0; Tcl_Obj **mapElemv, *sourceObj, *resultPtr; Tcl_UniChar *ustring1, *ustring2, *p, *end; int (*strCmpFn)(const Tcl_UniChar*, const Tcl_UniChar*, size_t); @@ -1968,20 +1967,20 @@ Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? charMap string"); return TCL_ERROR; } if (objc == 4) { - const char *string = TclGetStringFromObj(objv[1], &length2); + const char *string = Tcl_GetStringFromObj(objv[1], &length2); if ((length2 > 1) && strncmp(string, "-nocase", length2) == 0) { nocase = 1; } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": must be -nocase", string)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", - string, NULL); + string, (void *)NULL); return TCL_ERROR; } } /* @@ -1988,12 +1987,13 @@ * This test is tricky, but has to be that way or you get other strange * inconsistencies (see test string-10.20.1 for illustration why!) */ if (!TclHasStringRep(objv[objc-2]) - && TclHasIntRep(objv[objc-2], &tclDictType)) { - int i, done; + && TclHasInternalRep(objv[objc-2], &tclDictType)) { + Tcl_Size i; + int done; Tcl_DictSearch search; /* * We know the type exactly, so all dict operations will succeed for * sure. This shortens this code quite a bit. @@ -2023,12 +2023,12 @@ for (index=2 ; index30% faster on * larger strings. */ - size_t mapLen; + Tcl_Size mapLen; int u2lc; Tcl_UniChar *mapString; - ustring2 = TclGetUnicodeFromObj(mapElemv[0], &length2); + ustring2 = Tcl_GetUnicodeFromObj(mapElemv[0], &length2); p = ustring1; if ((length2 > length1) || (length2 == 0)) { /* * Match string is either longer than input or empty. */ ustring1 = end; } else { - mapString = TclGetUnicodeFromObj(mapElemv[1], &mapLen); + mapString = Tcl_GetUnicodeFromObj(mapElemv[1], &mapLen); u2lc = (nocase ? Tcl_UniCharToLower(*ustring2) : 0); for (; ustring1 < end; ustring1++) { if (((*ustring1 == *ustring2) || (nocase&&Tcl_UniCharToLower(*ustring1)==u2lc)) && (length2==1 || strCmpFn(ustring1, ustring2, length2) == 0)) { if (p != ustring1) { - TclAppendUnicodeToObj(resultPtr, p, ustring1-p); + Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p); p = ustring1 + length2; } else { p += length2; } ustring1 = p - 1; - TclAppendUnicodeToObj(resultPtr, mapString, mapLen); + Tcl_AppendUnicodeToObj(resultPtr, mapString, mapLen); } } } } else { Tcl_UniChar **mapStrings; - size_t *mapLens; + Tcl_Size *mapLens; int *u2lc = 0; /* - * Precompute pointers to the unicode string and length. This saves us + * Precompute pointers to the Unicode string and length. This saves us * repeated function calls later, significantly speeding up the * algorithm. We only need the lowercase first char in the nocase * case. */ mapStrings = (Tcl_UniChar **)TclStackAlloc(interp, mapElemc*sizeof(Tcl_UniChar *)*2); - mapLens = (size_t *)TclStackAlloc(interp, mapElemc * sizeof(size_t) * 2); + mapLens = (Tcl_Size *)TclStackAlloc(interp, mapElemc * sizeof(Tcl_Size) * 2); if (nocase) { u2lc = (int *)TclStackAlloc(interp, mapElemc * sizeof(int)); } for (index = 0; index < mapElemc; index++) { - mapStrings[index] = TclGetUnicodeFromObj(mapElemv[index], + mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index], mapLens+index); if (nocase && ((index % 2) == 0)) { u2lc[index/2] = Tcl_UniCharToLower(*mapStrings[index]); } } @@ -2153,18 +2153,18 @@ ustring2 = mapStrings[index]; length2 = mapLens[index]; if ((length2 > 0) && ((*ustring1 == *ustring2) || (nocase && (Tcl_UniCharToLower(*ustring1) == u2lc[index/2]))) && /* Restrict max compare length. */ - ((size_t)(end-ustring1) >= length2) && ((length2 == 1) || + ((end-ustring1) >= length2) && ((length2 == 1) || !strCmpFn(ustring2, ustring1, length2))) { if (p != ustring1) { /* * Put the skipped chars onto the result first. */ - TclAppendUnicodeToObj(resultPtr, p, ustring1-p); + Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p); p = ustring1 + length2; } else { p += length2; } @@ -2173,14 +2173,14 @@ */ ustring1 = p - 1; /* - * Append the map value to the unicode string. + * Append the map value to the Unicode string. */ - TclAppendUnicodeToObj(resultPtr, + Tcl_AppendUnicodeToObj(resultPtr, mapStrings[index+1], mapLens[index+1]); break; } } } @@ -2193,11 +2193,11 @@ if (p != ustring1) { /* * Put the rest of the unmapped chars onto result. */ - TclAppendUnicodeToObj(resultPtr, p, ustring1 - p); + Tcl_AppendUnicodeToObj(resultPtr, p, ustring1 - p); } Tcl_SetObjResult(interp, resultPtr); done: if (mapWithDict) { TclStackFree(interp, mapElemv); @@ -2226,11 +2226,11 @@ *---------------------------------------------------------------------- */ static int StringMatchCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int nocase = 0; @@ -2239,21 +2239,21 @@ Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? pattern string"); return TCL_ERROR; } if (objc == 4) { - size_t length; - const char *string = TclGetStringFromObj(objv[1], &length); + Tcl_Size length; + const char *string = Tcl_GetStringFromObj(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); + string, (void *)NULL); return TCL_ERROR; } } Tcl_SetObjResult(interp, Tcl_NewBooleanObj( TclStringMatchObj(objv[objc-1], objv[objc-2], nocase))); @@ -2278,16 +2278,16 @@ *---------------------------------------------------------------------- */ static int StringRangeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t first, last, end; + Tcl_Size first, last, end; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "string first last"); return TCL_ERROR; } @@ -2302,17 +2302,11 @@ 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) { + if (last >= 0) { Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last)); } return TCL_OK; } @@ -2334,24 +2328,24 @@ *---------------------------------------------------------------------- */ static int StringReptCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int count; + Tcl_WideInt count; Tcl_Obj *resultPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string count"); return TCL_ERROR; } - if (TclGetIntFromObj(interp, objv[2], &count) != TCL_OK) { + if (TclGetWideIntFromObj(interp, objv[2], &count) != TCL_OK) { return TCL_ERROR; } /* * Check for cases that allow us to skip copying stuff. @@ -2390,16 +2384,16 @@ *---------------------------------------------------------------------- */ static int StringRplcCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t first, last, end; + Tcl_Size first, last, end; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "string first last ?string?"); return TCL_ERROR; } @@ -2415,13 +2409,13 @@ * The following test screens out most empty substrings as candidates for * replacement. When they are detected, no replacement is done, and the * result is the original string. */ - if ((last == TCL_INDEX_NONE) || /* Range ends before start of string */ - (first + 1 > end + 1) || /* Range begins after end of string */ - (last + 1 < first + 1)) { /* Range begins after it starts */ + if ((last < 0) || /* Range ends before start of string */ + (first > end) || /* Range begins after end of string */ + (last < first)) { /* Range begins after it starts */ /* * BUT!!! when (end < 0) -- an empty original string -- we can * have (first <= end < 0 <= last) and an empty string is permitted * to be replaced. */ @@ -2428,21 +2422,24 @@ Tcl_SetObjResult(interp, objv[1]); } else { Tcl_Obj *resultPtr; - if (first == TCL_INDEX_NONE) { + if (first < 0) { first = TCL_INDEX_START; } - if (last + 1 > end + 1) { + if (last > end) { last = end; } resultPtr = TclStringReplace(interp, objv[1], first, last + 1 - first, (objc == 5) ? objv[4] : NULL, TCL_STRING_IN_PLACE); + if (resultPtr == NULL) { + return TCL_ERROR; + } Tcl_SetObjResult(interp, resultPtr); } return TCL_OK; } @@ -2464,11 +2461,11 @@ *---------------------------------------------------------------------- */ static int StringRevCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 2) { @@ -2497,51 +2494,50 @@ *---------------------------------------------------------------------- */ static int StringStartCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int ch; - const char *p, *string; - size_t numChars, length, cur, index; + const Tcl_UniChar *p, *string; + Tcl_Size cur, index, length; Tcl_Obj *obj; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string index"); return TCL_ERROR; } - string = TclGetStringFromObj(objv[1], &length); - numChars = Tcl_NumUtfChars(string, length) - 1; - if (TclGetIntForIndexM(interp, objv[2], numChars, &index) != TCL_OK) { + string = Tcl_GetUnicodeFromObj(objv[1], &length); + if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) { return TCL_ERROR; } - string = TclGetString(objv[1]); - if (index + 1 > numChars + 1) { - index = numChars; + if (index >= length) { + index = length - 1; } cur = 0; - if (index + 1 > 1) { - p = Tcl_UtfAtIndex(string, index); + if (index > 0) { + p = &string[index]; - TclUtfToUCS4(p, &ch); + ch = *p; for (cur = index; cur != TCL_INDEX_NONE; cur--) { int delta = 0; - const char *next; + const Tcl_UniChar *next; if (!Tcl_UniCharIsWordChar(ch)) { break; } - next = TclUtfPrev(p, string); + next = ((p > string) ? (p - 1) : p); do { next += delta; - delta = TclUtfToUCS4(next, &ch); + ch = *next; + delta = 1; } while (next + delta < p); p = next; } if (cur != index) { cur += 1; @@ -2569,48 +2565,46 @@ *---------------------------------------------------------------------- */ static int StringEndCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int ch; - const char *p, *end, *string; - size_t length, numChars, cur, index; + const Tcl_UniChar *p, *end, *string; + Tcl_Size cur, index, length; Tcl_Obj *obj; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string index"); return TCL_ERROR; } - string = TclGetStringFromObj(objv[1], &length); - numChars = Tcl_NumUtfChars(string, length) - 1; - if (TclGetIntForIndexM(interp, objv[2], numChars, &index) != TCL_OK) { + string = Tcl_GetUnicodeFromObj(objv[1], &length); + if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) { return TCL_ERROR; } - string = TclGetStringFromObj(objv[1], &length); - if (index == TCL_INDEX_NONE) { - index = TCL_INDEX_START; + if (index < 0) { + index = 0; } - if (index + 1 <= numChars + 1) { - p = Tcl_UtfAtIndex(string, index); + if (index < length) { + p = &string[index]; end = string+length; for (cur = index; p < end; cur++) { - p += TclUtfToUCS4(p, &ch); + ch = *p++; if (!Tcl_UniCharIsWordChar(ch)) { break; } } if (cur == index) { cur++; } } else { - cur = numChars + 1; + cur = length; } TclNewIndexObj(obj, cur); Tcl_SetObjResult(interp, obj); return TCL_OK; } @@ -2633,11 +2627,11 @@ *---------------------------------------------------------------------- */ static int StringEqualCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { /* @@ -2645,39 +2639,39 @@ * in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and INST_STR_CMP as well as * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...). */ const char *string2; - int i, match, nocase = 0, reqlength = -1; - size_t length; + int i, match, nocase = 0; + Tcl_Size length, 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); + string2 = Tcl_GetStringFromObj(objv[i], &length); if ((length > 1) && !strncmp(string2, "-nocase", length)) { nocase = 1; } else if ((length > 1) && !strncmp(string2, "-length", length)) { if (i+1 >= objc-2) { goto str_cmp_args; } i++; - if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) { + if (TclGetSizeIntFromObj(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); + string2, (void *)NULL); return TCL_ERROR; } } /* @@ -2684,11 +2678,11 @@ * From now on, we only access the two objects at the end of the argument * array. */ objv += objc-2; - match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength); + match = TclStringCmp(objv[0], objv[1], 1, nocase, reqlength); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1)); return TCL_OK; } /* @@ -2709,11 +2703,11 @@ *---------------------------------------------------------------------- */ static int StringCmpCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { /* @@ -2720,13 +2714,14 @@ * Remember to keep code here in some sync with the byte-compiled versions * in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and INST_STR_CMP as well as * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...). */ - int match, nocase, reqlength, status; + int match, nocase, status; + Tcl_Size reqlength = -1; - status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength); + status = StringCmpOpts(interp, objc, objv, &nocase, &reqlength); if (status != TCL_OK) { return status; } objv += objc-2; @@ -2734,19 +2729,19 @@ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(match)); return TCL_OK; } int -TclStringCmpOpts( +StringCmpOpts( Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[], /* Argument objects. */ int *nocase, - int *reqlength) + Tcl_Size *reqlength) { int i; - size_t length; + Tcl_Size length; const char *string; *reqlength = -1; *nocase = 0; if (objc < 3 || objc > 6) { @@ -2755,28 +2750,28 @@ "?-nocase? ?-length int? string1 string2"); return TCL_ERROR; } for (i = 1; i < objc-2; i++) { - string = TclGetStringFromObj(objv[i], &length); + string = Tcl_GetStringFromObj(objv[i], &length); if ((length > 1) && !strncmp(string, "-nocase", length)) { *nocase = 1; } else if ((length > 1) && !strncmp(string, "-length", length)) { if (i+1 >= objc-2) { goto str_cmp_args; } i++; - if (TclGetIntFromObj(interp, objv[i], reqlength) != TCL_OK) { + if (TclGetSizeIntFromObj(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); + string, (void *)NULL); return TCL_ERROR; } } return TCL_OK; } @@ -2798,11 +2793,11 @@ *---------------------------------------------------------------------- */ static int StringCatCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *objResultPtr; @@ -2826,48 +2821,10 @@ } /* *---------------------------------------------------------------------- * - * 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. @@ -2881,11 +2838,11 @@ *---------------------------------------------------------------------- */ static int StringLenCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 2) { @@ -2915,60 +2872,60 @@ *---------------------------------------------------------------------- */ static int StringLowerCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t length1, length2; + Tcl_Size length1, length2; const char *string1; char *string2; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?"); return TCL_ERROR; } - string1 = TclGetStringFromObj(objv[1], &length1); + string1 = Tcl_GetStringFromObj(objv[1], &length1); if (objc == 2) { Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1); length1 = Tcl_UtfToLower(TclGetString(resultPtr)); Tcl_SetObjLength(resultPtr, length1); Tcl_SetObjResult(interp, resultPtr); } else { - size_t first, last; + Tcl_Size first, last; const char *start, *end; Tcl_Obj *resultPtr; length1 = Tcl_NumUtfChars(string1, length1) - 1; if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) { return TCL_ERROR; } - if (first == TCL_INDEX_NONE) { + if (first < 0) { first = 0; } last = first; if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1, &last) != TCL_OK)) { return TCL_ERROR; } - if (last + 1 >= length1 + 1) { + if (last >= length1) { last = length1; } - if (last + 1 < first + 1) { + if (last < first) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } - string1 = TclGetStringFromObj(objv[1], &length1); + string1 = Tcl_GetStringFromObj(objv[1], &length1); start = Tcl_UtfAtIndex(string1, first); end = Tcl_UtfAtIndex(start, last - first + 1); resultPtr = Tcl_NewStringObj(string1, end - string1); string2 = TclGetString(resultPtr) + (start - string1); @@ -3000,60 +2957,60 @@ *---------------------------------------------------------------------- */ static int StringUpperCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t length1, length2; + Tcl_Size length1, length2; const char *string1; char *string2; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?"); return TCL_ERROR; } - string1 = TclGetStringFromObj(objv[1], &length1); + string1 = Tcl_GetStringFromObj(objv[1], &length1); if (objc == 2) { Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1); length1 = Tcl_UtfToUpper(TclGetString(resultPtr)); Tcl_SetObjLength(resultPtr, length1); Tcl_SetObjResult(interp, resultPtr); } else { - size_t first, last; + Tcl_Size first, last; const char *start, *end; Tcl_Obj *resultPtr; length1 = Tcl_NumUtfChars(string1, length1) - 1; if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) { return TCL_ERROR; } - if (first == TCL_INDEX_NONE) { - first = TCL_INDEX_START; + if (first < 0) { + first = 0; } last = first; if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1, &last) != TCL_OK)) { return TCL_ERROR; } - if (last + 1 >= length1 + 1) { + if (last >= length1) { last = length1; } - if (last + 1 < first + 1) { + if (last < first) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } - string1 = TclGetStringFromObj(objv[1], &length1); + string1 = Tcl_GetStringFromObj(objv[1], &length1); start = Tcl_UtfAtIndex(string1, first); end = Tcl_UtfAtIndex(start, last - first + 1); resultPtr = Tcl_NewStringObj(string1, end - string1); string2 = TclGetString(resultPtr) + (start - string1); @@ -3085,60 +3042,60 @@ *---------------------------------------------------------------------- */ static int StringTitleCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - size_t length1, length2; + Tcl_Size length1, length2; const char *string1; char *string2; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?"); return TCL_ERROR; } - string1 = TclGetStringFromObj(objv[1], &length1); + string1 = Tcl_GetStringFromObj(objv[1], &length1); if (objc == 2) { Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1); length1 = Tcl_UtfToTitle(TclGetString(resultPtr)); Tcl_SetObjLength(resultPtr, length1); Tcl_SetObjResult(interp, resultPtr); } else { - size_t first, last; + Tcl_Size first, last; const char *start, *end; Tcl_Obj *resultPtr; length1 = Tcl_NumUtfChars(string1, length1) - 1; if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) { return TCL_ERROR; } - if (first == TCL_INDEX_NONE) { - first = TCL_INDEX_START; + if (first < 0) { + first = 0; } last = first; if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1, &last) != TCL_OK)) { return TCL_ERROR; } - if (last + 1 >= length1 + 1) { + if (last >= length1) { last = length1; } - if (last + 1 < first + 1) { + if (last < first) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } - string1 = TclGetStringFromObj(objv[1], &length1); + string1 = Tcl_GetStringFromObj(objv[1], &length1); start = Tcl_UtfAtIndex(string1, first); end = Tcl_UtfAtIndex(start, last - first + 1); resultPtr = Tcl_NewStringObj(string1, end - string1); string2 = TclGetString(resultPtr) + (start - string1); @@ -3170,28 +3127,28 @@ *---------------------------------------------------------------------- */ static int StringTrimCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *string2; - size_t triml, trimr, length1, length2; + Tcl_Size triml, trimr, length1, length2; if (objc == 3) { - string2 = TclGetStringFromObj(objv[2], &length2); + string2 = Tcl_GetStringFromObj(objv[2], &length2); } else if (objc == 2) { string2 = tclDefaultTrimSet; length2 = strlen(tclDefaultTrimSet); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?"); return TCL_ERROR; } - string1 = TclGetStringFromObj(objv[1], &length1); + string1 = Tcl_GetStringFromObj(objv[1], &length1); triml = TclTrim(string1, length1, string2, length2, &trimr); Tcl_SetObjResult(interp, Tcl_NewStringObj(string1 + triml, length1 - triml - trimr)); @@ -3217,29 +3174,29 @@ *---------------------------------------------------------------------- */ static int StringTrimLCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *string2; int trim; - size_t length1, length2; + Tcl_Size length1, length2; if (objc == 3) { - string2 = TclGetStringFromObj(objv[2], &length2); + string2 = Tcl_GetStringFromObj(objv[2], &length2); } else if (objc == 2) { string2 = tclDefaultTrimSet; length2 = strlen(tclDefaultTrimSet); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?"); return TCL_ERROR; } - string1 = TclGetStringFromObj(objv[1], &length1); + string1 = Tcl_GetStringFromObj(objv[1], &length1); trim = TclTrimLeft(string1, length1, string2, length2); Tcl_SetObjResult(interp, Tcl_NewStringObj(string1+trim, length1-trim)); return TCL_OK; @@ -3264,29 +3221,29 @@ *---------------------------------------------------------------------- */ static int StringTrimRCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *string2; int trim; - size_t length1, length2; + Tcl_Size length1, length2; if (objc == 3) { - string2 = TclGetStringFromObj(objv[2], &length2); + string2 = Tcl_GetStringFromObj(objv[2], &length2); } else if (objc == 2) { string2 = tclDefaultTrimSet; length2 = strlen(tclDefaultTrimSet); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?"); return TCL_ERROR; } - string1 = TclGetStringFromObj(objv[1], &length1); + string1 = Tcl_GetStringFromObj(objv[1], &length1); trim = TclTrimRight(string1, length1, string2, length2); Tcl_SetObjResult(interp, Tcl_NewStringObj(string1, length1-trim)); return TCL_OK; @@ -3318,11 +3275,10 @@ 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}, @@ -3369,11 +3325,11 @@ */ int TclSubstOptions( Tcl_Interp *interp, - int numOpts, + Tcl_Size numOpts, Tcl_Obj *const opts[], int *flagPtr) { static const char *const substOptions[] = { "-nobackslashes", "-nocommands", "-novariables", NULL @@ -3408,21 +3364,21 @@ return TCL_OK; } int Tcl_SubstObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRSubstObjCmd, clientData, objc, objv); } int TclNRSubstObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int flags; @@ -3456,27 +3412,27 @@ *---------------------------------------------------------------------- */ int Tcl_SwitchObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRSwitchObjCmd, clientData, objc, objv); } int TclNRSwitchObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int i, index, mode, foundmode, splitObjs, numMatchesSaved; + int i, mode, foundmode, splitObjs, numMatchesSaved; int noCase; - size_t patternLength, j; + Tcl_Size patternLength, j; const char *pattern; Tcl_Obj *stringObj, *indexVarObj, *matchVarObj; Tcl_Obj *const *savedObjv = objv; Tcl_RegExp regExpr = NULL; Interp *iPtr = (Interp *) interp; @@ -3496,11 +3452,11 @@ "--", 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; @@ -3514,11 +3470,11 @@ } if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum switchOptionsEnum) index) { + switch (index) { /* * General options. */ case OPT_LAST: @@ -3541,11 +3497,11 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": %s option already found", TclGetString(objv[i]), options[mode])); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "DOUBLEOPT", NULL); + "DOUBLEOPT", (void *)NULL); return TCL_ERROR; } foundmode = 1; mode = index; break; @@ -3560,11 +3516,11 @@ if (i >= objc-2) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "missing variable name argument to %s option", "-indexvar")); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "NOVAR", NULL); + "NOVAR", (void *)NULL); return TCL_ERROR; } indexVarObj = objv[i]; numMatchesSaved = -1; break; @@ -3573,11 +3529,11 @@ if (i >= objc-2) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "missing variable name argument to %s option", "-matchvar")); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "NOVAR", NULL); + "NOVAR", (void *)NULL); return TCL_ERROR; } matchVarObj = objv[i]; numMatchesSaved = -1; break; @@ -3592,18 +3548,18 @@ } if (indexVarObj != NULL && mode != OPT_REGEXP) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s option requires -regexp option", "-indexvar")); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "MODERESTRICTION", NULL); + "MODERESTRICTION", (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", NULL); + "MODERESTRICTION", (void *)NULL); return TCL_ERROR; } stringObj = objv[i]; objc -= i + 1; @@ -3620,25 +3576,30 @@ */ splitObjs = 0; if (objc == 1) { Tcl_Obj **listv; + Tcl_Size listc; blist = objv[0]; - if (TclListObjGetElements(interp, objv[0], &objc, &listv) != TCL_OK) { + if (TclListObjLengthM(interp, objv[0], &listc) != TCL_OK) { return TCL_ERROR; } /* * Ensure that the list is non-empty. */ - if (objc < 1) { + if (listc < 1 || listc > INT_MAX) { Tcl_WrongNumArgs(interp, 1, savedObjv, "?-option ...? string {?pattern body ...? ?default body?}"); return TCL_ERROR; } + if (TclListObjGetElementsM(interp, objv[0], &listc, &listv) != TCL_OK) { + return TCL_ERROR; + } + objc = listc; objv = listv; splitObjs = 1; } /* @@ -3649,11 +3610,11 @@ 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); + (void *)NULL); /* * Check if this can be due to a badly placed comment in the switch * block. * @@ -3667,11 +3628,11 @@ Tcl_AppendToObj(Tcl_GetObjResult(interp), ", this may be due to a comment incorrectly" " placed outside of a switch body - see the" " \"switch\" documentation", -1); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", - "BADARM", "COMMENT?", NULL); + "BADARM", "COMMENT?", (void *)NULL); break; } } } @@ -3686,20 +3647,20 @@ if (strcmp(TclGetString(objv[objc-1]), "-") == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "no body specified for pattern \"%s\"", TclGetString(objv[objc-2]))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "BADARM", - "FALLTHROUGH", NULL); + "FALLTHROUGH", (void *)NULL); return TCL_ERROR; } for (i = 0; i < objc; i += 2) { /* * See if the pattern matches the string. */ - pattern = TclGetStringFromObj(objv[i], &patternLength); + pattern = Tcl_GetStringFromObj(objv[i], &patternLength); if ((i == objc - 2) && (*pattern == 'd') && (strcmp(pattern, "default") == 0)) { Tcl_Obj *emptyObj = NULL; @@ -3783,15 +3744,15 @@ for (j=0 ; j<=info.nsubs ; j++) { if (indexVarObj != NULL) { Tcl_Obj *rangeObjAry[2]; - if (info.matches[j].end + 1 > 1) { + if (info.matches[j].end > 0) { TclNewIndexObj(rangeObjAry[0], info.matches[j].start); TclNewIndexObj(rangeObjAry[1], info.matches[j].end-1); } else { - TclNewIndexObj(rangeObjAry[1], TCL_INDEX_NONE); + TclNewIntObj(rangeObjAry[1], -1); rangeObjAry[0] = rangeObjAry[1]; } /* * Never fails; the object is always clean at this point. @@ -3802,12 +3763,16 @@ } if (matchVarObj != NULL) { Tcl_Obj *substringObj; - substringObj = Tcl_GetRange(stringObj, - info.matches[j].start, info.matches[j].end-1); + 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. */ @@ -3880,11 +3845,11 @@ } if (ctxPtr->type == TCL_LOCATION_SOURCE && ctxPtr->line[bidx] >= 0) { int bline = ctxPtr->line[bidx]; - ctxPtr->line = (int *)Tcl_Alloc(objc * sizeof(int)); + ctxPtr->line = (Tcl_Size *)Tcl_Alloc(objc * sizeof(Tcl_Size)); ctxPtr->nline = objc; TclListLines(blist, bline, objc, ctxPtr->line, objv); } else { /* * This is either a dynamic code word, when all elements are @@ -3894,20 +3859,20 @@ * which triggers reversion to the old behavior. */ int k; - ctxPtr->line = (int *)Tcl_Alloc(objc * sizeof(int)); + ctxPtr->line = (Tcl_Size *)Tcl_Alloc(objc * sizeof(Tcl_Size)); ctxPtr->nline = objc; for (k=0; k < objc; k++) { ctxPtr->line[k] = -1; } } } for (j = i + 1; ; j += 2) { - if (j >= (size_t)objc) { + if (j >= objc) { /* * This shouldn't happen since we've checked that the last body is * not a continuation... */ @@ -3921,27 +3886,27 @@ /* * TIP #280: Make invoking context available to switch branch. */ Tcl_NRAddCallback(interp, SwitchPostProc, INT2PTR(splitObjs), ctxPtr, - INT2PTR(pc), (ClientData) pattern); + INT2PTR(pc), (void *)pattern); return TclNREvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j); } static int SwitchPostProc( - ClientData data[], /* Data passed from Tcl_NRAddCallback above */ + void *data[], /* Data passed from Tcl_NRAddCallback above */ Tcl_Interp *interp, /* Tcl interpreter */ int result) /* Result to return*/ { /* Unpack the preserved data */ int splitObjs = PTR2INT(data[0]); CmdFrame *ctxPtr = (CmdFrame *)data[1]; int pc = PTR2INT(data[2]); const char *pattern = (const char *)data[3]; - size_t patternLength = strlen(pattern); + Tcl_Size patternLength = strlen(pattern); /* * Clean up TIP 280 context information */ @@ -3959,16 +3924,16 @@ /* * Generate an error message if necessary. */ if (result == TCL_ERROR) { - unsigned limit = 50; + int limit = 50; int overflow = (patternLength > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%.*s%s\" arm line %d)", - (overflow ? limit : (unsigned)patternLength), pattern, + (int) (overflow ? limit : patternLength), pattern, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } TclStackFree(interp, ctxPtr); return result; } @@ -3990,17 +3955,17 @@ *---------------------------------------------------------------------- */ int Tcl_ThrowObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *options; - int len; + Tcl_Size len; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "type message"); return TCL_ERROR; } @@ -4007,17 +3972,17 @@ /* * The type must be a list of at least length 1. */ - if (Tcl_ListObjLength(interp, objv[1], &len) != TCL_OK) { + if (TclListObjLengthM(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); + (void *)NULL); return TCL_ERROR; } /* * Now prepare the result options dictionary. We use the list API as it is @@ -4052,11 +4017,11 @@ *---------------------------------------------------------------------- */ int Tcl_TimeObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *objPtr; @@ -4107,13 +4072,13 @@ if (count <= 1) { /* * Use int obj since we know time is not fractional. [Bug 1202178] */ - objs[0] = Tcl_NewWideIntObj((count <= 0) ? 0 : (Tcl_WideInt)totalMicroSec); + TclNewIntObj(objs[0], (count <= 0) ? 0 : (Tcl_WideInt)totalMicroSec); } else { - objs[0] = Tcl_NewDoubleObj(totalMicroSec/count); + TclNewDoubleObj(objs[0], totalMicroSec/count); } /* * Construct the result as a list because many programs have always parsed * as such (extracting the first element, typically). @@ -4150,11 +4115,11 @@ *---------------------------------------------------------------------- */ int Tcl_TimeRateObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static double measureOverhead = 0; @@ -4187,21 +4152,21 @@ }; NRE_callback *rootPtr; ByteCode *codePtr = NULL; for (i = 1; i < objc - 1; i++) { - int index; + enum timeRateOptionsEnum index; if (Tcl_GetIndexFromObj(NULL, objv[i], options, "option", TCL_EXACT, &index) != TCL_OK) { break; } if (index == TMRT_LAST) { i++; break; } - switch ((enum timeRateOptionsEnum)index) { + switch (index) { case TMRT_EV_DIRECT: direct = objv[i]; break; case TMRT_OVERHEAD: if (++i >= objc - 1) { @@ -4594,11 +4559,11 @@ */ if (measureOverhead > ((double) usec) / count) { measureOverhead = ((double) usec) / count; } - objs[0] = Tcl_NewDoubleObj(measureOverhead); + TclNewDoubleObj(objs[0], measureOverhead); TclNewLiteralStringObj(objs[1], "\xC2\xB5s/#-overhead"); /* mics */ objs += 2; } val = usec / count; /* microsecs per iteration */ @@ -4696,27 +4661,28 @@ *---------------------------------------------------------------------- */ int Tcl_TryObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRTryObjCmd, clientData, objc, objv); } int TclNRTryObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *bodyObj, *handlersObj, *finallyObj = NULL; - int i, bodyShared, haveHandlers, dummy, code; + int i, bodyShared, haveHandlers, code; + Tcl_Size dummy; static const char *const handlerNames[] = { "finally", "on", "trap", NULL }; enum Handlers { TryFinally, TryOn, TryTrap @@ -4732,38 +4698,38 @@ Tcl_WrongNumArgs(interp, 1, objv, "body ?handler ...? ?finally script?"); return TCL_ERROR; } bodyObj = objv[1]; - handlersObj = Tcl_NewObj(); + TclNewObj(handlersObj); bodyShared = 0; haveHandlers = 0; for (i=2 ; icmdFramePtr, 1); } /* @@ -4904,17 +4870,17 @@ *---------------------------------------------------------------------- */ static int TryPostBody( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Obj *resultObj, *options, *handlersObj, *finallyObj, *cmdObj, **objv; - int i, code, objc; - int numHandlers = 0; + int code, objc; + Tcl_Size i, numHandlers = 0; handlersObj = (Tcl_Obj *)data[0]; finallyObj = (Tcl_Obj *)data[1]; objv = (Tcl_Obj **)data[2]; objc = PTR2INT(data[3]); @@ -4957,16 +4923,16 @@ if (handlersObj != NULL) { int found = 0; Tcl_Obj **handlers, **info; - Tcl_ListObjGetElements(NULL, handlersObj, &numHandlers, &handlers); + TclListObjGetElementsM(NULL, handlersObj, &numHandlers, &handlers); for (i=0 ; i 0) { Tcl_Obj *varName; Tcl_ListObjIndex(NULL, info[3], 0, &varName); if (Tcl_ObjSetVar2(interp, varName, NULL, resultObj, @@ -5120,25 +5086,25 @@ *---------------------------------------------------------------------- */ static int TryPostHandler( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Obj *resultObj, *cmdObj, *options, *handlerKindObj, **objv; Tcl_Obj *finallyObj; - int finally; + int finallyIndex; objv = (Tcl_Obj **)data[0]; options = (Tcl_Obj *)data[1]; handlerKindObj = (Tcl_Obj *)data[2]; - finally = PTR2INT(data[3]); + finallyIndex = PTR2INT(data[3]); cmdObj = objv[0]; - finallyObj = finally ? objv[finally] : 0; + finallyObj = finallyIndex ? objv[finallyIndex] : 0; /* * Check for limits/rewinding, which override normal trapping behaviour. */ @@ -5178,11 +5144,11 @@ Tcl_NRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj, NULL); /* The 'finally' script is always the last argument word. */ return TclNREvalObjEx(interp, finallyObj, 0, iPtr->cmdFramePtr, - finally); + finallyIndex); } /* * Install the correct result/options into the interpreter and clean up * any temporary storage. @@ -5206,11 +5172,11 @@ *---------------------------------------------------------------------- */ static int TryPostFinal( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Obj *resultObj, *options, *cmdObj; @@ -5273,21 +5239,21 @@ *---------------------------------------------------------------------- */ int Tcl_WhileObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRWhileObjCmd, clientData, objc, objv); } int TclNRWhileObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { ForIterData *iterPtr; @@ -5332,22 +5298,22 @@ void TclListLines( Tcl_Obj *listObj, /* Pointer to obj holding a string with list * structure. Assumed to be valid. Assumed to * contain n elements. */ - int line, /* Line the list as a whole starts on. */ - int n, /* #elements in lines */ - int *lines, /* Array of line numbers, to fill. */ + Tcl_Size line, /* Line the list as a whole starts on. */ + Tcl_Size n, /* #elements in lines */ + Tcl_Size *lines, /* Array of line numbers, to fill. */ Tcl_Obj *const *elems) /* The list elems as Tcl_Obj*, in need of * derived continuation data */ { const char *listStr = TclGetString(listObj); const char *listHead = listStr; - int i, length = strlen(listStr); + Tcl_Size i, length = strlen(listStr); const char *element = NULL, *next = NULL; ContLineLoc *clLocPtr = TclContinuationsGet(listObj); - int *clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL); + Tcl_Size *clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL); for (i = 0; i < n; i++) { TclFindElement(NULL, listStr, length, &element, &next, NULL, NULL); TclAdvanceLines(&line, listStr, element); Index: generic/tclCompCmds.c ================================================================== --- generic/tclCompCmds.c +++ generic/tclCompCmds.c @@ -2,14 +2,14 @@ * tclCompCmds.c -- * * This file contains compilation procedures that compile various Tcl * commands into a sequence of instructions ("bytecodes"). * - * Copyright (c) 1997-1998 Sun Microsystems, Inc. - * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. - * Copyright (c) 2002 ActiveState Corporation. - * Copyright (c) 2004-2013 by Donal K. Fellows. + * Copyright © 1997-1998 Sun Microsystems, Inc. + * Copyright © 2001 Kevin B. Kenny. All rights reserved. + * Copyright © 2002 ActiveState Corporation. + * Copyright © 2004-2013 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -120,11 +120,11 @@ int TclCompileAppendCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varTokenPtr, *valueTokenPtr; @@ -228,11 +228,11 @@ /* *---------------------------------------------------------------------- * * TclCompileArray*Cmd -- * - * Functions called to compile "array" sucommands. + * Functions called to compile "array" subcommands. * * Results: * All return TCL_OK for a successful compile, and TCL_ERROR to defer * evaluation to runtime. * @@ -277,18 +277,19 @@ int TclCompileArraySetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varTokenPtr, *dataTokenPtr; int isScalar, localIndex, code = TCL_OK; - int isDataLiteral, isDataValid, isDataEven, len; + int isDataLiteral, isDataValid, isDataEven; + Tcl_Size len; int keyVar, valVar, infoIndex; int fwd, offsetBack, offsetFwd; Tcl_Obj *literalObj; ForeachInfo *infoPtr; @@ -299,11 +300,11 @@ varTokenPtr = TokenAfter(parsePtr->tokenPtr); dataTokenPtr = TokenAfter(varTokenPtr); TclNewObj(literalObj); isDataLiteral = TclWordKnownAtCompileTime(dataTokenPtr, literalObj); isDataValid = (isDataLiteral - && Tcl_ListObjLength(NULL, literalObj, &len) == TCL_OK); + && TclListObjLengthM(NULL, literalObj, &len) == TCL_OK); isDataEven = (isDataValid && (len & 1) == 0); /* * Special case: literal odd-length argument is always an error. */ @@ -390,11 +391,11 @@ keyVar = AnonymousLocal(envPtr); valVar = AnonymousLocal(envPtr); infoPtr = (ForeachInfo *)Tcl_Alloc(offsetof(ForeachInfo, varLists) + sizeof(ForeachVarList *)); infoPtr->numLists = 1; - infoPtr->varLists[0] = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes) + 2 * sizeof(int)); + infoPtr->varLists[0] = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes) + 2 * sizeof(Tcl_Size)); infoPtr->varLists[0]->numVars = 2; infoPtr->varLists[0]->varIndexes[0] = keyVar; infoPtr->varLists[0]->varIndexes[1] = valVar; infoIndex = TclCreateAuxData(infoPtr, &newForeachInfoType, envPtr); @@ -450,11 +451,11 @@ int TclCompileArrayUnsetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); @@ -581,20 +582,20 @@ /* * If syntax does not match what we expect for [catch], do not compile. * Let runtime checks determine if syntax has changed. */ - if ((parsePtr->numWords < 2) || (parsePtr->numWords > 4)) { + if (((int)parsePtr->numWords < 2) || ((int)parsePtr->numWords > 4)) { return TCL_ERROR; } /* * If variables were specified and the catch command is at global level * (not in a procedure), don't compile it inline: the payoff is too small. */ - if ((parsePtr->numWords >= 3) && !EnvHasLVT(envPtr)) { + if (((int)parsePtr->numWords >= 3) && !EnvHasLVT(envPtr)) { return TCL_ERROR; } /* * Make sure the variable names, if any, have no substitutions and just @@ -601,11 +602,11 @@ * refer to local scalars. */ resultIndex = optsIndex = -1; cmdTokenPtr = TokenAfter(parsePtr->tokenPtr); - if (parsePtr->numWords >= 3) { + if ((int)parsePtr->numWords >= 3) { resultNameTokenPtr = TokenAfter(cmdTokenPtr); /* DGP */ resultIndex = LocalScalarFromToken(resultNameTokenPtr, envPtr); if (resultIndex < 0) { return TCL_ERROR; @@ -632,11 +633,11 @@ * substituted body. * Care has to be taken to make sure that substitution happens outside the * catch range so that errors in the substitution are not caught. * [Bug 219184] * The reason for duplicating the script is that EVAL_STK would otherwise - * begin by undeflowing the stack below the mark set by BEGIN_CATCH4. + * begin by underflowing the stack below the mark set by BEGIN_CATCH4. */ range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); if (cmdTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { TclEmitInstInt4( INST_BEGIN_CATCH4, range, envPtr); @@ -814,11 +815,11 @@ int TclCompileClockReadingCmd( TCL_UNUSED(Tcl_Interp *), Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { if (parsePtr->numWords != 1) { return TCL_ERROR; @@ -874,11 +875,11 @@ * Test if all arguments are compile-time known. If they are, we can * implement with a simple push. */ TclNewObj(listObj); - for (i = 1, tokenPtr = parsePtr->tokenPtr; i < parsePtr->numWords; i++) { + for (i = 1, tokenPtr = parsePtr->tokenPtr; i < (int)parsePtr->numWords; i++) { tokenPtr = TokenAfter(tokenPtr); TclNewObj(objPtr); if (!TclWordKnownAtCompileTime(tokenPtr, objPtr)) { Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(listObj); @@ -888,27 +889,26 @@ (void) Tcl_ListObjAppendElement(NULL, listObj, objPtr); } if (listObj != NULL) { Tcl_Obj **objs; const char *bytes; - int len; - size_t slen; + Tcl_Size len, slen; - Tcl_ListObjGetElements(NULL, listObj, &len, &objs); + TclListObjGetElementsM(NULL, listObj, &len, &objs); objPtr = Tcl_ConcatObj(len, objs); Tcl_DecrRefCount(listObj); - bytes = TclGetStringFromObj(objPtr, &slen); + bytes = Tcl_GetStringFromObj(objPtr, &slen); PushLiteral(envPtr, bytes, slen); Tcl_DecrRefCount(objPtr); return TCL_OK; } /* * General case: runtime concat. */ - for (i = 1, tokenPtr = parsePtr->tokenPtr; i < parsePtr->numWords; i++) { + for (i = 1, tokenPtr = parsePtr->tokenPtr; i < (int)parsePtr->numWords; i++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); } TclEmitInstInt4( INST_CONCAT_STK, i-1, envPtr); @@ -981,11 +981,11 @@ /* *---------------------------------------------------------------------- * * TclCompileDict*Cmd -- * - * Functions called to compile "dict" sucommands. + * Functions called to compile "dict" subcommands. * * Results: * All return TCL_OK for a successful compile, and TCL_ERROR to defer * evaluation to runtime. * @@ -1011,11 +1011,11 @@ /* * There must be at least one argument after the command. */ - if (parsePtr->numWords < 4) { + if ((int)parsePtr->numWords < 4) { return TCL_ERROR; } /* * The dictionary variable must be a local scalar that is knowable at @@ -1032,20 +1032,20 @@ /* * Remaining words (key path and value to set) can be handled normally. */ tokenPtr = TokenAfter(varTokenPtr); - for (i=2 ; i< parsePtr->numWords ; i++) { + for (i=2 ; i< (int)parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } /* * Now emit the instruction to do the dict manipulation. */ - TclEmitInstInt4( INST_DICT_SET, parsePtr->numWords-3, envPtr); + TclEmitInstInt4( INST_DICT_SET, (int)parsePtr->numWords-3, envPtr); TclEmitInt4( dictVarIndex, envPtr); TclAdjustStackDepth(-1, envPtr); return TCL_OK; } @@ -1052,11 +1052,11 @@ int TclCompileDictIncrCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varTokenPtr, *keyTokenPtr; @@ -1064,11 +1064,11 @@ /* * There must be at least two arguments after the command. */ - if (parsePtr->numWords < 3 || parsePtr->numWords > 4) { + if ((int)parsePtr->numWords < 3 || (int)parsePtr->numWords > 4) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); keyTokenPtr = TokenAfter(varTokenPtr); @@ -1076,11 +1076,11 @@ * Parse the increment amount, if present. */ if (parsePtr->numWords == 4) { const char *word; - size_t numBytes; + Tcl_Size numBytes; int code; Tcl_Token *incrTokenPtr; Tcl_Obj *intObj; incrTokenPtr = TokenAfter(keyTokenPtr); @@ -1138,24 +1138,24 @@ * There must be at least two arguments after the command (the single-arg * case is legal, but too special and magic for us to deal with here). */ /* TODO: Consider support for compiling expanded args. */ - if (parsePtr->numWords < 3) { + if ((int)parsePtr->numWords < 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); /* * Only compile this because we need INST_DICT_GET anyway. */ - for (i=1 ; inumWords ; i++) { + for (i=1 ; i<(int)parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } - TclEmitInstInt4(INST_DICT_GET, parsePtr->numWords-2, envPtr); + TclEmitInstInt4(INST_DICT_GET, (int)parsePtr->numWords-2, envPtr); TclAdjustStackDepth(-1, envPtr); return TCL_OK; } int @@ -1173,20 +1173,20 @@ /* * There must be at least three arguments after the command. */ /* TODO: Consider support for compiling expanded args. */ - if (parsePtr->numWords < 4) { + if ((int)parsePtr->numWords < 4) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); - for (i=1 ; inumWords ; i++) { + for (i=1 ; i<(int)parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } - TclEmitInstInt4(INST_DICT_GET_DEF, parsePtr->numWords-3, envPtr); + TclEmitInstInt4(INST_DICT_GET_DEF, (int)parsePtr->numWords-3, envPtr); TclAdjustStackDepth(-2, envPtr); return TCL_OK; } int @@ -1205,34 +1205,34 @@ * There must be at least two arguments after the command (the single-arg * case is legal, but too special and magic for us to deal with here). */ /* TODO: Consider support for compiling expanded args. */ - if (parsePtr->numWords < 3) { + if ((int)parsePtr->numWords < 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); /* * Now we do the code generation. */ - for (i=1 ; inumWords ; i++) { + for (i=1 ; i<(int)parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } - TclEmitInstInt4(INST_DICT_EXISTS, parsePtr->numWords-2, envPtr); + TclEmitInstInt4(INST_DICT_EXISTS, (int)parsePtr->numWords-2, envPtr); TclAdjustStackDepth(-1, envPtr); return TCL_OK; } int TclCompileDictUnsetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; @@ -1242,11 +1242,11 @@ * There must be at least one argument after the variable name for us to * compile to bytecode. */ /* TODO: Consider support for compiling expanded args. */ - if (parsePtr->numWords < 3) { + if ((int)parsePtr->numWords < 3) { return TCL_ERROR; } /* * The dictionary variable must be a local scalar that is knowable at @@ -1262,40 +1262,40 @@ /* * Remaining words (the key path) can be handled normally. */ - for (i=2 ; inumWords ; i++) { + for (i=2 ; i<(int)parsePtr->numWords ; i++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); } /* * Now emit the instruction to do the dict manipulation. */ - TclEmitInstInt4( INST_DICT_UNSET, parsePtr->numWords-2, envPtr); + TclEmitInstInt4( INST_DICT_UNSET, (int)parsePtr->numWords-2, envPtr); TclEmitInt4( dictVarIndex, envPtr); return TCL_OK; } int TclCompileDictCreateCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ int worker; /* Temp var for building the value in. */ Tcl_Token *tokenPtr; Tcl_Obj *keyObj, *valueObj, *dictObj; const char *bytes; int i; - size_t len; + Tcl_Size len; if ((parsePtr->numWords & 1) == 0) { return TCL_ERROR; } @@ -1304,11 +1304,11 @@ */ tokenPtr = TokenAfter(parsePtr->tokenPtr); TclNewObj(dictObj); Tcl_IncrRefCount(dictObj); - for (i=1 ; inumWords ; i+=2) { + for (i=1 ; i<(int)parsePtr->numWords ; i+=2) { TclNewObj(keyObj); Tcl_IncrRefCount(keyObj); if (!TclWordKnownAtCompileTime(tokenPtr, keyObj)) { Tcl_DecrRefCount(keyObj); Tcl_DecrRefCount(dictObj); @@ -1331,11 +1331,11 @@ /* * We did! Excellent. The "verifyDict" is to do type forcing. */ - bytes = TclGetStringFromObj(dictObj, &len); + bytes = Tcl_GetStringFromObj(dictObj, &len); PushLiteral(envPtr, bytes, len); TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_DICT_VERIFY, envPtr); Tcl_DecrRefCount(dictObj); return TCL_OK; @@ -1354,11 +1354,11 @@ PushStringLiteral(envPtr, ""); Emit14Inst( INST_STORE_SCALAR, worker, envPtr); TclEmitOpcode( INST_POP, envPtr); tokenPtr = TokenAfter(parsePtr->tokenPtr); - for (i=1 ; inumWords ; i+=2) { + for (i=1 ; i<(int)parsePtr->numWords ; i+=2) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i+1); tokenPtr = TokenAfter(tokenPtr); TclEmitInstInt4( INST_DICT_SET, 1, envPtr); @@ -1375,11 +1375,11 @@ int TclCompileDictMergeCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; @@ -1389,11 +1389,11 @@ * Deal with some special edge cases. Note that in the case with one * argument, the only thing to do is to verify the dict-ness. */ /* TODO: Consider support for compiling expanded args. (less likely) */ - if (parsePtr->numWords < 2) { + if ((int)parsePtr->numWords < 2) { PushStringLiteral(envPtr, ""); return TCL_OK; } else if (parsePtr->numWords == 2) { tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); @@ -1431,11 +1431,11 @@ */ outLoop = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); TclEmitInstInt4( INST_BEGIN_CATCH4, outLoop, envPtr); ExceptionRangeStarts(envPtr, outLoop); - for (i=2 ; inumWords ; i++) { + for (i=2 ; i<(int)parsePtr->numWords ; i++) { /* * Get the dictionary, and merge its pairs into the first dict (using * a small loop). */ @@ -1489,11 +1489,11 @@ int TclCompileDictForCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { return CompileDictEachCmd(interp, parsePtr, cmdPtr, envPtr, TCL_EACH_KEEP_NONE); @@ -1502,11 +1502,11 @@ int TclCompileDictMapCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { return CompileDictEachCmd(interp, parsePtr, cmdPtr, envPtr, TCL_EACH_COLLECT); @@ -1515,11 +1515,11 @@ int CompileDictEachCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int collect) /* Flag == TCL_EACH_COLLECT to collect and * construct a new dictionary with the loop * body result. */ @@ -1526,11 +1526,12 @@ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varsTokenPtr, *dictTokenPtr, *bodyTokenPtr; int keyVarIndex, valueVarIndex, nameChars, loopRange, catchRange; int infoIndex, jumpDisplacement, bodyTargetOffset, emptyTargetOffset; - int numVars, endTargetOffset; + Tcl_Size numVars; + int endTargetOffset; int collectVar = -1; /* Index of temp var holding the result * dict. */ const char **argv; Tcl_DString buffer; @@ -1687,11 +1688,11 @@ endTargetOffset = CurrentOffset(envPtr); TclEmitInstInt1( INST_JUMP1, 0, envPtr); /* * Error handler "finally" clause, which force-terminates the iteration - * and rethrows the error. + * and re-throws the error. */ TclAdjustStackDepth(-1, envPtr); ExceptionRangeTarget(envPtr, catchRange, catchOffset); TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr); @@ -1744,11 +1745,11 @@ int TclCompileDictUpdateCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ int i, dictIndex, numVars, range, infoIndex; @@ -1758,20 +1759,20 @@ /* * There must be at least one argument after the command. */ - if (parsePtr->numWords < 5) { + if ((int)parsePtr->numWords < 5) { return TCL_ERROR; } /* * Parse the command. Expect the following: * dict update ? ...? */ - if ((parsePtr->numWords - 1) & 1) { + if (((int)parsePtr->numWords - 1) & 1) { return TCL_ERROR; } numVars = (parsePtr->numWords - 3) / 2; /* @@ -1790,11 +1791,11 @@ * Assemble the instruction metadata. This is complex enough that it is * represented as auxData; it holds an ordered list of variable indices * that are to be used. */ - duiPtr = (DictUpdateInfo *)Tcl_Alloc(offsetof(DictUpdateInfo, varIndices) + sizeof(int) * numVars); + duiPtr = (DictUpdateInfo *)Tcl_Alloc(offsetof(DictUpdateInfo, varIndices) + sizeof(size_t) * numVars); duiPtr->length = numVars; keyTokenPtrs = (Tcl_Token **)TclStackAlloc(interp, sizeof(Tcl_Token *) * numVars); tokenPtr = TokenAfter(dictVarTokenPtr); for (i=0 ; ivarIndices[i] = LocalScalarFromToken(tokenPtr, envPtr); - if (duiPtr->varIndices[i] < 0) { + if (duiPtr->varIndices[i] == TCL_INDEX_NONE) { goto failedUpdateInfoAssembly; } tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { @@ -1859,11 +1860,11 @@ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); /* * Termination code for non-ok returns: stash the result and return * options in the stack, bring up the key list, finish the update code, - * and finally return with the catched return data + * and finally return with the caught return data */ ExceptionRangeTarget(envPtr, range, catchOffset); TclEmitOpcode( INST_PUSH_RESULT, envPtr); TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr); @@ -1895,26 +1896,26 @@ int TclCompileDictAppendCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; int i, dictVarIndex; /* * There must be at least two argument after the command. And we impose an - * (arbirary) safe limit; anyone exceeding it should stop worrying about + * (arbitrary) safe limit; anyone exceeding it should stop worrying about * speed quite so much. ;-) */ /* TODO: Consider support for compiling expanded args. */ - if (parsePtr->numWords<4 || parsePtr->numWords>100) { + if ((int)parsePtr->numWords<4 || (int)parsePtr->numWords>100) { return TCL_ERROR; } /* * Get the index of the local variable that we will be working with. @@ -1929,16 +1930,16 @@ /* * Produce the string to concatenate onto the dictionary entry. */ tokenPtr = TokenAfter(tokenPtr); - for (i=2 ; inumWords ; i++) { + for (i=2 ; i<(int)parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } - if (parsePtr->numWords > 4) { - TclEmitInstInt1(INST_STR_CONCAT1, parsePtr->numWords-3, envPtr); + if ((int)parsePtr->numWords > 4) { + TclEmitInstInt1(INST_STR_CONCAT1, (int)parsePtr->numWords-3, envPtr); } /* * Do the concatenation. */ @@ -1950,11 +1951,11 @@ int TclCompileDictLappendCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varTokenPtr, *keyTokenPtr, *valueTokenPtr; @@ -1995,11 +1996,11 @@ int TclCompileDictWithCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ int i, range, varNameTmp = -1, pathTmp = -1, keysTmp, gotPath; @@ -2011,11 +2012,11 @@ /* * There must be at least one argument after the command. */ /* TODO: Consider support for compiling expanded args. */ - if (parsePtr->numWords < 3) { + if ((int)parsePtr->numWords < 3) { return TCL_ERROR; } /* * Parse the command (trivially). Expect the following: @@ -2022,11 +2023,11 @@ * dict with ? ...? */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(varTokenPtr); - for (i=3 ; inumWords ; i++) { + for (i=3 ; i<(int)parsePtr->numWords ; i++) { tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } @@ -2050,11 +2051,11 @@ /* * Determine if we're manipulating a dict in a simple local variable. */ - gotPath = (parsePtr->numWords > 3); + gotPath = ((int)parsePtr->numWords > 3); dictVar = LocalScalarFromToken(varTokenPtr, envPtr); /* * Special case: an empty body means we definitely have no need to issue * try-finally style code or to allocate local variable table entries for @@ -2069,15 +2070,15 @@ /* * Case: Path into dict in LVT with empty body. */ tokenPtr = TokenAfter(varTokenPtr); - for (i=2 ; inumWords-1 ; i++) { + for (i=2 ; i<(int)parsePtr->numWords-1 ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } - TclEmitInstInt4(INST_LIST, parsePtr->numWords-3,envPtr); + TclEmitInstInt4(INST_LIST, (int)parsePtr->numWords-3,envPtr); Emit14Inst( INST_LOAD_SCALAR, dictVar, envPtr); TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitOpcode( INST_DICT_EXPAND, envPtr); TclEmitInstInt4(INST_DICT_RECOMBINE_IMM, dictVar, envPtr); } else { @@ -2096,15 +2097,15 @@ /* * Case: Path into dict in non-simple var with empty body. */ tokenPtr = varTokenPtr; - for (i=1 ; inumWords-1 ; i++) { + for (i=1 ; i<(int)parsePtr->numWords-1 ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } - TclEmitInstInt4(INST_LIST, parsePtr->numWords-3,envPtr); + TclEmitInstInt4(INST_LIST, (int)parsePtr->numWords-3,envPtr); TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitOpcode( INST_LOAD_STK, envPtr); TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitOpcode( INST_DICT_EXPAND, envPtr); TclEmitOpcode( INST_DICT_RECOMBINE_STK, envPtr); @@ -2151,15 +2152,15 @@ CompileWord(envPtr, varTokenPtr, interp, 1); Emit14Inst( INST_STORE_SCALAR, varNameTmp, envPtr); } tokenPtr = TokenAfter(varTokenPtr); if (gotPath) { - for (i=2 ; inumWords-1 ; i++) { + for (i=2 ; i<(int)parsePtr->numWords-1 ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } - TclEmitInstInt4( INST_LIST, parsePtr->numWords-3,envPtr); + TclEmitInstInt4( INST_LIST, (int)parsePtr->numWords-3,envPtr); Emit14Inst( INST_STORE_SCALAR, pathTmp, envPtr); TclEmitOpcode( INST_POP, envPtr); } if (dictVar == -1) { TclEmitOpcode( INST_LOAD_STK, envPtr); @@ -2217,11 +2218,11 @@ TclEmitOpcode( INST_PUSH_RESULT, envPtr); TclEmitOpcode( INST_END_CATCH, envPtr); if (dictVar == -1) { Emit14Inst( INST_LOAD_SCALAR, varNameTmp, envPtr); } - if (parsePtr->numWords > 3) { + if ((int)parsePtr->numWords > 3) { Emit14Inst( INST_LOAD_SCALAR, pathTmp, envPtr); } else { PushStringLiteral(envPtr, ""); } Emit14Inst( INST_LOAD_SCALAR, keysTmp, envPtr); @@ -2264,58 +2265,58 @@ * DisassembleDictUpdateInfo: none * *---------------------------------------------------------------------- */ -static ClientData +static void * DupDictUpdateInfo( - ClientData clientData) + void *clientData) { DictUpdateInfo *dui1Ptr, *dui2Ptr; size_t len; dui1Ptr = (DictUpdateInfo *)clientData; - len = offsetof(DictUpdateInfo, varIndices) + sizeof(int) * dui1Ptr->length; + len = offsetof(DictUpdateInfo, varIndices) + sizeof(size_t) * dui1Ptr->length; dui2Ptr = (DictUpdateInfo *)Tcl_Alloc(len); memcpy(dui2Ptr, dui1Ptr, len); return dui2Ptr; } static void FreeDictUpdateInfo( - ClientData clientData) + void *clientData) { Tcl_Free(clientData); } static void PrintDictUpdateInfo( - ClientData clientData, + void *clientData, Tcl_Obj *appendObj, TCL_UNUSED(ByteCode *), - TCL_UNUSED(unsigned int)) + TCL_UNUSED(size_t)) { DictUpdateInfo *duiPtr = (DictUpdateInfo *)clientData; - size_t i; + Tcl_Size i; for (i=0 ; ilength ; i++) { if (i) { Tcl_AppendToObj(appendObj, ", ", -1); } - Tcl_AppendPrintfToObj(appendObj, "%%v%u", duiPtr->varIndices[i]); + Tcl_AppendPrintfToObj(appendObj, "%%v%" TCL_Z_MODIFIER "u", duiPtr->varIndices[i]); } } static void DisassembleDictUpdateInfo( - ClientData clientData, + void *clientData, Tcl_Obj *dictObj, TCL_UNUSED(ByteCode *), - TCL_UNUSED(unsigned int)) + TCL_UNUSED(size_t)) { DictUpdateInfo *duiPtr = (DictUpdateInfo *)clientData; - size_t i; + Tcl_Size i; Tcl_Obj *variables; TclNewObj(variables); for (i=0 ; ilength ; i++) { Tcl_ListObjAppendElement(NULL, variables, @@ -2356,11 +2357,11 @@ /* * General syntax: [error message ?errorInfo? ?errorCode?] */ - if (parsePtr->numWords < 2 || parsePtr->numWords > 4) { + if ((int)parsePtr->numWords < 2 || (int)parsePtr->numWords > 4) { return TCL_ERROR; } /* * Handle the message. @@ -2436,11 +2437,11 @@ envPtr->line = envPtr->extCmdMapPtr->loc[ envPtr->extCmdMapPtr->nuloc-1].line[1]; firstWordPtr = TokenAfter(parsePtr->tokenPtr); - TclCompileExprWords(interp, firstWordPtr, parsePtr->numWords-1, envPtr); + TclCompileExprWords(interp, firstWordPtr, (int)parsePtr->numWords-1, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2611,11 +2612,11 @@ int TclCompileForeachCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { return CompileEachloopCmd(interp, parsePtr, cmdPtr, envPtr, TCL_EACH_KEEP_NONE); @@ -2642,12 +2643,12 @@ int TclCompileLmapCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being - * compiled. */ + Command *cmdPtr, /* Points to the definition of the command + * being compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { return CompileEachloopCmd(interp, parsePtr, cmdPtr, envPtr, TCL_EACH_COLLECT); } @@ -2686,11 +2687,12 @@ * foreach command. Stored in a AuxData * record in the ByteCode. */ Tcl_Token *tokenPtr, *bodyTokenPtr; int jumpBackOffset, infoIndex, range; - int numWords, numLists, i, j, code = TCL_OK; + int numWords, numLists, i, code = TCL_OK; + Tcl_Size j; Tcl_Obj *varListObj = NULL; /* * If the foreach command isn't in a procedure, don't compile it inline: * the payoff is too small. @@ -2698,17 +2700,17 @@ if (procPtr == NULL) { return TCL_ERROR; } - numWords = parsePtr->numWords; + numWords = (int)parsePtr->numWords; if ((numWords < 4) || (numWords%2 != 0)) { return TCL_ERROR; } /* - * Bail out if the body requires substitutions in order to insure correct + * Bail out if the body requires substitutions in order to ensure correct * behaviour. [Bug 219166] */ for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++) { tokenPtr = TokenAfter(tokenPtr); @@ -2738,11 +2740,11 @@ TclNewObj(varListObj); for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++, tokenPtr = TokenAfter(tokenPtr)) { ForeachVarList *varListPtr; - int numVars; + Tcl_Size numVars; if (i%2 != 1) { continue; } @@ -2751,31 +2753,31 @@ * the interpreted version would not. Take care to ensure this does * not happen. [Bug 1671138] */ if (!TclWordKnownAtCompileTime(tokenPtr, varListObj) || - TCL_OK != Tcl_ListObjLength(NULL, varListObj, &numVars) || + TCL_OK != TclListObjLengthM(NULL, varListObj, &numVars) || numVars == 0) { code = TCL_ERROR; goto done; } varListPtr = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes) - + numVars * sizeof(int)); + + numVars * sizeof(varListPtr->varIndexes[0])); varListPtr->numVars = numVars; infoPtr->varLists[i/2] = varListPtr; infoPtr->numLists++; for (j = 0; j < numVars; j++) { Tcl_Obj *varNameObj; const char *bytes; int varIndex; - size_t length; + Tcl_Size length; Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj); - bytes = TclGetStringFromObj(varNameObj, &length); + bytes = Tcl_GetStringFromObj(varNameObj, &length); varIndex = LocalScalar(bytes, length, envPtr); if (varIndex < 0) { code = TCL_ERROR; goto done; } @@ -2885,13 +2887,13 @@ * the new ForeachInfo record. * *---------------------------------------------------------------------- */ -static ClientData +static void * DupForeachInfo( - ClientData clientData) /* The foreach command's compilation auxiliary + void *clientData) /* The foreach command's compilation auxiliary * data to duplicate. */ { ForeachInfo *srcPtr = (ForeachInfo *)clientData; ForeachInfo *dupPtr; ForeachVarList *srcListPtr, *dupListPtr; @@ -2905,11 +2907,11 @@ for (i = 0; i < numLists; i++) { srcListPtr = srcPtr->varLists[i]; numVars = srcListPtr->numVars; dupListPtr = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes) - + numVars * sizeof(int)); + + numVars * sizeof(size_t)); dupListPtr->numVars = numVars; for (j = 0; j < numVars; j++) { dupListPtr->varIndexes[j] = srcListPtr->varIndexes[j]; } dupPtr->varLists[i] = dupListPtr; @@ -2936,17 +2938,16 @@ *---------------------------------------------------------------------- */ static void FreeForeachInfo( - ClientData clientData) /* The foreach command's compilation auxiliary + void *clientData) /* The foreach command's compilation auxiliary * data to free. */ { ForeachInfo *infoPtr = (ForeachInfo *)clientData; ForeachVarList *listPtr; - int numLists = infoPtr->numLists; - int i; + size_t i, numLists = infoPtr->numLists; for (i = 0; i < numLists; i++) { listPtr = infoPtr->varLists[i]; Tcl_Free(listPtr); } @@ -2970,60 +2971,60 @@ *---------------------------------------------------------------------- */ static void PrintForeachInfo( - ClientData clientData, + void *clientData, Tcl_Obj *appendObj, TCL_UNUSED(ByteCode *), - TCL_UNUSED(unsigned int)) + TCL_UNUSED(size_t)) { ForeachInfo *infoPtr = (ForeachInfo *)clientData; ForeachVarList *varsPtr; - int i, j; + Tcl_Size i, j; Tcl_AppendToObj(appendObj, "data=[", -1); for (i=0 ; inumLists ; i++) { if (i) { Tcl_AppendToObj(appendObj, ", ", -1); } - Tcl_AppendPrintfToObj(appendObj, "%%v%u", - (unsigned) (infoPtr->firstValueTemp + i)); + Tcl_AppendPrintfToObj(appendObj, "%%v%" TCL_Z_MODIFIER "u", + (infoPtr->firstValueTemp + i)); } - Tcl_AppendPrintfToObj(appendObj, "], loop=%%v%u", - (unsigned) infoPtr->loopCtTemp); + Tcl_AppendPrintfToObj(appendObj, "], loop=%%v%" TCL_Z_MODIFIER "u", + infoPtr->loopCtTemp); for (i=0 ; inumLists ; i++) { if (i) { Tcl_AppendToObj(appendObj, ",", -1); } - Tcl_AppendPrintfToObj(appendObj, "\n\t\t it%%v%u\t[", - (unsigned) (infoPtr->firstValueTemp + i)); + Tcl_AppendPrintfToObj(appendObj, "\n\t\t it%%v%" TCL_Z_MODIFIER "u\t[", + (infoPtr->firstValueTemp + i)); varsPtr = infoPtr->varLists[i]; for (j=0 ; jnumVars ; j++) { if (j) { Tcl_AppendToObj(appendObj, ", ", -1); } - Tcl_AppendPrintfToObj(appendObj, "%%v%u", - (unsigned) varsPtr->varIndexes[j]); + Tcl_AppendPrintfToObj(appendObj, "%%v%" TCL_Z_MODIFIER "u", + varsPtr->varIndexes[j]); } Tcl_AppendToObj(appendObj, "]", -1); } } static void PrintNewForeachInfo( - ClientData clientData, + void *clientData, Tcl_Obj *appendObj, TCL_UNUSED(ByteCode *), - TCL_UNUSED(unsigned int)) + TCL_UNUSED(size_t)) { ForeachInfo *infoPtr = (ForeachInfo *)clientData; ForeachVarList *varsPtr; - int i, j; + Tcl_Size i, j; - Tcl_AppendPrintfToObj(appendObj, "jumpOffset=%+d, vars=", + Tcl_AppendPrintfToObj(appendObj, "jumpOffset=%+" TCL_Z_MODIFIER "d, vars=", infoPtr->loopCtTemp); for (i=0 ; inumLists ; i++) { if (i) { Tcl_AppendToObj(appendObj, ",", -1); } @@ -3031,27 +3032,27 @@ varsPtr = infoPtr->varLists[i]; for (j=0 ; jnumVars ; j++) { if (j) { Tcl_AppendToObj(appendObj, ",", -1); } - Tcl_AppendPrintfToObj(appendObj, "%%v%u", - (unsigned) varsPtr->varIndexes[j]); + Tcl_AppendPrintfToObj(appendObj, "%%v%" TCL_Z_MODIFIER "u", + varsPtr->varIndexes[j]); } Tcl_AppendToObj(appendObj, "]", -1); } } static void DisassembleForeachInfo( - ClientData clientData, + void *clientData, Tcl_Obj *dictObj, TCL_UNUSED(ByteCode *), - TCL_UNUSED(unsigned int)) + TCL_UNUSED(size_t)) { ForeachInfo *infoPtr = (ForeachInfo *)clientData; ForeachVarList *varsPtr; - int i, j; + Tcl_Size i, j; Tcl_Obj *objPtr, *innerPtr; /* * Data stores. */ @@ -3087,18 +3088,18 @@ Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("assign", -1), objPtr); } static void DisassembleNewForeachInfo( - ClientData clientData, + void *clientData, Tcl_Obj *dictObj, TCL_UNUSED(ByteCode *), - TCL_UNUSED(unsigned int)) + TCL_UNUSED(size_t)) { ForeachInfo *infoPtr = (ForeachInfo *)clientData; ForeachVarList *varsPtr; - int i, j; + Tcl_Size i, j; Tcl_Obj *objPtr, *innerPtr; /* * Jump offset. */ @@ -3153,17 +3154,17 @@ DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; Tcl_Obj **objv, *formatObj, *tmpObj; const char *bytes, *start; int i, j; - size_t len; + Tcl_Size len; /* * Don't handle any guaranteed-error cases. */ - if (parsePtr->numWords < 2) { + if ((int)parsePtr->numWords < 2) { return TCL_ERROR; } /* * Check if the argument words are all compile-time-known literals; that's @@ -3176,12 +3177,12 @@ if (!TclWordKnownAtCompileTime(tokenPtr, formatObj)) { Tcl_DecrRefCount(formatObj); return TCL_ERROR; } - objv = (Tcl_Obj **)Tcl_Alloc((parsePtr->numWords-2) * sizeof(Tcl_Obj *)); - for (i=0 ; i+2 < parsePtr->numWords ; i++) { + objv = (Tcl_Obj **)Tcl_Alloc(((int)parsePtr->numWords-2) * sizeof(Tcl_Obj *)); + for (i=0 ; i+2 < (int)parsePtr->numWords ; i++) { tokenPtr = TokenAfter(tokenPtr); TclNewObj(objv[i]); Tcl_IncrRefCount(objv[i]); if (!TclWordKnownAtCompileTime(tokenPtr, objv[i])) { goto checkForStringConcatCase; @@ -3192,11 +3193,11 @@ * Everything is a literal, so the result is constant too (or an error if * the format is broken). Do the format now. */ tmpObj = Tcl_Format(interp, TclGetString(formatObj), - parsePtr->numWords-2, objv); + (int)parsePtr->numWords-2, objv); for (; --i>=0 ;) { Tcl_DecrRefCount(objv[i]); } Tcl_Free(objv); Tcl_DecrRefCount(formatObj); @@ -3208,11 +3209,11 @@ /* * Not an error, always a constant result, so just push the result as a * literal. Job done. */ - bytes = TclGetStringFromObj(tmpObj, &len); + bytes = Tcl_GetStringFromObj(tmpObj, &len); PushLiteral(envPtr, bytes, len); Tcl_DecrRefCount(tmpObj); return TCL_OK; checkForStringConcatCase: @@ -3253,11 +3254,11 @@ /* * Check if the number of things to concatenate will fit in a byte. */ - if (i+2 != parsePtr->numWords || i > 125) { + if (i+2 != (int)parsePtr->numWords || i > 125) { Tcl_DecrRefCount(formatObj); return TCL_ERROR; } /* @@ -3279,11 +3280,11 @@ if (*bytes == '%') { Tcl_AppendToObj(tmpObj, start, bytes - start); if (*++bytes == '%') { Tcl_AppendToObj(tmpObj, "%", 1); } else { - const char *b = TclGetStringFromObj(tmpObj, &len); + const char *b = Tcl_GetStringFromObj(tmpObj, &len); /* * If there is a non-empty literal from the format string, * push it and reset. */ @@ -3313,11 +3314,11 @@ /* * Handle the case of a trailing literal. */ Tcl_AppendToObj(tmpObj, start, bytes - start); - bytes = TclGetStringFromObj(tmpObj, &len); + bytes = Tcl_GetStringFromObj(tmpObj, &len); if (len > 0) { PushLiteral(envPtr, bytes, len); i++; } Tcl_DecrRefCount(tmpObj); @@ -3343,19 +3344,19 @@ * * 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. + * then return TCL_INDEX_NONE. * * Side effects: - * May add an entery into the table of compiled locals. + * May add an entry into the table of compiled locals. * *---------------------------------------------------------------------- */ -int +size_t TclLocalScalarFromToken( Tcl_Token *tokenPtr, CompileEnv *envPtr) { int isScalar, index; @@ -3365,11 +3366,11 @@ index = -1; } return index; } -int +size_t TclLocalScalar( const char *bytes, size_t numBytes, CompileEnv *envPtr) { Index: generic/tclCompCmdsGR.c ================================================================== --- generic/tclCompCmdsGR.c +++ generic/tclCompCmdsGR.c @@ -3,21 +3,22 @@ * * This file contains compilation procedures that compile various Tcl * commands (beginning with the letters 'g' through 'r') into a sequence * of instructions ("bytecodes"). * - * Copyright (c) 1997-1998 Sun Microsystems, Inc. - * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. - * Copyright (c) 2002 ActiveState Corporation. - * Copyright (c) 2004-2013 by Donal K. Fellows. + * Copyright © 1997-1998 Sun Microsystems, Inc. + * Copyright © 2001 Kevin B. Kenny. All rights reserved. + * Copyright © 2002 ActiveState Corporation. + * Copyright © 2004-2013 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" +#include "tclBrodnik.h" #include /* * Prototypes for procedures defined later in this file: */ @@ -161,30 +162,32 @@ * runtime. * *---------------------------------------------------------------------- */ +TclBrodnikArrayDefine(JumpFixup,MODULE_SCOPE); + int TclCompileIfCmd( 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 */ - JumpFixupArray jumpFalseFixupArray; + BA_JumpFixup *jumpFalseFixup; /* Used to fix the ifFalse jump after each * test when its target PC is determined. */ - JumpFixupArray jumpEndFixupArray; + BA_JumpFixup *jumpEndFixup; /* Used to fix the jump after each "then" body * to the end of the "if" when that PC is * determined. */ + JumpFixup *falseFixupPtr = NULL, *endFixupPtr = NULL; Tcl_Token *tokenPtr, *testTokenPtr; - int jumpIndex = 0; /* Avoid compiler warning. */ - size_t numBytes; - int jumpFalseDist, numWords, wordIdx, j, code; + int jumpFalseDist, numWords, wordIdx, code; + size_t numBytes; const char *word; int realCond = 1; /* Set to 0 for static conditions: * "if 0 {..}" */ int boolVal; /* Value of static condition. */ int compileScripts = 1; @@ -203,12 +206,12 @@ return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); } - TclInitJumpFixupArray(&jumpFalseFixupArray); - TclInitJumpFixupArray(&jumpEndFixupArray); + jumpFalseFixup = BA_JumpFixup_Create(); + jumpEndFixup = BA_JumpFixup_Create(); code = TCL_OK; /* * Each iteration of this loop compiles one "if expr ?then? body" or * "elseif expr ?then? body" clause. @@ -264,17 +267,12 @@ } } else { SetLineInformation(wordIdx); Tcl_ResetResult(interp); TclCompileExprWords(interp, testTokenPtr, 1, envPtr); - if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) { - TclExpandJumpFixupArray(&jumpFalseFixupArray); - } - jumpIndex = jumpFalseFixupArray.next; - jumpFalseFixupArray.next++; - TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, - jumpFalseFixupArray.fixup + jumpIndex); + falseFixupPtr = BA_JumpFixup_Append(jumpFalseFixup); + TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, falseFixupPtr); } code = TCL_OK; } /* @@ -307,21 +305,12 @@ if (compileScripts) { BODY(tokenPtr, wordIdx); } if (realCond) { - /* - * Jump to the end of the "if" command. Both jumpFalseFixupArray - * and jumpEndFixupArray are indexed by "jumpIndex". - */ - - if (jumpEndFixupArray.next >= jumpEndFixupArray.end) { - TclExpandJumpFixupArray(&jumpEndFixupArray); - } - jumpEndFixupArray.next++; - TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, - jumpEndFixupArray.fixup + jumpIndex); + endFixupPtr = BA_JumpFixup_Append(jumpEndFixup); + TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, endFixupPtr); /* * Fix the target of the jumpFalse after the test. Generate a 4 * byte jump if the distance is > 120 bytes. This is conservative, * and ensures that we won't have to replace this jump if we later @@ -328,18 +317,17 @@ * also need to replace the proceeding jump to the end of the "if" * with a 4 byte jump. */ TclAdjustStackDepth(-1, envPtr); - if (TclFixupForwardJumpToHere(envPtr, - jumpFalseFixupArray.fixup + jumpIndex, 120)) { + if (TclFixupForwardJumpToHere(envPtr, falseFixupPtr, 120)) { /* * Adjust the code offset for the proceeding jump to the end * of the "if" command. */ - jumpEndFixupArray.fixup[jumpIndex].codeOffset += 3; + endFixupPtr->codeOffset += 3; } } else if (boolVal) { /* * We were processing an "if 1 {...}"; stop compiling scripts. */ @@ -409,21 +397,22 @@ /* * Fix the unconditional jumps to the end of the "if" command. */ - for (j = jumpEndFixupArray.next; j > 0; j--) { - jumpIndex = (j - 1); /* i.e. process the closest jump first. */ - if (TclFixupForwardJumpToHere(envPtr, - jumpEndFixupArray.fixup + jumpIndex, 127)) { + endFixupPtr = BA_JumpFixup_Detach(jumpEndFixup); + falseFixupPtr = BA_JumpFixup_Detach(jumpFalseFixup); + + while (endFixupPtr) { + if (TclFixupForwardJumpToHere(envPtr, endFixupPtr, 127)) { /* - * Adjust the immediately preceeding "ifFalse" jump. We moved it's + * Adjust the immediately preceding "ifFalse" jump. We moved it's * target (just after this jump) down three bytes. */ unsigned char *ifFalsePc = envPtr->codeStart - + jumpFalseFixupArray.fixup[jumpIndex].codeOffset; + + falseFixupPtr->codeOffset; unsigned char opCode = *ifFalsePc; if (opCode == INST_JUMP_FALSE1) { jumpFalseDist = TclGetInt1AtPtr(ifFalsePc + 1); jumpFalseDist += 3; @@ -434,19 +423,22 @@ TclStoreInt4AtPtr(jumpFalseDist, (ifFalsePc + 1)); } else { Tcl_Panic("TclCompileIfCmd: unexpected opcode \"%d\" updating ifFalse jump", opCode); } } + + endFixupPtr = BA_JumpFixup_Detach(jumpEndFixup); + falseFixupPtr = BA_JumpFixup_Detach(jumpFalseFixup); } /* * Free the jumpFixupArray array if malloc'ed storage was used. */ done: - TclFreeJumpFixupArray(&jumpFalseFixupArray); - TclFreeJumpFixupArray(&jumpEndFixupArray); + BA_JumpFixup_Destroy(jumpFalseFixup); + BA_JumpFixup_Destroy(jumpEndFixup); return code; } /* *---------------------------------------------------------------------- @@ -579,11 +571,11 @@ int TclCompileInfoCommandsCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; @@ -617,12 +609,12 @@ goto notCompilable; } Tcl_DecrRefCount(objPtr); /* - * Confirmed as a literal that will not frighten the horses. Compile. Note - * that the result needs to be list-ified. + * Confirmed as a literal that will not frighten the horses. Compile. + * The result must be made into a list. */ /* TODO: Just push the known value */ CompileWord(envPtr, tokenPtr, interp, 1); TclEmitOpcode( INST_RESOLVE_COMMAND, envPtr); @@ -1354,88 +1346,38 @@ * 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 ; inumWords ; i++) { + 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); } - 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); - } + + /* 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; } /* @@ -1456,120 +1398,38 @@ * 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; + Tcl_Token *tokenPtr; + int i; 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 ; inumWords ; 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); - } - } + + /* 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; } /* @@ -1632,11 +1492,11 @@ /* * Check argument count. */ /* TODO: Consider support for compiling expanded args. */ - if (parsePtr->numWords < 3) { + if ((int)parsePtr->numWords < 3) { /* * Fail at run time, not in compilation. */ return TCL_ERROR; @@ -1656,11 +1516,11 @@ /* * Push the "index" args and the new element value. */ - for (i=2 ; inumWords ; ++i) { + for (i=2 ; i<(int)parsePtr->numWords ; ++i) { varTokenPtr = TokenAfter(varTokenPtr); CompileWord(envPtr, varTokenPtr, interp, i); } /* @@ -1941,11 +1801,11 @@ /* * Only compile [namespace upvar ...]: needs an even number of args, >=4 */ - numWords = parsePtr->numWords; + numWords = (int)parsePtr->numWords; if ((numWords % 2) || (numWords < 4)) { return TCL_ERROR; } /* @@ -1993,11 +1853,11 @@ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr, *opt; int idx; - if (parsePtr->numWords < 2 || parsePtr->numWords > 3) { + if ((int)parsePtr->numWords < 2 || (int)parsePtr->numWords > 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); idx = 1; @@ -2066,11 +1926,11 @@ * supported compile cases are: * regexp ?-nocase? ?--? staticString $var * regexp ?-nocase? ?--? {^staticString$} $var */ - if (parsePtr->numWords < 3) { + if ((int)parsePtr->numWords < 3) { return TCL_ERROR; } simple = 0; nocase = 0; @@ -2081,11 +1941,11 @@ * We only look for -nocase and -- as options. Everything else gets pushed * to runtime execution. This is different than regexp's runtime option * handling, but satisfies our stricter needs. */ - for (i = 1; i < parsePtr->numWords - 2; i++) { + for (i = 1; i < (int)parsePtr->numWords - 2; i++) { varTokenPtr = TokenAfter(varTokenPtr); if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { /* * Not a simple string, so punt to runtime. */ @@ -2096,11 +1956,11 @@ len = varTokenPtr[1].size; if ((len == 2) && (str[0] == '-') && (str[1] == '-')) { sawLast++; i++; break; - } else if ((len > 1) && (strncmp(str,"-nocase", len) == 0)) { + } else if ((len > 1) && (strncmp(str, "-nocase", len) == 0)) { nocase = 1; } else { /* * Not an option we recognize. */ @@ -2107,11 +1967,11 @@ return TCL_ERROR; } } - if ((parsePtr->numWords - i) != 2) { + if (((int)parsePtr->numWords - i) != 2) { /* * We don't support capturing to variables. */ return TCL_ERROR; @@ -2160,19 +2020,19 @@ Tcl_DStringFree(&ds); } } if (!simple) { - CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 2); + CompileWord(envPtr, varTokenPtr, interp, (int)parsePtr->numWords - 2); } /* * Push the string arg. */ varTokenPtr = TokenAfter(varTokenPtr); - CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 1); + CompileWord(envPtr, varTokenPtr, interp, (int)parsePtr->numWords - 1); if (simple) { if (exact && !nocase) { TclEmitOpcode( INST_STR_EQ, envPtr); } else { @@ -2243,13 +2103,13 @@ Tcl_Token *tokenPtr, *stringTokenPtr; Tcl_Obj *patternObj = NULL, *replacementObj = NULL; Tcl_DString pattern; const char *bytes; int exact, quantified, result = TCL_ERROR; - size_t len; + Tcl_Size len; - if (parsePtr->numWords < 5 || parsePtr->numWords > 6) { + if ((int)parsePtr->numWords < 5 || (int)parsePtr->numWords > 6) { return TCL_ERROR; } /* * Parse the "-all", which must be the first argument (other options not @@ -2302,11 +2162,11 @@ /* * Next, higher-level checks. Is the RE a very simple glob? Is the * replacement "simple"? */ - bytes = TclGetStringFromObj(patternObj, &len); + bytes = Tcl_GetStringFromObj(patternObj, &len); if (TclReToGlob(NULL, bytes, len, &pattern, &exact, &quantified) != TCL_OK || exact || quantified) { goto done; } bytes = Tcl_DStringValue(&pattern); @@ -2350,13 +2210,13 @@ */ result = TCL_OK; bytes = Tcl_DStringValue(&pattern) + 1; PushLiteral(envPtr, bytes, len); - bytes = TclGetStringFromObj(replacementObj, &len); + bytes = Tcl_GetStringFromObj(replacementObj, &len); PushLiteral(envPtr, bytes, len); - CompileWord(envPtr, stringTokenPtr, interp, parsePtr->numWords - 2); + CompileWord(envPtr, stringTokenPtr, interp, (int)parsePtr->numWords - 2); TclEmitOpcode( INST_STR_MAP, envPtr); done: Tcl_DStringFree(&pattern); if (patternObj) { @@ -2397,11 +2257,12 @@ DefineLineInformation; /* TIP #280 */ /* * General syntax: [return ?-option value ...? ?result?] * An even number of words means an explicit result argument is present. */ - int level, code, objc, size, status = TCL_OK; + int level, code, objc, status = TCL_OK; + Tcl_Size size; int numWords = parsePtr->numWords; int explicitResult = (0 == (numWords % 2)); int numOptionWords = numWords - 1 - explicitResult; Tcl_Obj *returnOpts, **objv; Tcl_Token *wordTokenPtr = TokenAfter(parsePtr->tokenPtr); @@ -2507,11 +2368,11 @@ while (index >= 0) { ExceptionRange range = envPtr->exceptArrayPtr[index]; if ((range.type == CATCH_EXCEPTION_RANGE) - && (range.catchOffset == -1)) { + && (range.catchOffset == TCL_INDEX_NONE)) { enclosingCatch = 1; break; } index--; } @@ -2607,12 +2468,12 @@ TclCompileSyntaxError( Tcl_Interp *interp, CompileEnv *envPtr) { Tcl_Obj *msg = Tcl_GetObjResult(interp); - size_t numBytes; - const char *bytes = TclGetStringFromObj(msg, &numBytes); + Tcl_Size numBytes; + const char *bytes = Tcl_GetStringFromObj(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))); @@ -2834,11 +2695,11 @@ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Obj *tailPtr; const char *tailName, *p; int n = varTokenPtr->numComponents; - size_t len; + Tcl_Size len; Tcl_Token *lastTokenPtr; int full, localIndex; /* * Determine if the tail is (a) known at compile time, and (b) not an @@ -2866,11 +2727,11 @@ return -1; } Tcl_SetStringObj(tailPtr, lastTokenPtr->start, lastTokenPtr->size); } - tailName = TclGetStringFromObj(tailPtr, &len); + tailName = Tcl_GetStringFromObj(tailPtr, &len); if (len) { if (*(tailName + len - 1) == ')') { /* * Possible array: bail out @@ -2927,15 +2788,15 @@ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; int i; - if (parsePtr->numWords > 255) { + if ((int)parsePtr->numWords > 255) { return TCL_ERROR; } - for (i=0 ; inumWords ; i++) { + for (i=0 ; i<(int)parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt1( INST_TCLOO_NEXT, i, envPtr); return TCL_OK; @@ -2951,15 +2812,15 @@ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; int i; - if (parsePtr->numWords < 2 || parsePtr->numWords > 255) { + if ((int)parsePtr->numWords < 2 || (int)parsePtr->numWords > 255) { return TCL_ERROR; } - for (i=0 ; inumWords ; i++) { + for (i=0 ; i<(int)parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt1( INST_TCLOO_NEXT_CLASS, i, envPtr); return TCL_OK; Index: generic/tclCompCmdsSZ.c ================================================================== --- generic/tclCompCmdsSZ.c +++ generic/tclCompCmdsSZ.c @@ -4,14 +4,14 @@ * This file contains compilation procedures that compile various Tcl * commands (beginning with the letters 's' through 'z', except for * [upvar] and [variable]) into a sequence of instructions ("bytecodes"). * Also includes the operator command compilers. * - * Copyright (c) 1997-1998 Sun Microsystems, Inc. - * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. - * Copyright (c) 2002 ActiveState Corporation. - * Copyright (c) 2004-2010 by Donal K. Fellows. + * Copyright © 1997-1998 Sun Microsystems, Inc. + * Copyright © 2001 Kevin B. Kenny. All rights reserved. + * Copyright © 2002 ActiveState Corporation. + * Copyright © 2004-2010 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -39,16 +39,16 @@ static int CompileUnaryOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, int instruction, CompileEnv *envPtr); static void IssueSwitchChainedTests(Tcl_Interp *interp, CompileEnv *envPtr, int mode, int noCase, - int numWords, Tcl_Token **bodyToken, - int *bodyLines, int **bodyNext); + Tcl_Size numWords, Tcl_Token **bodyToken, + Tcl_Size *bodyLines, Tcl_Size **bodyNext); static void IssueSwitchJumpTable(Tcl_Interp *interp, CompileEnv *envPtr, int numWords, - Tcl_Token **bodyToken, int *bodyLines, - int **bodyContLines); + Tcl_Token **bodyToken, Tcl_Size *bodyLines, + Tcl_Size **bodyContLines); static int IssueTryClausesInstructions(Tcl_Interp *interp, CompileEnv *envPtr, Tcl_Token *bodyToken, int numHandlers, int *matchCodes, Tcl_Obj **matchClauses, int *resultVarIndices, int *optionVarIndices, Tcl_Token **handlerTokens); @@ -250,12 +250,12 @@ folded = obj; } } else { Tcl_DecrRefCount(obj); if (folded) { - size_t len; - const char *bytes = TclGetStringFromObj(folded, &len); + Tcl_Size len; + const char *bytes = Tcl_GetStringFromObj(folded, &len); PushLiteral(envPtr, bytes, len); Tcl_DecrRefCount(folded); folded = NULL; numArgs ++; @@ -268,12 +268,12 @@ } } wordTokenPtr = TokenAfter(wordTokenPtr); } if (folded) { - size_t len; - const char *bytes = TclGetStringFromObj(folded, &len); + Tcl_Size len; + const char *bytes = Tcl_GetStringFromObj(folded, &len); PushLiteral(envPtr, bytes, len); Tcl_DecrRefCount(folded); folded = NULL; numArgs ++; @@ -495,33 +495,33 @@ int TclCompileStringIsCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); static const char *const isClasses[] = { "alnum", "alpha", "ascii", "control", - "boolean", "dict", "digit", "double", "entier", - "false", "graph", "integer", "list", - "lower", "print", "punct", "space", - "true", "upper", "wideinteger", "wordchar", - "xdigit", NULL + "boolean", "dict", "digit", "double", + "entier", "false", "graph", "integer", + "list", "lower", "print", "punct", + "space", "true", "upper", "unicode", + "wideinteger", "wordchar", "xdigit", NULL }; enum isClassesEnum { STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL, - STR_IS_BOOL, STR_IS_DICT, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_ENTIER, - STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, STR_IS_LIST, - STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, STR_IS_SPACE, - STR_IS_TRUE, STR_IS_UPPER, STR_IS_WIDE, STR_IS_WORD, - STR_IS_XDIGIT - }; - int t, range, allowEmpty = 0, end; + STR_IS_BOOL, STR_IS_DICT, STR_IS_DIGIT, STR_IS_DOUBLE, + STR_IS_ENTIER, STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, + STR_IS_LIST, STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, + STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER, STR_IS_UNICODE, + 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; @@ -571,13 +571,13 @@ * 3. Integers * 4. Floats * 5. Lists */ - CompileWord(envPtr, tokenPtr, interp, parsePtr->numWords-1); + CompileWord(envPtr, tokenPtr, interp, (int)parsePtr->numWords-1); - switch ((enum isClassesEnum) t) { + switch (t) { case STR_IS_ALNUM: strClassType = STR_CLASS_ALNUM; goto compileStrClass; case STR_IS_ALPHA: strClassType = STR_CLASS_ALPHA; @@ -607,10 +607,13 @@ strClassType = STR_CLASS_SPACE; goto compileStrClass; case STR_IS_UPPER: strClassType = STR_CLASS_UPPER; goto compileStrClass; + case STR_IS_UNICODE: + strClassType = STR_CLASS_UNICODE; + goto compileStrClass; case STR_IS_WORD: strClassType = STR_CLASS_WORD; goto compileStrClass; case STR_IS_XDIGIT: strClassType = STR_CLASS_XDIGIT; @@ -678,10 +681,12 @@ PUSH( "1"); } FIXJUMP1( over); OP( LNOT); return TCL_OK; + default: + break; } break; case STR_IS_DOUBLE: { int satisfied, isEmpty; @@ -743,10 +748,12 @@ 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); @@ -783,11 +790,11 @@ int TclCompileStringMatchCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; @@ -888,11 +895,11 @@ */ char buf[TCL_INTEGER_SPACE]; size_t len = Tcl_GetCharLength(objPtr); - len = sprintf(buf, "%" TCL_Z_MODIFIER "d", len); + len = snprintf(buf, sizeof(buf), "%" TCL_Z_MODIFIER "u", len); PushLiteral(envPtr, buf, len); } else { SetLineInformation(1); CompileTokens(envPtr, tokenPtr, interp); TclEmitOpcode(INST_STR_LEN, envPtr); @@ -904,20 +911,19 @@ int TclCompileStringMapCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *mapTokenPtr, *stringTokenPtr; Tcl_Obj *mapObj, **objv; const char *bytes; - int len; - size_t slen; + Tcl_Size len, slen; /* * We only handle the case: * * string map {foo bar} $thing @@ -935,11 +941,11 @@ TclNewObj(mapObj); Tcl_IncrRefCount(mapObj); if (!TclWordKnownAtCompileTime(mapTokenPtr, mapObj)) { Tcl_DecrRefCount(mapObj); return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); - } else if (Tcl_ListObjGetElements(NULL, mapObj, &len, &objv) != TCL_OK) { + } else if (TclListObjGetElementsM(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); @@ -949,16 +955,16 @@ * Now issue the opcodes. Note that in the case that we know that the * first word is an empty word, we don't issue the map at all. That is the * correct semantics for mapping. */ - bytes = TclGetStringFromObj(objv[0], &slen); + bytes = Tcl_GetStringFromObj(objv[0], &slen); if (slen == 0) { CompileWord(envPtr, stringTokenPtr, interp, 2); } else { PushLiteral(envPtr, bytes, slen); - bytes = TclGetStringFromObj(objv[1], &slen); + bytes = Tcl_GetStringFromObj(objv[1], &slen); PushLiteral(envPtr, bytes, slen); CompileWord(envPtr, stringTokenPtr, interp, 2); OP(STR_MAP); } Tcl_DecrRefCount(mapObj); @@ -1050,11 +1056,11 @@ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr, *valueTokenPtr; int first, last; - if (parsePtr->numWords < 4 || parsePtr->numWords > 5) { + if ((int)parsePtr->numWords < 4 || (int)parsePtr->numWords > 5) { return TCL_ERROR; } /* Bytecode to compute/push string argument being replaced */ valueTokenPtr = TokenAfter(parsePtr->tokenPtr); @@ -1322,11 +1328,11 @@ int TclCompileStringToUpperCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; @@ -1344,11 +1350,11 @@ int TclCompileStringToLowerCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; @@ -1366,11 +1372,11 @@ int TclCompileStringToTitleCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; @@ -1415,10 +1421,11 @@ {"punct", Tcl_UniCharIsPunct}, {"space", Tcl_UniCharIsSpace}, {"upper", Tcl_UniCharIsUpper}, {"word", Tcl_UniCharIsWordChar}, {"xdigit", UniCharIsHexDigit}, + {"unicode", Tcl_UniCharIsUnicode}, {"", NULL} }; /* *---------------------------------------------------------------------- @@ -1508,24 +1515,22 @@ void TclSubstCompile( Tcl_Interp *interp, const char *bytes, - size_t numBytes, + Tcl_Size numBytes, int flags, - int line, + Tcl_Size line, CompileEnv *envPtr) { Tcl_Token *endTokenPtr, *tokenPtr; - int breakOffset = 0, count = 0, bline = line; + int breakOffset = 0, count = 0; + Tcl_Size bline = line; Tcl_Parse parse; - Tcl_InterpState state = NULL; - TclSubstParse(interp, bytes, numBytes, flags, &parse, &state); - if (state != NULL) { - Tcl_ResetResult(interp); - } + parse.commandStart = NULL; + TclSubstParse(interp, bytes, numBytes, flags, &parse); /* * Tricky point! 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 an INST_STR_CONCAT1 or INST_DONE without enough @@ -1539,11 +1544,11 @@ count++; } for (endTokenPtr = tokenPtr + parse.numTokens; tokenPtr < endTokenPtr; tokenPtr = TokenAfter(tokenPtr)) { - size_t length; + Tcl_Size length; int literal, catchRange, breakJump; char buf[4] = ""; JumpFixup startFixup, okFixup, returnFixup, breakFixup; JumpFixup continueFixup, otherFixup, endFixup; @@ -1571,15 +1576,15 @@ * code. Note that the first component of TCL_TOKEN_VARIABLE is * always TCL_TOKEN_TEXT... */ if (tokenPtr->numComponents > 1) { - size_t i; + Tcl_Size i; int foundCommand = 0; for (i=2 ; i<=tokenPtr->numComponents ; i++) { - if (tokenPtr[i].type == TCL_TOKEN_COMMAND) { + if (tokenPtr[i].type == TCL_TOKEN_SCRIPT_SUBST) { foundCommand = 1; break; } } if (foundCommand) { @@ -1622,19 +1627,22 @@ catchRange = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); OP4( BEGIN_CATCH4, catchRange); ExceptionRangeStarts(envPtr, catchRange); switch (tokenPtr->type) { - case TCL_TOKEN_COMMAND: - TclCompileScript(interp, tokenPtr->start+1, tokenPtr->size-2, + case TCL_TOKEN_SCRIPT_SUBST: + TclCompileTokens(interp, tokenPtr, tokenPtr->numComponents + 1, envPtr); count++; break; case TCL_TOKEN_VARIABLE: TclCompileVarSubst(interp, tokenPtr, envPtr); count++; break; + case TCL_TOKEN_ERROR: + TclCompileTokens(interp, tokenPtr, 1, envPtr); + break; default: Tcl_Panic("unexpected token type in TclCompileSubstCmd: %d", tokenPtr->type); } @@ -1736,19 +1744,25 @@ count -= 254; } if (count > 1) { OP1( STR_CONCAT1, count); } + + if (endTokenPtr[-1].type == TCL_TOKEN_ERROR) { + /* + * Bytecode execution will only reach this point after a + * TCL_RETURN, TCL_CONTINUE, or other exception is raised. + * In those cases, we're at a +1 status in stack depth, so + * we POP before continuing with instructions to raise the + * syntax error message. + */ + OP( POP); + TclCompileTokens(interp, endTokenPtr - 1, 1, envPtr); + } Tcl_FreeParse(&parse); - if (state != NULL) { - Tcl_RestoreInterpState(interp, state); - TclCompileSyntaxError(interp, envPtr); - TclAdjustStackDepth(-1, envPtr); - } - /* Final target of the multi-jump from all BREAKs */ if (breakOffset > 0) { TclUpdateInstInt4AtPc(INST_JUMP4, CurrentOffset(envPtr) - breakOffset, envPtr->codeStart + breakOffset); } @@ -1790,18 +1804,18 @@ enum {Switch_Exact, Switch_Glob, Switch_Regexp} mode; /* What kind of switch are we doing? */ Tcl_Token *bodyTokenArray; /* Array of real pattern list items. */ Tcl_Token **bodyToken; /* Array of pointers to pattern list items. */ - int *bodyLines; /* Array of line numbers for body list + Tcl_Size *bodyLines; /* Array of line numbers for body list * items. */ - int **bodyContLines; /* Array of continuation line info. */ + Tcl_Size **bodyContLines; /* Array of continuation line info. */ int noCase; /* Has the -nocase flag been given? */ int foundMode = 0; /* Have we seen a mode flag yet? */ int i, valueIndex; int result = TCL_ERROR; - int *clNext = envPtr->clNext; + Tcl_Size *clNext = envPtr->clNext; /* * Only handle the following versions: * switch ?--? word {pattern body ...} * switch -exact ?--? word {pattern body ...} @@ -1935,12 +1949,12 @@ * available at this point, this is pretty easy. */ if (numWords == 1) { const char *bytes; - size_t maxLen, numBytes; - int bline; /* TIP #280: line of the pattern/action list, + Tcl_Size maxLen, numBytes; + Tcl_Size bline; /* TIP #280: line of the pattern/action list, * and start of list for when tracking the * location. This list comes immediately after * the value we switch on. */ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { @@ -1954,12 +1968,12 @@ if (maxLen < 2) { return TCL_ERROR; } bodyTokenArray = (Tcl_Token *)Tcl_Alloc(sizeof(Tcl_Token) * maxLen); bodyToken = (Tcl_Token **)Tcl_Alloc(sizeof(Tcl_Token *) * maxLen); - bodyLines = (int *)Tcl_Alloc(sizeof(int) * maxLen); - bodyContLines = (int **)Tcl_Alloc(sizeof(int*) * maxLen); + bodyLines = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size) * maxLen); + bodyContLines = (Tcl_Size **)Tcl_Alloc(sizeof(Tcl_Size*) * maxLen); bline = mapPtr->loc[eclIndex].line[valueIndex+1]; numWords = 0; while (numBytes > 0) { @@ -2015,12 +2029,12 @@ /* * Multi-word definition of patterns & actions. */ bodyToken = (Tcl_Token **)Tcl_Alloc(sizeof(Tcl_Token *) * numWords); - bodyLines = (int *)Tcl_Alloc(sizeof(int) * numWords); - bodyContLines = (int **)Tcl_Alloc(sizeof(int*) * numWords); + bodyLines = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size) * numWords); + bodyContLines = (Tcl_Size **)Tcl_Alloc(sizeof(Tcl_Size*) * numWords); bodyTokenArray = NULL; for (i=0 ; ihashTable); Tcl_Free(jtPtr); } static void PrintJumptableInfo( - ClientData clientData, + void *clientData, Tcl_Obj *appendObj, TCL_UNUSED(ByteCode *), - unsigned int pcOffset) + size_t pcOffset) { JumptableInfo *jtPtr = (JumptableInfo *)clientData; Tcl_HashEntry *hPtr; Tcl_HashSearch search; const char *keyPtr; - int offset, i = 0; + size_t offset, i = 0; hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search); for (; hPtr ; hPtr = Tcl_NextHashEntry(&search)) { keyPtr = (const char *)Tcl_GetHashKey(&jtPtr->hashTable, hPtr); offset = PTR2INT(Tcl_GetHashValue(hPtr)); @@ -2599,21 +2613,21 @@ Tcl_AppendToObj(appendObj, ", ", -1); if (i%4==0) { Tcl_AppendToObj(appendObj, "\n\t\t", -1); } } - Tcl_AppendPrintfToObj(appendObj, "\"%s\"->pc %d", + Tcl_AppendPrintfToObj(appendObj, "\"%s\"->pc %" TCL_Z_MODIFIER "u", keyPtr, pcOffset + offset); } } static void DisassembleJumptableInfo( - ClientData clientData, + void *clientData, Tcl_Obj *dictObj, TCL_UNUSED(ByteCode *), - TCL_UNUSED(unsigned int)) + TCL_UNUSED(size_t)) { JumptableInfo *jtPtr = (JumptableInfo *)clientData; Tcl_Obj *mapping; Tcl_HashEntry *hPtr; Tcl_HashSearch search; @@ -2659,23 +2673,23 @@ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; int i; - if (parsePtr->numWords < 2 || parsePtr->numWords > 256 + if (parsePtr->numWords < 2 || parsePtr->numWords >= 256 || envPtr->procPtr == NULL) { return TCL_ERROR; } /* make room for the nsObjPtr */ /* TODO: Doesn't this have to be a known value? */ CompileWord(envPtr, tokenPtr, interp, 0); - for (i=1 ; inumWords ; i++) { + for (i=1 ; i<(int)parsePtr->numWords ; i++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); } - TclEmitInstInt1( INST_TAILCALL, parsePtr->numWords, envPtr); + TclEmitInstInt1( INST_TAILCALL, (int)parsePtr->numWords, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2705,11 +2719,12 @@ { DefineLineInformation; /* TIP #280 */ int numWords = parsePtr->numWords; Tcl_Token *codeToken, *msgToken; Tcl_Obj *objPtr; - int codeKnown, codeIsList, codeIsValid, len; + int codeKnown, codeIsList, codeIsValid; + Tcl_Size len; if (numWords != 3) { return TCL_ERROR; } codeToken = TokenAfter(parsePtr->tokenPtr); @@ -2729,11 +2744,11 @@ PUSH( "-errorcode"); } CompileWord(envPtr, msgToken, interp, 2); codeIsList = codeKnown && (TCL_OK == - Tcl_ListObjLength(interp, objPtr, &len)); + TclListObjLengthM(interp, objPtr, &len)); codeIsValid = codeIsList && (len != 0); if (codeIsValid) { Tcl_Obj *errPtr, *dictPtr; @@ -2846,11 +2861,11 @@ resultVarIndices = (int *)TclStackAlloc(interp, sizeof(int) * numHandlers); optionVarIndices = (int *)TclStackAlloc(interp, sizeof(int) * numHandlers); for (i=0 ; itype != TCL_TOKEN_SIMPLE_WORD) { goto failedToCompile; } if (tokenPtr[1].size == 4 @@ -2862,11 +2877,11 @@ matchCodes[i] = TCL_ERROR; tokenPtr = TokenAfter(tokenPtr); TclNewObj(tmpObj); Tcl_IncrRefCount(tmpObj); if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj) - || Tcl_ListObjLength(NULL, tmpObj, &objc) != TCL_OK + || TclListObjLengthM(NULL, tmpObj, &objc) != TCL_OK || (objc == 0)) { TclDecrRefCount(tmpObj); goto failedToCompile; } Tcl_ListObjReplace(NULL, tmpObj, 0, 0, 0, NULL); @@ -2905,18 +2920,18 @@ Tcl_IncrRefCount(tmpObj); if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) { TclDecrRefCount(tmpObj); goto failedToCompile; } - if (Tcl_ListObjGetElements(NULL, tmpObj, &objc, &objv) != TCL_OK + if (TclListObjGetElementsM(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); + Tcl_Size len; + const char *varname = Tcl_GetStringFromObj(objv[0], &len); resultVarIndices[i] = LocalScalar(varname, len, envPtr); if (resultVarIndices[i] < 0) { TclDecrRefCount(tmpObj); goto failedToCompile; @@ -2923,12 +2938,12 @@ } } else { resultVarIndices[i] = -1; } if (objc == 2) { - size_t len; - const char *varname = TclGetStringFromObj(objv[1], &len); + Tcl_Size len; + const char *varname = Tcl_GetStringFromObj(objv[1], &len); optionVarIndices[i] = LocalScalar(varname, len, envPtr); if (optionVarIndices[i] < 0) { TclDecrRefCount(tmpObj); goto failedToCompile; @@ -2970,10 +2985,13 @@ 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; } /* @@ -3041,12 +3059,12 @@ int *optionVars, Tcl_Token **handlerTokens) { DefineLineInformation; /* TIP #280 */ int range, resultVar, optionsVar; - int i, j, len, forwardsNeedFixing = 0, trapZero = 0, afterBody = 0; - size_t slen; + int i, j, forwardsNeedFixing = 0, trapZero = 0, afterBody = 0; + Tcl_Size slen, len; int *addrsToFix, *forwardsToFix, notCodeJumpSource, notECJumpSource; int *noError; char buf[TCL_INTEGER_SPACE]; resultVar = AnonymousLocal(envPtr); @@ -3110,18 +3128,18 @@ forwardsToFix = (int *)TclStackAlloc(interp, sizeof(int)*numHandlers); noError = (int *)TclStackAlloc(interp, sizeof(int)*numHandlers); for (i=0 ; itokenPtr ; inumWords ; i++) { + for (i=1,varTokenPtr=parsePtr->tokenPtr ; i<(int)parsePtr->numWords ; i++) { Tcl_Obj *leadingWord; TclNewObj(leadingWord); varTokenPtr = TokenAfter(varTokenPtr); if (!TclWordKnownAtCompileTime(varTokenPtr, leadingWord)) { @@ -3666,13 +3684,13 @@ } return TCL_ERROR; } if (varCount == 0) { const char *bytes; - size_t len; + Tcl_Size len; - bytes = TclGetStringFromObj(leadingWord, &len); + bytes = Tcl_GetStringFromObj(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++; @@ -3691,11 +3709,11 @@ varTokenPtr = TokenAfter(parsePtr->tokenPtr); for (i=0; inumWords ; i++) { + for (i=1+haveFlags ; i<(int)parsePtr->numWords ; i++) { /* * Decide if we can use a frame slot for the var/array name or if we * need to emit code to compute and push the name at runtime. We use a * frame slot (entry in the array of local vars) if we are compiling a * procedure body and if the name is simple text that does not include @@ -3976,16 +3994,16 @@ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); int i; - if (parsePtr->numWords < 2) { + if ((int)parsePtr->numWords < 2) { return TCL_ERROR; } OP( NS_CURRENT); - for (i = 1 ; i < parsePtr->numWords ; i++) { + for (i = 1 ; i < (int)parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } OP4( LIST, i); OP( YIELD_TO_INVOKE); @@ -4059,11 +4077,11 @@ int instruction, CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; - int words; + Tcl_Size words; /* TODO: Consider support for compiling expanded args. */ for (words=1 ; wordsnumWords ; words++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, words); @@ -4073,11 +4091,11 @@ words++; } if (words > 3) { /* * Reverse order of arguments to get precise agreement with [expr] in - * calcuations, including roundoff errors. + * calculations, including roundoff errors. */ OP4( REVERSE, words-1); } while (--words > 1) { @@ -4146,11 +4164,11 @@ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; /* TODO: Consider support for compiling expanded args. */ - if (parsePtr->numWords < 3) { + if ((int)parsePtr->numWords < 3) { PUSH("1"); } else if (parsePtr->numWords == 3) { tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); tokenPtr = TokenAfter(tokenPtr); @@ -4162,11 +4180,11 @@ */ return TCL_ERROR; } else { int tmpIndex = AnonymousLocal(envPtr); - int words; + Tcl_Size words; tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); @@ -4298,11 +4316,11 @@ TCL_UNUSED(Command *), CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; - int words; + Tcl_Size words; /* * This one has its own implementation because the ** operator is the only * one with right associativity. */ @@ -4499,11 +4517,11 @@ TCL_UNUSED(Command *), CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; - int words; + Tcl_Size words; /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords == 1) { /* * Fallback to direct eval to report syntax error. @@ -4524,11 +4542,11 @@ return TCL_OK; } /* * Reverse order of arguments to get precise agreement with [expr] in - * calcuations, including roundoff errors. + * calculations, including roundoff errors. */ TclEmitInstInt4(INST_REVERSE, words-1, envPtr); while (--words > 1) { TclEmitInstInt4(INST_REVERSE, 2, envPtr); @@ -4544,11 +4562,11 @@ TCL_UNUSED(Command *), CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; - int words; + Tcl_Size words; /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords == 1) { /* * Fallback to direct eval to report syntax error. @@ -4568,11 +4586,11 @@ return TCL_OK; } /* * Reverse order of arguments to get precise agreement with [expr] in - * calcuations, including roundoff errors. + * calculations, including roundoff errors. */ TclEmitInstInt4(INST_REVERSE, words-1, envPtr); while (--words > 1) { TclEmitInstInt4(INST_REVERSE, 2, envPtr); Index: generic/tclCompExpr.c ================================================================== --- generic/tclCompExpr.c +++ generic/tclCompExpr.c @@ -94,11 +94,11 @@ * hold the p.prev field which chains together a stack of incomplete trees * awaiting their right operands. * * The lexeme field is filled in with the lexeme of the operator that is * returned by the ParseLexeme() routine. Only lexemes for unary and binary - * operators get stored in an OpNode. Other lexmes get different treatement. + * operators get stored in an OpNode. Other lexmes get different treatment. * * The precedence field provides a place to store the precedence of the * operator, so it need not be looked up again and again. * * The mark field is use to control the traversal of the tree, so that it can @@ -155,17 +155,19 @@ #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 +#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 */ @@ -460,11 +462,11 @@ INVALID /* CAN */, INVALID /* EM */, INVALID /* SUB */, INVALID /* ESC */, INVALID /* FS */, INVALID /* GS */, INVALID /* RS */, INVALID /* US */, INVALID /* SPACE */, 0 /* ! or != */, - QUOTED /* " */, INVALID /* # */, + QUOTED /* " */, 0 /* # */, VARIABLE /* $ */, MOD /* % */, 0 /* & or && */, INVALID /* ' */, OPEN_PAREN /* ( */, CLOSE_PAREN /* ) */, 0 /* * or ** */, PLUS /* + */, COMMA /* , */, MINUS /* - */, @@ -485,42 +487,28 @@ BRACED /* { */, 0 /* | or || */, INVALID /* } */, BIT_NOT /* ~ */, INVALID /* DEL */ }; -/* - * The JumpList struct is used to create a stack of data needed for the - * TclEmitForwardJump() and TclFixupForwardJump() calls that are performed - * when compiling the short-circuiting operators QUESTION/COLON, AND, and OR. - * Keeping a stack permits the CompileExprTree() routine to be non-recursive. - */ - -typedef struct JumpList { - JumpFixup jump; /* Pass this argument to matching calls of - * TclEmitForwardJump() and - * TclFixupForwardJump(). */ - struct JumpList *next; /* Point to next item on the stack */ -} JumpList; - /* * Declarations for local functions to this file: */ static void CompileExprTree(Tcl_Interp *interp, OpNode *nodes, int index, Tcl_Obj *const **litObjvPtr, Tcl_Obj *const *funcObjv, Tcl_Token *tokenPtr, CompileEnv *envPtr, int optimize); -static void ConvertTreeToTokens(const char *start, size_t numBytes, +static void ConvertTreeToTokens(const char *start, Tcl_Size numBytes, OpNode *nodes, Tcl_Token *tokenPtr, Tcl_Parse *parsePtr); static int ExecConstantExprTree(Tcl_Interp *interp, OpNode *nodes, int index, Tcl_Obj * const **litObjvPtr); static int ParseExpr(Tcl_Interp *interp, const char *start, - size_t numBytes, OpNode **opTreePtr, + Tcl_Size numBytes, OpNode **opTreePtr, Tcl_Obj *litList, Tcl_Obj *funcList, Tcl_Parse *parsePtr, int parseOnly); -static size_t ParseLexeme(const char *start, size_t numBytes, +static Tcl_Size ParseLexeme(const char *start, Tcl_Size numBytes, unsigned char *lexemePtr, Tcl_Obj **literalPtr); /* *---------------------------------------------------------------------- * @@ -554,11 +542,11 @@ static int ParseExpr( Tcl_Interp *interp, /* Used for error reporting. */ const char *start, /* Start of source string to parse. */ - size_t numBytes, /* Number of bytes in string. */ + Tcl_Size numBytes, /* Number of bytes in string. */ OpNode **opTreePtr, /* Points to space where a pointer to the * allocated OpNode tree should go. */ Tcl_Obj *litList, /* List to append literals to. */ Tcl_Obj *funcList, /* List to append function names to. */ Tcl_Parse *parsePtr, /* Structure to fill with tokens representing @@ -572,16 +560,16 @@ { OpNode *nodes = NULL; /* Pointer to the OpNode storage array where * we build the parse tree. */ unsigned int nodesAvailable = 64; /* Initial size of the storage array. This * value establishes a minimum tree memory - * cost of only about 1 kibyte, and is large + * cost of only about 1 kilobyte, and is large * enough for most expressions to parse with * no need for array growth and * reallocation. */ unsigned int nodesUsed = 0; /* Number of OpNodes filled. */ - size_t scanned = 0; /* Capture number of byte scanned by parsing + Tcl_Size scanned = 0; /* Capture number of byte scanned by parsing * routines. */ int lastParsed; /* Stores info about what the lexeme parsed * the previous pass through the parsing loop * was. If it was an operator, lastParsed is * the index of the OpNode for that operator. @@ -621,11 +609,11 @@ * into the string being parsed to aid in * pinpointing the location of the syntax * error in the expression. */ int insertMark = 0; /* A boolean controlling whether the "mark" * should be inserted. */ - const unsigned limit = 25; /* Portions of the error message are + const int limit = 25; /* Portions of the error message are * constructed out of substrings of the * original expression. In order to keep the * error message readable, we impose this * limit on the substring size we extract. */ @@ -672,13 +660,14 @@ if (nodesUsed >= nodesAvailable) { unsigned int size = nodesUsed * 2; OpNode *newPtr = NULL; do { - if (size <= UINT_MAX/sizeof(OpNode)) { - newPtr = (OpNode *)Tcl_AttemptRealloc(nodes, size * sizeof(OpNode)); - } + if (size <= UINT_MAX/sizeof(OpNode)) { + newPtr = (OpNode *) Tcl_AttemptRealloc(nodes, + size * sizeof(OpNode)); + } } while ((newPtr == NULL) && ((size -= (size - nodesUsed) / 2) > nodesUsed)); if (newPtr == NULL) { TclNewLiteralStringObj(msg, "not enough memory to parse expression"); @@ -706,10 +695,14 @@ 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; @@ -740,22 +733,48 @@ 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\"", - (scanned < limit) ? (int)scanned : (int)limit - 3, start, + (int)((scanned < limit) ? scanned : limit - 3), start, (scanned < limit) ? "" : "..."); post = Tcl_ObjPrintf( "should be \"$%.*s%s\" or \"{%.*s%s}\"", - (scanned < limit) ? (int)scanned : (int)limit - 3, + (int) ((scanned < limit) ? scanned : limit - 3), start, (scanned < limit) ? "" : "...", - (scanned < limit) ? (int)scanned : (int)limit - 3, + (int) ((scanned < limit) ? scanned : limit - 3), start, (scanned < limit) ? "" : "..."); Tcl_AppendPrintfToObj(post, " or \"%.*s%s(...)\" or ...", - (scanned < limit) ? (int)scanned : (int)limit - 3, + (int) ((scanned < limit) ? scanned : limit - 3), start, (scanned < limit) ? "" : "..."); errCode = "BAREWORD"; if (start[0] == '0') { const char *stop; TclParseNumber(NULL, NULL, NULL, start, scanned, @@ -888,12 +907,14 @@ tokenPtr->start = start; parsePtr->numTokens++; switch (lexeme) { case QUOTED: - code = Tcl_ParseQuotedString(NULL, start, numBytes, - parsePtr, 1, &end); + code = parseOnly ? Tcl_ParseQuotedString(NULL, start, + numBytes, parsePtr, 1, &end) + : TclParseQuotedString(NULL, start, numBytes, parsePtr, + PARSE_APPEND | PARSE_USE_INTERNAL_TOKENS, &end); scanned = end - start; break; case BRACED: code = Tcl_ParseBraces(NULL, start, numBytes, @@ -900,11 +921,13 @@ parsePtr, 1, &end); scanned = end - start; break; case VARIABLE: - code = Tcl_ParseVarName(NULL, start, numBytes, parsePtr, 1); + code = parseOnly ? Tcl_ParseVarName(NULL, start, numBytes, + parsePtr, 1) : TclParseVarName(NULL, start, numBytes, + parsePtr, PARSE_APPEND | PARSE_USE_INTERNAL_TOKENS); /* * Handle the quirk that Tcl_ParseVarName reports a successful * parse even when it gets only a "$" with no variable name. */ @@ -916,11 +939,12 @@ goto error; } scanned = tokenPtr->size; break; - case SCRIPT: { + case SCRIPT: + if (parseOnly) { Tcl_Parse *nestedPtr = (Tcl_Parse *) TclStackAlloc(interp, sizeof(Tcl_Parse)); tokenPtr = parsePtr->tokenPtr + parsePtr->numTokens; tokenPtr->type = TCL_TOKEN_COMMAND; @@ -960,11 +984,14 @@ start = tokenPtr->start; scanned = end - start; tokenPtr->size = scanned; parsePtr->numTokens++; break; - } /* SCRIPT case */ + } + code = TclParseScriptSubst(start, numBytes, parsePtr, 0); + scanned = parsePtr->term + 1 - start; + break; } if (code != TCL_OK) { /* * Here we handle all the syntax errors generated by the * Tcl_Token generating parsing routines called in the switch @@ -1444,11 +1471,11 @@ "\n (parsing expression \"%.*s%s\")", (numBytes < limit) ? (int)numBytes : (int)limit - 3, parsePtr->string, (numBytes < limit) ? "" : "...")); if (errCode) { Tcl_SetErrorCode(interp, "TCL", "PARSE", "EXPR", errCode, - subErrCode, NULL); + subErrCode, (void *)NULL); } } return TCL_ERROR; } @@ -1477,11 +1504,11 @@ */ static void ConvertTreeToTokens( const char *start, - size_t numBytes, + Tcl_Size numBytes, OpNode *nodes, Tcl_Token *tokenPtr, Tcl_Parse *parsePtr) { int subExprTokenIdx = 0; @@ -1695,11 +1722,11 @@ * nodePtr->lexeme. */ scanned = ParseLexeme(start, numBytes, &lexeme, NULL); - switch(nodePtr->lexeme) { + switch (nodePtr->lexeme) { case OPEN_PAREN: case COMMA: case COLON: /* @@ -1771,11 +1798,11 @@ * TCL_TOKEN_SUB_EXPR token, and all the rest (one fewer) * are its components. */ subExprTokenPtr->numComponents = - (parsePtr->numTokens - subExprTokenIdx) - 1; + ((int)parsePtr->numTokens - subExprTokenIdx) - 1; /* * Finally, as we return up the tree to our parent, pop the * parent subexpression off our subexpression stack, and * fill in the zero numComponents for the operator Tcl_Token. @@ -1825,11 +1852,11 @@ int Tcl_ParseExpr( Tcl_Interp *interp, /* Used for error reporting. */ const char *start, /* Start of source string to parse. */ - size_t numBytes, /* Number of bytes in string. If -1, the + Tcl_Size numBytes, /* Number of bytes in string. If -1, the * string consists of all bytes up to the * first null character. */ Tcl_Parse *parsePtr) /* Structure to fill with information about * the parsed expression; any previous * information in the structure is ignored. */ @@ -1841,11 +1868,11 @@ Tcl_Parse *exprParsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse)); /* Holds the Tcl_Tokens of substitutions. */ TclNewObj(litList); TclNewObj(funcList); - if (numBytes == TCL_INDEX_NONE) { + if (numBytes < 0) { numBytes = (start ? strlen(start) : 0); } code = ParseExpr(interp, start, numBytes, &opTree, litList, funcList, exprParsePtr, 1 /* parseOnly */); @@ -1877,26 +1904,26 @@ * * Results: * Returns the number of bytes scanned to produce the lexeme. * * Side effects: - * Code identifying lexeme parsed is writen to *lexemePtr. + * Code identifying lexeme parsed is written to *lexemePtr. * *---------------------------------------------------------------------- */ -static size_t +static Tcl_Size ParseLexeme( const char *start, /* Start of lexeme to parse. */ - size_t numBytes, /* Number of bytes in string. */ + Tcl_Size numBytes, /* Number of bytes in string. */ unsigned char *lexemePtr, /* Write code of parsed lexeme to this * storage. */ Tcl_Obj **literalPtr) /* Write corresponding literal value to this storage, if non-NULL. */ { const char *end; - Tcl_UniChar ch = 0; + int ch; Tcl_Obj *literal = NULL; unsigned char byte; if (numBytes == 0) { *lexemePtr = END; @@ -1906,10 +1933,23 @@ 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; } @@ -2045,13 +2085,13 @@ if (TclParseNumber(NULL, literal, NULL, start, numBytes, &end, TCL_PARSE_NO_WHITESPACE) == TCL_OK) { if (end < start + numBytes && !TclIsBareword(*end)) { number: - TclInitStringRep(literal, start, end-start); *lexemePtr = NUMBER; if (literalPtr) { + TclInitStringRep(literal, start, end-start); *literalPtr = literal; } else { Tcl_DecrRefCount(literal); } return (end-start); @@ -2063,11 +2103,11 @@ * (alpha, digit, underscore). Is this a number followed by * bareword syntax error? Or should we join into one bareword? * Example: Inf + luence + () becomes a valid function call. * [Bug 3401704] */ - if (TclHasIntRep(literal, &tclDoubleType)) { + if (TclHasInternalRep(literal, &tclDoubleType)) { const char *p = start; while (p < end) { if (!TclIsBareword(*p++)) { /* @@ -2099,19 +2139,19 @@ * Might be inspired by reserved identifier rules in C, which of course * have no direct relevance here. */ if (!TclIsBareword(*start) || *start == '_') { - size_t scanned; + Tcl_Size scanned; if (Tcl_UtfCharComplete(start, numBytes)) { - scanned = TclUtfToUniChar(start, &ch); + scanned = Tcl_UtfToUniChar(start, &ch); } else { - char utfBytes[4]; + char utfBytes[8]; memcpy(utfBytes, start, numBytes); utfBytes[numBytes] = '\0'; - scanned = TclUtfToUniChar(utfBytes, &ch); + scanned = Tcl_UtfToUniChar(utfBytes, &ch); } *lexemePtr = INVALID; Tcl_DecrRefCount(literal); return scanned; } @@ -2120,11 +2160,11 @@ end += 1; numBytes -= 1; } *lexemePtr = BAREWORD; if (literalPtr) { - Tcl_SetStringObj(literal, start, (int) (end-start)); + Tcl_SetStringObj(literal, start, end-start); *literalPtr = literal; } else { Tcl_DecrRefCount(literal); } return (end-start); @@ -2149,11 +2189,11 @@ void TclCompileExpr( Tcl_Interp *interp, /* Used for error reporting. */ const char *script, /* The source script to compile. */ - size_t numBytes, /* Number of bytes in script. */ + Tcl_Size numBytes, /* Number of bytes in script. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int optimize) /* 0 for one-off expressions. */ { OpNode *opTree = NULL; /* Will point to the tree of operators */ Tcl_Obj *litList; /* List to hold the literals */ @@ -2170,20 +2210,20 @@ if (code == TCL_OK) { /* * Valid parse; compile the tree. */ - int objc; + Tcl_Size objc; Tcl_Obj *const *litObjv; Tcl_Obj **funcObjv; /* TIP #280 : Track Lines within the expression */ TclAdvanceLines(&envPtr->line, script, script + TclParseAllWhiteSpace(script, numBytes)); - TclListObjGetElements(NULL, litList, &objc, (Tcl_Obj ***)&litObjv); - TclListObjGetElements(NULL, funcList, &objc, &funcObjv); + TclListObjGetElementsM(NULL, litList, &objc, (Tcl_Obj ***)&litObjv); + TclListObjGetElementsM(NULL, funcList, &objc, &funcObjv); CompileExprTree(interp, opTree, 0, &litObjv, funcObjv, parsePtr->tokenPtr, envPtr, optimize); } else { TclCompileSyntaxError(interp, envPtr); } @@ -2280,16 +2320,16 @@ int optimize) { OpNode *nodePtr = nodes + index; OpNode *rootPtr = nodePtr; int numWords = 0; - JumpList *jumpPtr = NULL; + JumpFixup *jumpPtr = NULL; + BA_JumpFixup *stack = NULL; int convert = 1; while (1) { int next; - JumpList *freePtr, *newJump; if (nodePtr->mark == MARK_LEFT) { next = nodePtr->left; if (nodePtr->lexeme == QUESTION) { @@ -2300,15 +2340,15 @@ switch (nodePtr->lexeme) { case FUNCTION: { Tcl_DString cmdName; const char *p; - size_t length; + Tcl_Size length; Tcl_DStringInit(&cmdName); TclDStringAppendLiteral(&cmdName, "tcl::mathfunc::"); - p = TclGetStringFromObj(*funcObjv, &length); + p = Tcl_GetStringFromObj(*funcObjv, &length); funcObjv++; Tcl_DStringAppend(&cmdName, p, length); TclEmitPush(TclRegisterLiteral(envPtr, Tcl_DStringValue(&cmdName), Tcl_DStringLength(&cmdName), LITERAL_CMD_NAME), envPtr); @@ -2324,34 +2364,33 @@ nodePtr->left = numWords; numWords = 2; /* Command plus one argument */ break; } case QUESTION: - newJump = (JumpList *)TclStackAlloc(interp, sizeof(JumpList)); - newJump->next = jumpPtr; - jumpPtr = newJump; - TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpPtr->jump); + if (stack == NULL) { + stack = BA_JumpFixup_Create(); + } + jumpPtr = BA_JumpFixup_Append(stack); + TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, jumpPtr); break; case COLON: - newJump = (JumpList *)TclStackAlloc(interp, sizeof(JumpList)); - newJump->next = jumpPtr; - jumpPtr = newJump; - TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, - &jumpPtr->jump); + jumpPtr = BA_JumpFixup_Append(stack); + TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, jumpPtr); TclAdjustStackDepth(-1, envPtr); if (convert) { - jumpPtr->jump.jumpType = TCL_TRUE_JUMP; + jumpPtr->jumpType = TCL_TRUE_JUMP; } convert = 1; break; case AND: case OR: - newJump = (JumpList *)TclStackAlloc(interp, sizeof(JumpList)); - newJump->next = jumpPtr; - jumpPtr = newJump; + if (stack == NULL) { + stack = BA_JumpFixup_Create(); + } + jumpPtr = BA_JumpFixup_Append(stack); TclEmitForwardJump(envPtr, (nodePtr->lexeme == AND) - ? TCL_FALSE_JUMP : TCL_TRUE_JUMP, &jumpPtr->jump); + ? TCL_FALSE_JUMP : TCL_TRUE_JUMP, jumpPtr); break; } } else { int pc1, pc2, target; @@ -2391,31 +2430,27 @@ */ numWords++; break; case COLON: + jumpPtr = BA_JumpFixup_Detach(stack); CLANG_ASSERT(jumpPtr); - if (jumpPtr->jump.jumpType == TCL_TRUE_JUMP) { - jumpPtr->jump.jumpType = TCL_UNCONDITIONAL_JUMP; + if (jumpPtr->jumpType == TCL_TRUE_JUMP) { + jumpPtr->jumpType = TCL_UNCONDITIONAL_JUMP; convert = 1; } - target = jumpPtr->jump.codeOffset + 2; - if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) { + target = jumpPtr->codeOffset + 2; + if (TclFixupForwardJumpToHere(envPtr, jumpPtr, 127)) { target += 3; } - freePtr = jumpPtr; - jumpPtr = jumpPtr->next; - TclStackFree(interp, freePtr); - TclFixupForwardJump(envPtr, &jumpPtr->jump, - target - jumpPtr->jump.codeOffset, 127); - - freePtr = jumpPtr; - jumpPtr = jumpPtr->next; - TclStackFree(interp, freePtr); + jumpPtr = BA_JumpFixup_Detach(stack); + TclFixupForwardJump(envPtr, jumpPtr, + target - jumpPtr->codeOffset, 127); break; case AND: case OR: + jumpPtr = BA_JumpFixup_Detach(stack); CLANG_ASSERT(jumpPtr); pc1 = CurrentOffset(envPtr); TclEmitInstInt1((nodePtr->lexeme == AND) ? INST_JUMP_FALSE1 : INST_JUMP_TRUE1, 0, envPtr); TclEmitPush(TclRegisterLiteral(envPtr, @@ -2423,30 +2458,30 @@ pc2 = CurrentOffset(envPtr); TclEmitInstInt1(INST_JUMP1, 0, envPtr); TclAdjustStackDepth(-1, envPtr); TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc1, envPtr->codeStart + pc1 + 1); - if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) { + if (TclFixupForwardJumpToHere(envPtr, jumpPtr, 127)) { pc2 += 3; } TclEmitPush(TclRegisterLiteral(envPtr, (nodePtr->lexeme == AND) ? "0" : "1", 1, 0), envPtr); TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc2, envPtr->codeStart + pc2 + 1); convert = 0; - freePtr = jumpPtr; - jumpPtr = jumpPtr->next; - TclStackFree(interp, freePtr); break; default: TclEmitOpcode(instruction[nodePtr->lexeme], envPtr); convert = 0; break; } if (nodePtr == rootPtr) { /* We're done */ + if (stack) { + BA_JumpFixup_Destroy(stack); + } return; } nodePtr = nodes + nodePtr->p.parent; continue; } @@ -2459,12 +2494,12 @@ case OT_LITERAL: { Tcl_Obj *const *litObjv = *litObjvPtr; Tcl_Obj *literal = *litObjv; if (optimize) { - size_t length; - const char *bytes = TclGetStringFromObj(literal, &length); + Tcl_Size length; + const char *bytes = Tcl_GetStringFromObj(literal, &length); int idx = TclRegisterLiteral(envPtr, bytes, length, 0); Tcl_Obj *objPtr = TclFetchLiteral(envPtr, idx); if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) { /* @@ -2475,11 +2510,11 @@ * Tcl_DecrRefCount(objPtr); * * However, the design of the "global" and "local" * LiteralTable does not permit the value of lePtr->objPtr * to change. So rather than replace lePtr->objPtr, we do - * surgery to transfer our desired intrep into it. + * surgery to transfer our desired internalrep into it. */ objPtr->typePtr = literal->typePtr; objPtr->internalRep = literal->internalRep; literal->typePtr = NULL; @@ -2488,13 +2523,13 @@ } else { /* * When optimize==0, we know the expression is a one-off and * there's nothing to be gained from sharing literals when * they won't live long, and the copies we have already have - * an appropriate intrep. In this case, skip literal + * an appropriate internalrep. In this case, skip literal * registration that would enable sharing, and use the routine - * that preserves intreps. + * that preserves internalreps. */ TclEmitPush(TclAddLiteralObj(envPtr, literal, NULL), envPtr); } (*litObjvPtr)++; @@ -2518,20 +2553,20 @@ * already, then use it to share via the literal table. */ if (TclHasStringRep(objPtr)) { Tcl_Obj *tableValue; - size_t numBytes; + Tcl_Size numBytes; const char *bytes - = TclGetStringFromObj(objPtr, &numBytes); + = Tcl_GetStringFromObj(objPtr, &numBytes); idx = TclRegisterLiteral(envPtr, bytes, numBytes, 0); tableValue = TclFetchLiteral(envPtr, idx); if ((tableValue->typePtr == NULL) && (objPtr->typePtr != NULL)) { /* - * Same intrep surgery as for OT_LITERAL. + * Same internalrep surgery as for OT_LITERAL. */ tableValue->typePtr = objPtr->typePtr; tableValue->internalRep = objPtr->internalRep; objPtr->typePtr = NULL; @@ -2571,11 +2606,11 @@ *---------------------------------------------------------------------- */ int TclSingleOpCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData; @@ -2624,11 +2659,11 @@ *---------------------------------------------------------------------- */ int TclSortingOpCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int code = TCL_OK; @@ -2704,11 +2739,11 @@ *---------------------------------------------------------------------- */ int TclVariadicOpCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData; @@ -2742,11 +2777,11 @@ nodes[1].left = OT_LITERAL; nodes[1].right = OT_LITERAL; nodes[1].p.parent = 0; } else { if (lexeme == DIVIDE) { - litObjv[0] = Tcl_NewDoubleObj(1.0); + TclNewDoubleObj(litObjv[0], 1.0); } else { TclNewIntObj(litObjv[0], occdPtr->i.identity); } Tcl_IncrRefCount(litObjv[0]); litObjv[1] = objv[1]; @@ -2823,11 +2858,11 @@ *---------------------------------------------------------------------- */ int TclNoIdentOpCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData; Index: generic/tclCompile.c ================================================================== --- generic/tclCompile.c +++ generic/tclCompile.c @@ -3,20 +3,38 @@ * * This file contains procedures that compile Tcl commands or parts of * commands (like quoted strings or nested sub-commands) into a sequence * of instructions ("bytecodes"). * - * Copyright (c) 1996-1998 Sun Microsystems, Inc. - * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. + * Copyright © 1996-1998 Sun Microsystems, Inc. + * Copyright © 2001 Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include +#include "tclBrodnik.h" + +/* + * 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 CmdLocation { + size_t codeOffset; /* Offset of first byte of command code. */ + size_t numCodeBytes; /* Number of bytes for command's code. */ + size_t srcOffset; /* Offset of first char of the command. */ + size_t numSrcBytes; /* Number of command source chars. */ +} CmdLocation; +TclBrodnikArray(CmdLocation); +TclBrodnikArrayDefine(AuxData,MODULE_SCOPE); /* * Variable that controls whether compilation tracing is enabled and, if so, * what level of tracing is desired: * 0: no compilation tracing @@ -655,29 +673,37 @@ /* 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. + */ {NULL, 0, 0, 0, {OPERAND_NONE}} }; /* * Prototypes for procedures defined later in this file: */ static void CleanupByteCode(ByteCode *codePtr); +static void CompileScriptTokens(Tcl_Interp *interp, + Tcl_Token *tokens, Tcl_Token *lastTokenPtr, + CompileEnv *envPtr); 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 CmdLocation * EnterCmdStartData(CompileEnv *envPtr, + 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); @@ -690,40 +716,43 @@ /* * TIP #280: Helper for building the per-word line information of all compiled * commands. */ -static void EnterCmdWordData(ExtCmdLoc *eclPtr, int srcOffset, +static void EnterCmdWordData(ExtCmdLoc *eclPtr, Tcl_Size srcOffset, Tcl_Token *tokenPtr, const char *cmd, - int numWords, int line, int *clNext, int **lines, + Tcl_Size numWords, Tcl_Size line, + Tcl_Size *clNext, Tcl_Size **lines, CompileEnv *envPtr); static void ReleaseCmdWordData(ExtCmdLoc *eclPtr); /* - * The structure below defines the bytecode Tcl object type by means of - * procedures that can be invoked by generic object code. + * 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 */ + SetByteCodeFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; /* - * The structure below defines a bytecode Tcl object type to hold the - * compiled bytecode for the [subst]itution of Tcl values. + * substCodeType provides the standard type management procedures for the + * substcode type, which represents substitution within a Tcl value. */ static const Tcl_ObjType substCodeType = { "substcode", /* name */ FreeSubstCodeInternalRep, /* freeIntRepProc */ DupByteCodeInternalRep, /* dupIntRepProc - shared with bytecode */ NULL, /* updateStringProc */ NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; #define SubstFlags(objPtr) (objPtr)->internalRep.twoPtrValue.ptr2 /* * Helper macros. @@ -736,20 +765,18 @@ *---------------------------------------------------------------------- * * TclSetByteCodeFromAny -- * * Part of the bytecode Tcl object type implementation. Attempts to - * generate an byte code internal form for the Tcl object "objPtr" by - * compiling its string representation. This function also takes a hook - * procedure that will be invoked to perform any needed post processing - * on the compilation results before generating byte codes. interp is + * compile the string representation of the objPtr into bytecode. Accepts + * a hook routine that is invoked to perform any needed post-processing on + * the compilation results before generating byte codes. interp is the * compilation context and may not be NULL. * * Results: - * The return value is a standard Tcl object result. If an error occurs - * during compilation, an error message is left in the interpreter's - * result. + * 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 @@ -762,16 +789,16 @@ TclSetByteCodeFromAny( Tcl_Interp *interp, /* The interpreter for which the code is being * compiled. Must not be NULL. */ Tcl_Obj *objPtr, /* The object to make a ByteCode object. */ CompileHookProc *hookProc, /* Procedure to invoke after compilation. */ - ClientData clientData) /* Hook procedure private data. */ + void *clientData) /* Hook procedure private data. */ { Interp *iPtr = (Interp *) interp; CompileEnv compEnv; /* Compilation environment structure allocated * in frame. */ - size_t length; + Tcl_Size length; int result = TCL_OK; const char *stringPtr; Proc *procPtr = iPtr->compiledProcPtr; ContLineLoc *clLocPtr; @@ -783,31 +810,30 @@ } traceInitialized = 1; } #endif - stringPtr = TclGetStringFromObj(objPtr, &length); + stringPtr = Tcl_GetStringFromObj(objPtr, &length); /* - * TIP #280: Pick up the CmdFrame in which the BC compiler was invoked and + * TIP #280: Pick up the CmdFrame in which the BC compiler was invoked, and * use to initialize the tracking in the compiler. This information was * stored by TclCompEvalObj and ProcCompileProc. */ TclInitCompileEnv(interp, &compEnv, stringPtr, length, iPtr->invokeCmdFramePtr, iPtr->invokeWord); /* - * Now we check if we have data about invisible continuation lines for the - * script, and make it available to the compile environment, if so. + * 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 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". + * 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]; @@ -814,21 +840,21 @@ } TclCompileScript(interp, stringPtr, length, &compEnv); /* - * Successful compilation. Add a "done" instruction at the end. + * Compilation succeeded. Add a "done" instruction at the end. */ TclEmitOpcode(INST_DONE, &compEnv); /* * Check for optimizations! * - * Test if the generated code is free of most hazards; if so, recompile - * but with generation of INST_START_CMD disabled. This produces somewhat - * faster code in some cases, and more compact code in more. + * If the generated code is free of most hazards, recompile with generation + * of INST_START_CMD disabled to produce code that more compact in many + * cases, and also sometimes more performant. */ if (Tcl_GetParent(interp) == NULL && !Tcl_LimitTypeEnabled(interp, TCL_LIMIT_COMMANDS|TCL_LIMIT_TIME) && IsCompactibleCompileEnv(&compEnv)) { @@ -854,20 +880,32 @@ if (iPtr->optimizer) { (iPtr->optimizer)(&compEnv); } /* - * Invoke the compilation hook procedure if one exists. + * Invoke the compilation hook procedure if there is one. */ if (hookProc) { result = hookProc(interp, &compEnv, clientData); } + + /* + * After optimization is all done, check that byte code length limits + * are not exceeded. Bug [27b3ce2997]. + */ + if ((compEnv.codeNext - compEnv.codeStart) > INT_MAX) { + /* + * Cannot just return TCL_ERROR as callers ignore return value. + * TODO - May be use TclCompileSyntaxError here? + */ + Tcl_Panic("Maximum byte code length %d exceeded.", INT_MAX); + } /* * Change the object into a ByteCode object. Ownership of the literal - * objects and aux data items is given to the ByteCode object. + * objects and aux data items passes to the ByteCode object. */ #ifdef TCL_COMPILE_DEBUG TclVerifyLocalLiteralTable(&compEnv); #endif /*TCL_COMPILE_DEBUG*/ @@ -894,16 +932,16 @@ * Part of the bytecode Tcl object type implementation. Attempts to * generate an byte code internal form for the Tcl object "objPtr" by * compiling its string representation. * * Results: - * The return value is a standard Tcl object result. If an error occurs - * during compilation, an error message is left in the interpreter's - * result unless "interp" is NULL. + * A standard Tcl object result. If an error occurs during compilation and + * "interp" is not null, an error message is left in the interpreter's + * result. * * Side effects: - * Frees the old internal representation. If no error occurs, then the + * Frees the old internal representation. If no error occurs then the * compiled code is stored as "objPtr"s bytecode representation. Also, if * debugging, initializes the "tcl_traceCompile" Tcl variable used to * trace compilations. * *---------------------------------------------------------------------- @@ -911,11 +949,11 @@ static int SetByteCodeFromAny( Tcl_Interp *interp, /* The interpreter for which the code is being * compiled. Must not be NULL. */ - Tcl_Obj *objPtr) /* The object to make a ByteCode object. */ + Tcl_Obj *objPtr) /* The object to compile to bytecode */ { if (interp == NULL) { return TCL_ERROR; } return TclSetByteCodeFromAny(interp, objPtr, NULL, NULL); @@ -925,13 +963,13 @@ *---------------------------------------------------------------------- * * DupByteCodeInternalRep -- * * Part of the bytecode Tcl object type implementation. However, it does - * not copy the internal representation of a bytecode Tcl_Obj, but - * instead leaves the new object untyped (with a NULL type pointer). - * Code will be compiled for the new object only if necessary. + * not copy the internal representation of a bytecode Tcl_Obj, instead + * assigning NULL to the type pointer of the new object. Code is compiled + * for the new object only if necessary. * * Results: * None. * * Side effects: @@ -959,13 +997,13 @@ * * Results: * None. * * Side effects: - * The bytecode object's internal rep is marked invalid and its code gets - * freed unless the code is actively being executed. In that case the - * cleanup is delayed until the last execution of the code completes. + * The bytecode object's internal rep is invalidated and its code is freed + * unless the code is actively being executed, in which case cleanup is + * delayed until the last execution of the code completes. * *---------------------------------------------------------------------- */ static void @@ -972,11 +1010,11 @@ FreeByteCodeInternalRep( Tcl_Obj *objPtr) /* Object whose internal rep to free. */ { ByteCode *codePtr; - ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr); assert(codePtr != NULL); TclReleaseByteCode(codePtr); } @@ -983,20 +1021,20 @@ /* *---------------------------------------------------------------------- * * TclReleaseByteCode -- * - * This procedure does all the real work of freeing up a bytecode - * object's ByteCode structure. It's called only when the structure's - * reference count becomes zero. + * Does all the real work of freeing up a bytecode object's ByteCode + * structure. Called only when the structure's reference count + * is zero. * * Results: * None. * * Side effects: - * Frees objPtr's bytecode internal representation and sets its type NULL - * Also releases its literals and frees its auxiliary data items. + * Frees objPtr's bytecode internal representation and sets its type to + * NULL. Also releases its literals and frees its auxiliary data items. * *---------------------------------------------------------------------- */ void @@ -1023,11 +1061,10 @@ ByteCode *codePtr) /* Points to the ByteCode to free. */ { Tcl_Interp *interp = (Tcl_Interp *) *codePtr->interpHandle; Interp *iPtr = (Interp *) interp; int numLitObjects = codePtr->numLitObjects; - int numAuxDataItems = codePtr->numAuxDataItems; Tcl_Obj **objArrayPtr, *objPtr; const AuxData *auxDataPtr; int i; #ifdef TCL_COMPILE_STATS @@ -1037,20 +1074,20 @@ int lifetimeSec, lifetimeMicroSec, log2; statsPtr = &iPtr->stats; statsPtr->numByteCodesFreed++; - statsPtr->currentSrcBytes -= (double) codePtr->numSrcBytes; + statsPtr->currentSrcBytes -= (double)codePtr->numSrcBytes; statsPtr->currentByteCodeBytes -= (double) codePtr->structureSize; statsPtr->currentInstBytes -= (double) codePtr->numCodeBytes; statsPtr->currentLitBytes -= (double) codePtr->numLitObjects * sizeof(Tcl_Obj *); statsPtr->currentExceptBytes -= (double) codePtr->numExceptRanges * sizeof(ExceptionRange); statsPtr->currentAuxBytes -= (double) - codePtr->numAuxDataItems * sizeof(AuxData); + BA_AuxData_Size(codePtr->auxData) * sizeof(AuxData); statsPtr->currentCmdMapBytes -= (double) codePtr->numCmdLocBytes; Tcl_GetTime(&destroyTime); lifetimeSec = destroyTime.sec - codePtr->createTime.sec; if (lifetimeSec > 2000) { /* avoid overflow */ @@ -1068,25 +1105,25 @@ #endif /* TCL_COMPILE_STATS */ /* * A single heap object holds the ByteCode structure and its code, object, * command location, and auxiliary data arrays. This means we only need to - * 1) decrement the ref counts of the LiteralEntry's in its literal array, - * 2) call the free procs for the auxiliary data items, 3) free the + * 1) decrement the ref counts of each literal value in the literal array, + * 2) call the free procedures for the auxiliary data items, 3) free the * localCache if it is unused, and finally 4) free the ByteCode * structure's heap object. * * The case for TCL_BYTECODE_PRECOMPILED (precompiled ByteCodes, like * those generated from tbcload) is special, as they doesn't make use of * the global literal table. They instead maintain private references to * their literals which must be decremented. * - * In order to insure a proper and efficient cleanup of the literal array - * when it contains non-shared literals [Bug 983660], we also distinguish - * the case of an interpreter being deleted (signaled by interp == NULL). + * In order to ensure proper and efficient cleanup of the literal array + * when it contains non-shared literals [Bug 983660], distinguish the case + * of an interpreter being deleted, which is signaled by interp == NULL. * Also, as the interp deletion will remove the global literal table - * anyway, we avoid the extra cost of updating it for each literal being + * anyway, avoid the extra cost of updating it for each literal being * released. */ if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) { @@ -1104,23 +1141,32 @@ while (numLitObjects--) { /* TclReleaseLiteral calls Tcl_DecrRefCount() for us */ TclReleaseLiteral(interp, *objArrayPtr++); } } + if (codePtr->flags & TCL_BYTECODE_FREE_LITERALS) { + Tcl_Free(codePtr->objArrayPtr); + } - auxDataPtr = codePtr->auxDataArrayPtr; - for (i = 0; i < numAuxDataItems; i++) { - if (auxDataPtr->type->freeProc != NULL) { - auxDataPtr->type->freeProc(auxDataPtr->clientData); + if (codePtr->auxData) { + BA_AuxData *adArray = codePtr->auxData; + + codePtr->auxData = NULL; + auxDataPtr = BA_AuxData_Detach(adArray); + while (auxDataPtr) { + if (auxDataPtr->type->freeProc != NULL) { + auxDataPtr->type->freeProc(auxDataPtr->clientData); + } + auxDataPtr = BA_AuxData_Detach(adArray); } - auxDataPtr++; + BA_AuxData_Destroy(adArray); } /* - * TIP #280. Release the location data associated with this byte code - * structure, if any. NOTE: The interp we belong to may be gone already, - * and the data with it. + * TIP #280. Release the location data associated with this bytecode + * structure, if any. The associated interp may be gone already, and the + * data with it. * * See also tclBasic.c, DeleteInterpProc */ if (iPtr) { @@ -1144,12 +1190,12 @@ /* * --------------------------------------------------------------------- * * IsCompactibleCompileEnv -- * - * Checks to see if we may apply some basic compaction optimizations to a - * piece of bytecode. Idempotent. + * Determines whether some basic compaction optimizations may be applied + * to a piece of bytecode. Idempotent. * * --------------------------------------------------------------------- */ static int @@ -1159,11 +1205,11 @@ unsigned char *pc; int size; /* * Special: procedures in the '::tcl' namespace (or its children) are - * considered to be well-behaved and so can have compaction applied even + * considered to be well-behaved, so compaction can be applied to them even * if it would otherwise be invalid. */ if (envPtr->procPtr != NULL && envPtr->procPtr->cmdPtr != NULL && envPtr->procPtr->cmdPtr->nsPtr != NULL) { @@ -1175,14 +1221,14 @@ } } /* * Go through and ensure that no operation involved can cause a desired - * change of bytecode sequence during running. This comes down to ensuring - * that there are no mapped variables (due to traces) or calls to external - * commands (traces, [uplevel] trickery). This is actually a very - * conservative check; it turns down a lot of code that is OK in practice. + * change of bytecode sequence during its execution. This comes down to + * ensuring that there are no mapped variables (due to traces) or calls to + * external commands (traces, [uplevel] trickery). This is actually a very + * conservative check. It turns down a lot of code that is OK in practice. */ for (pc = envPtr->codeStart ; pc < envPtr->codeNext ; pc += size) { switch (*pc) { /* Invokes */ @@ -1214,12 +1260,12 @@ /* *---------------------------------------------------------------------- * * Tcl_SubstObj -- * - * This function performs the substitutions specified on the given string - * as described in the user documentation for the "subst" Tcl command. + * Performs substitutions on the given string as described in the user + * documentation for "subst". * * Results: * A Tcl_Obj* containing the substituted string, or NULL to indicate that * an error occurred. * @@ -1247,18 +1293,18 @@ /* *---------------------------------------------------------------------- * * Tcl_NRSubstObj -- * - * Request substitution of a Tcl value by the NR stack. + * Adds substitution within the value of objPtr to the NR execution stack. * * Results: - * Returns TCL_OK. + * TCL_OK. * * Side effects: * Compiles objPtr into bytecode that performs the substitutions as - * governed by flags and places callbacks on the NR stack to execute + * governed by flags, adds a callback to the NR execution stack to execute * the bytecode and store the result in the interp. * *---------------------------------------------------------------------- */ @@ -1278,15 +1324,15 @@ /* *---------------------------------------------------------------------- * * CompileSubstObj -- * - * Compile a Tcl value into ByteCode implementing its substitution, as - * governed by flags. + * Compiles a value into bytecode that performs substitution within the + * value, as governed by flags. * * Results: - * A (ByteCode *) is returned pointing to the resulting ByteCode. + * A (ByteCode *) is pointing to the resulting ByteCode. * * Side effects: * The Tcl_ObjType of objPtr is changed to the "substcode" type, and the * ByteCode and governing flags value are kept in the internal rep for * faster operations the next time CompileSubstObj is called on the same @@ -1302,11 +1348,11 @@ int flags) { Interp *iPtr = (Interp *) interp; ByteCode *codePtr = NULL; - ByteCodeGetIntRep(objPtr, &substCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &substCodeType, codePtr); if (codePtr != NULL) { Namespace *nsPtr = iPtr->varFramePtr->nsPtr; if (flags != PTR2INT(SubstFlags(objPtr)) @@ -1314,18 +1360,18 @@ || (codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsPtr != nsPtr) || (codePtr->nsEpoch != nsPtr->resolverEpoch) || (codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)) { - Tcl_StoreIntRep(objPtr, &substCodeType, NULL); + Tcl_StoreInternalRep(objPtr, &substCodeType, NULL); codePtr = NULL; } } if (codePtr == NULL) { CompileEnv compEnv; - size_t numBytes; - const char *bytes = TclGetStringFromObj(objPtr, &numBytes); + Tcl_Size numBytes; + const char *bytes = Tcl_GetStringFromObj(objPtr, &numBytes); /* TODO: Check for more TIP 280 */ TclInitCompileEnv(interp, &compEnv, bytes, numBytes, NULL, 0); TclSubstCompile(interp, bytes, numBytes, flags, 1, &compEnv); @@ -1352,13 +1398,13 @@ /* *---------------------------------------------------------------------- * * FreeSubstCodeInternalRep -- * - * Part of the substcode Tcl object type implementation. Frees the - * storage associated with a substcode object's internal representation - * unless its code is actively being executed. + * Part of the "substcode" Tcl object type implementation. Frees the + * storage associated with the substcode internal representation of a + * Tcl_Obj unless its code is actively being executed. * * Results: * None. * * Side effects: @@ -1373,21 +1419,21 @@ FreeSubstCodeInternalRep( Tcl_Obj *objPtr) /* Object whose internal rep to free. */ { ByteCode *codePtr; - ByteCodeGetIntRep(objPtr, &substCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &substCodeType, codePtr); assert(codePtr != NULL); TclReleaseByteCode(codePtr); } static void ReleaseCmdWordData( ExtCmdLoc *eclPtr) { - int i; + Tcl_Size i; if (eclPtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(eclPtr->path); } for (i=0 ; inuloc ; i++) { @@ -1423,11 +1469,11 @@ Tcl_Interp *interp, /* The interpreter for which a CompileEnv * structure is initialized. */ CompileEnv *envPtr,/* Points to the CompileEnv structure to * initialize. */ const char *stringPtr, /* The source string to be compiled. */ - size_t numBytes, /* Number of bytes in source string. */ + Tcl_Size numBytes, /* Number of bytes in source string. */ const CmdFrame *invoker, /* Location context invoking the bcc */ int word) /* Index of the word in that context getting * compiled */ { Interp *iPtr = (Interp *) interp; @@ -1442,11 +1488,11 @@ envPtr->numCommands = 0; envPtr->exceptDepth = 0; envPtr->maxExceptDepth = 0; envPtr->maxStackDepth = 0; envPtr->currStackDepth = 0; - TclInitLiteralTable(&envPtr->localLitTable); + Tcl_InitHashTable(&envPtr->litMap, TCL_ONE_WORD_KEYS); envPtr->codeStart = envPtr->staticCodeSpace; envPtr->codeNext = envPtr->codeStart; envPtr->codeEnd = envPtr->codeStart + COMPILEENV_INIT_CODE_BYTES; envPtr->mallocedCodeArray = 0; @@ -1460,13 +1506,11 @@ envPtr->exceptAuxArrayPtr = envPtr->staticExAuxArraySpace; envPtr->exceptArrayNext = 0; envPtr->exceptArrayEnd = COMPILEENV_INIT_EXCEPT_RANGES; envPtr->mallocedExceptArray = 0; - envPtr->cmdMapPtr = envPtr->staticCmdMapSpace; - envPtr->cmdMapEnd = COMPILEENV_INIT_CMD_MAP_SIZE; - envPtr->mallocedCmdMap = 0; + envPtr->cmdMap = BA_CmdLocation_Create(); envPtr->atCmdStart = 1; envPtr->expandCount = 0; /* * TIP #280: Set up the extended command location information, based on @@ -1597,29 +1641,26 @@ * data is available. */ envPtr->clNext = NULL; - envPtr->auxDataArrayPtr = envPtr->staticAuxDataArraySpace; - envPtr->auxDataArrayNext = 0; - envPtr->auxDataArrayEnd = COMPILEENV_INIT_AUX_DATA_SIZE; - envPtr->mallocedAuxDataArray = 0; + envPtr->auxData = NULL; } /* *---------------------------------------------------------------------- * * TclFreeCompileEnv -- * - * Free the storage allocated in a CompileEnv compilation environment + * Frees the storage allocated in a CompileEnv compilation environment * structure. * * Results: * None. * * Side effects: - * Allocated storage in the CompileEnv structure is freed. Note that its + * Allocated storage in the CompileEnv structure is freed, although its * local literal table is not deleted and its literal objects are not * released. In addition, storage referenced by its auxiliary data items * is not freed. This is done so that, when compilation is successful, * "ownership" of these objects and aux data items is handed over to the * corresponding ByteCode structure. @@ -1629,56 +1670,54 @@ void TclFreeCompileEnv( CompileEnv *envPtr)/* Points to the CompileEnv structure. */ { - if (envPtr->localLitTable.buckets != envPtr->localLitTable.staticBuckets){ - Tcl_Free(envPtr->localLitTable.buckets); - envPtr->localLitTable.buckets = envPtr->localLitTable.staticBuckets; - } + Tcl_DeleteHashTable(&envPtr->litMap); 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; + Tcl_Size i; + Tcl_Obj **litPtr = envPtr->literalArrayPtr; for (i = 0; i < envPtr->literalArrayNext; i++) { - TclReleaseLiteral((Tcl_Interp *)envPtr->iPtr, entryPtr->objPtr); - entryPtr++; + TclReleaseLiteral((Tcl_Interp *)envPtr->iPtr, *litPtr++); } #ifdef TCL_COMPILE_DEBUG TclVerifyGlobalLiteralTable(envPtr->iPtr); #endif /*TCL_COMPILE_DEBUG*/ - for (i = 0; i < envPtr->auxDataArrayNext; i++) { - if (auxDataPtr->type->freeProc != NULL) { - auxDataPtr->type->freeProc(auxDataPtr->clientData); + if (envPtr->auxData) { + BA_AuxData *adArray = envPtr->auxData; + AuxData *auxDataPtr; + + envPtr->auxData = NULL; + auxDataPtr = BA_AuxData_Detach(adArray); + while (auxDataPtr) { + if (auxDataPtr->type->freeProc != NULL) { + auxDataPtr->type->freeProc(auxDataPtr->clientData); + } + auxDataPtr = BA_AuxData_Detach(adArray); } - auxDataPtr++; + BA_AuxData_Destroy(adArray); } } if (envPtr->mallocedCodeArray) { Tcl_Free(envPtr->codeStart); } - if (envPtr->mallocedLiteralArray) { + if (envPtr->mallocedLiteralArray && envPtr->iPtr) { Tcl_Free(envPtr->literalArrayPtr); } if (envPtr->mallocedExceptArray) { Tcl_Free(envPtr->exceptArrayPtr); Tcl_Free(envPtr->exceptAuxArrayPtr); } - if (envPtr->mallocedCmdMap) { - Tcl_Free(envPtr->cmdMapPtr); - } - if (envPtr->mallocedAuxDataArray) { - Tcl_Free(envPtr->auxDataArrayPtr); - } + BA_CmdLocation_Destroy(envPtr->cmdMap); if (envPtr->extCmdMapPtr) { ReleaseCmdWordData(envPtr->extCmdMapPtr); envPtr->extCmdMapPtr = NULL; } } @@ -1686,14 +1725,15 @@ /* *---------------------------------------------------------------------- * * TclWordKnownAtCompileTime -- * - * Test whether the value of a token is completely known at compile time. + * Determines whether the value of a token is completely known at compile + * time. * * Results: - * Returns true if the tokenPtr argument points to a word value that is + * True if the tokenPtr argument points to a word value that is * completely known at compile time. Generally, values that are known at * compile time can be compiled to their values, while values that cannot * be known until substitution at runtime must be compiled to bytecode * instructions that perform that substitution. For several commands, * whether or not arguments are known at compile time determine whether @@ -1704,11 +1744,11 @@ * unshared Tcl_Obj (*valuePtr), unless valuePtr is NULL. * *---------------------------------------------------------------------- */ -int +Tcl_Size TclWordKnownAtCompileTime( Tcl_Token *tokenPtr, /* Points to Tcl_Token we should check */ Tcl_Obj *valuePtr) /* If not NULL, points to an unshared Tcl_Obj * to which we should append the known value * of the word. */ @@ -1739,11 +1779,11 @@ break; case TCL_TOKEN_BS: if (tempPtr != NULL) { char utfBuf[4] = ""; - size_t length = TclParseBackslash(tokenPtr->start, + Tcl_Size length = TclParseBackslash(tokenPtr->start, tokenPtr->size, NULL, utfBuf); Tcl_AppendToObj(tempPtr, utfBuf, length); } break; @@ -1766,16 +1806,16 @@ /* *---------------------------------------------------------------------- * * TclCompileScript -- * - * Compile a Tcl script in a string. + * Compiles a Tcl script in a string. * * Results: - * The return value is TCL_OK on a successful compilation and TCL_ERROR - * on failure. If TCL_ERROR is returned, then the interpreter's result - * contains an error message. + * + * 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. * *---------------------------------------------------------------------- @@ -1782,11 +1822,11 @@ */ static int ExpandRequested( Tcl_Token *tokenPtr, - size_t numWords) + Tcl_Size numWords) { /* Determine whether any words of the command require expansion */ while (numWords--) { if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) { return 1; @@ -1803,36 +1843,36 @@ CompileEnv *envPtr) { const char *bytes; Command *cmdPtr; int cmdLitIdx, extraLiteralFlags = LITERAL_CMD_NAME; - size_t length; + Tcl_Size length; cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj); if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) { extraLiteralFlags |= LITERAL_UNSHARED; } - bytes = TclGetStringFromObj(cmdObj, &length); + bytes = Tcl_GetStringFromObj(cmdObj, &length); cmdLitIdx = TclRegisterLiteral(envPtr, bytes, length, extraLiteralFlags); if (cmdPtr && TclRoutineHasName(cmdPtr)) { TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLitIdx), cmdPtr); } TclEmitPush(cmdLitIdx, envPtr); } -void +Tcl_Token * TclCompileInvocation( Tcl_Interp *interp, Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, - size_t numWords, + Tcl_Size numWords, CompileEnv *envPtr) { DefineLineInformation; - size_t wordIdx = 0; + Tcl_Size wordIdx = 0; int depth = TclGetStackDepth(envPtr); if (cmdObj) { CompileCmdLiteral(interp, cmdObj, envPtr); wordIdx = 1; @@ -1862,13 +1902,15 @@ TclEmitInvoke(envPtr, INST_INVOKE_STK1, wordIdx); } else { TclEmitInvoke(envPtr, INST_INVOKE_STK4, wordIdx); } TclCheckStackDepth(depth+1, envPtr); + + return tokenPtr; } -static void +static Tcl_Token * CompileExpanded( Tcl_Interp *interp, Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, int numWords, @@ -1909,47 +1951,56 @@ } /* * The stack depth during argument expansion can only be managed at * runtime, as the number of elements in the expanded lists is not known - * at compile time. We adjust here the stack depth estimate so that it is + * at compile time. Adjust the stack depth estimate here so that it is * correct after the command with expanded arguments returns. * * The end effect of this command's invocation is that all the words of - * the command are popped from the stack, and the result is pushed: the + * the command are popped from the stack and the result is pushed: The * stack top changes by (1-wordIdx). * - * Note that the estimates are not correct while the command is being + * The estimates are not correct while the command is being * prepared and run, INST_EXPAND_STKTOP is not stack-neutral in general. */ TclEmitInvoke(envPtr, INST_INVOKE_EXPANDED, wordIdx); TclCheckStackDepth(depth+1, envPtr); + + return tokenPtr; } static int CompileCmdCompileProc( Tcl_Interp *interp, - Tcl_Parse *parsePtr, + Tcl_Token *tokenPtr, Command *cmdPtr, CompileEnv *envPtr) { DefineLineInformation; - int unwind = 0, incrOffset = -1; + int unwind = 0; + Tcl_Size incrOffset = -1; int depth = TclGetStackDepth(envPtr); + Tcl_Parse parse; + + parse.commandStart = tokenPtr->start; + parse.commandSize = tokenPtr->size; + parse.numWords = tokenPtr->numComponents; + parse.tokenPtr = tokenPtr + 1; /* - * Emit of the INST_START_CMD instruction is controlled by the value of + * Emission of the INST_START_CMD instruction is controlled by the value of * envPtr->atCmdStart: * - * atCmdStart == 2 : We are not using the INST_START_CMD instruction. - * atCmdStart == 1 : INST_START_CMD was the last instruction emitted. - * : We do not need to emit another. Instead we - * : increment the number of cmds started at it (except - * : for the special case at the start of a script.) - * atCmdStart == 0 : The last instruction was something else. We need - * : to emit INST_START_CMD here. + * atCmdStart == 2 : Don't use the INST_START_CMD instruction. + * atCmdStart == 1 : INST_START_CMD was the last instruction emitted, + * : so no need to emit another. Instead + * : increment the number of cmds started at it, except + * : for the special case at the start of a script. + * atCmdStart == 0 : The last instruction was something else. + * : Emit INST_START_CMD here. */ switch (envPtr->atCmdStart) { case 0: unwind = tclInstructionTable[INST_START_CMD].numBytes; @@ -1965,14 +2016,14 @@ case 2: /* Nothing to do */ ; } - if (TCL_OK == TclAttemptCompileProc(interp, parsePtr, 1, cmdPtr, envPtr)) { + if (TCL_OK == TclAttemptCompileProc(interp, &parse, 1, cmdPtr, envPtr)) { if (incrOffset >= 0) { /* - * We successfully compiled a command. Increment the number of + * Command compiled succesfully. Increment the number of * commands that start at the currently active INST_START_CMD. */ unsigned char *incrPtr = envPtr->codeStart + incrOffset; unsigned char *startPtr = incrPtr - 5; @@ -2002,62 +2053,78 @@ /* * Reset the index of next command. Toss out any from failed nested * partial compiles. */ - envPtr->numCommands = mapPtr->nuloc; + TclDisposeFailedCompile(envPtr, mapPtr->nuloc); return TCL_ERROR; } -static int +void +TclDisposeFailedCompile( + CompileEnv *envPtr, + Tcl_Size numCommands) +{ + while (envPtr->numCommands > numCommands) { + (void) BA_CmdLocation_Detach(envPtr->cmdMap); + envPtr->numCommands--; + } +} + +static Tcl_Token * CompileCommandTokens( Tcl_Interp *interp, - Tcl_Parse *parsePtr, - CompileEnv *envPtr) + Tcl_Token *commandTokenPtr, + CompileEnv *envPtr, + CmdLocation **cmdLocPtrPtr) { Interp *iPtr = (Interp *) interp; - Tcl_Token *tokenPtr = parsePtr->tokenPtr; + + Tcl_Token *tokenPtr = commandTokenPtr; + Tcl_Size numWords = tokenPtr->numComponents; + const char *commandStart = tokenPtr->start; + Tcl_Size commandSize = tokenPtr->size; + ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr; Tcl_Obj *cmdObj; Command *cmdPtr = NULL; + CmdLocation *cmdLocPtr = NULL; int code = TCL_ERROR; int cmdKnown, expand = -1; - int *wlines, wlineat; - int cmdLine = envPtr->line; - int *clNext = envPtr->clNext; - int cmdIdx = envPtr->numCommands; - int startCodeOffset = envPtr->codeNext - envPtr->codeStart; + Tcl_Size *wlines, wlineat; + Tcl_Size cmdLine = envPtr->line; + Tcl_Size *clNext = envPtr->clNext; + Tcl_Size startCodeOffset = envPtr->codeNext - envPtr->codeStart; int depth = TclGetStackDepth(envPtr); - assert (parsePtr->numWords > 0); + assert (numWords > 0); - /* Pre-Compile */ + /* Precompile */ TclNewObj(cmdObj); + tokenPtr++; envPtr->numCommands++; - EnterCmdStartData(envPtr, cmdIdx, - parsePtr->commandStart - envPtr->source, startCodeOffset); + cmdLocPtr = EnterCmdStartData(envPtr, commandStart - envPtr->source, + startCodeOffset); /* * TIP #280. Scan the words and compute the extended location information. - * The map first contain full per-word line information for use by the + * At first the map first contains full per-word line information for use by the * compiler. This is later replaced by a reduced form which signals * non-literal words, stored in 'wlines'. */ - EnterCmdWordData(eclPtr, parsePtr->commandStart - envPtr->source, - parsePtr->tokenPtr, parsePtr->commandStart, - parsePtr->numWords, cmdLine, + EnterCmdWordData(eclPtr, commandStart - envPtr->source, + tokenPtr, commandStart, numWords, cmdLine, clNext, &wlines, envPtr); wlineat = eclPtr->nuloc - 1; envPtr->line = eclPtr->loc[wlineat].line[0]; envPtr->clNext = eclPtr->loc[wlineat].next[0]; /* Do we know the command word? */ Tcl_IncrRefCount(cmdObj); - tokenPtr = parsePtr->tokenPtr; cmdKnown = TclWordKnownAtCompileTime(tokenPtr, cmdObj); /* Is this a command we should (try to) compile with a compileProc ? */ if (cmdKnown && !(iPtr->flags & DONT_COMPILE_CMDS_INLINE)) { cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj); @@ -2071,198 +2138,191 @@ || (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) { cmdPtr = NULL; } } if (cmdPtr && !(cmdPtr->flags & CMD_COMPILES_EXPANDED)) { - expand = ExpandRequested(parsePtr->tokenPtr, parsePtr->numWords); + expand = ExpandRequested(tokenPtr, numWords); if (expand) { /* We need to expand, but compileProc cannot. */ cmdPtr = NULL; } } } - /* If cmdPtr != NULL, we will try to call cmdPtr->compileProc */ + /* If cmdPtr != NULL, try to call cmdPtr->compileProc */ if (cmdPtr) { - code = CompileCmdCompileProc(interp, parsePtr, cmdPtr, envPtr); + code = CompileCmdCompileProc(interp, commandTokenPtr, cmdPtr, envPtr); } if (code == TCL_ERROR) { if (expand < 0) { - expand = ExpandRequested(parsePtr->tokenPtr, parsePtr->numWords); + expand = ExpandRequested(tokenPtr, numWords); } if (expand) { - CompileExpanded(interp, parsePtr->tokenPtr, - cmdKnown ? cmdObj : NULL, parsePtr->numWords, envPtr); + tokenPtr = CompileExpanded(interp, tokenPtr, + cmdKnown ? cmdObj : NULL, numWords, envPtr); } else { - TclCompileInvocation(interp, parsePtr->tokenPtr, - cmdKnown ? cmdObj : NULL, parsePtr->numWords, envPtr); + tokenPtr = TclCompileInvocation(interp, tokenPtr, + cmdKnown ? cmdObj : NULL, numWords, envPtr); + } + } else { + while (numWords--) { + tokenPtr = TokenAfter(tokenPtr); } } Tcl_DecrRefCount(cmdObj); TclEmitOpcode(INST_POP, envPtr); - EnterCmdExtentData(envPtr, cmdIdx, - parsePtr->term - parsePtr->commandStart, - (envPtr->codeNext-envPtr->codeStart) - startCodeOffset); + cmdLocPtr->numSrcBytes = commandSize; + cmdLocPtr->numCodeBytes = (envPtr->codeNext-envPtr->codeStart) + - startCodeOffset; /* - * TIP #280: Free full form of per-word line data and insert the reduced - * form now + * TIP #280: Free the full form of per-word line data and insert the + * reduced form now. */ envPtr->line = cmdLine; envPtr->clNext = clNext; Tcl_Free(eclPtr->loc[wlineat].line); Tcl_Free(eclPtr->loc[wlineat].next); eclPtr->loc[wlineat].line = wlines; eclPtr->loc[wlineat].next = NULL; + *cmdLocPtrPtr = cmdLocPtr; TclCheckStackDepth(depth, envPtr); - return cmdIdx; + + return tokenPtr; } void TclCompileScript( Tcl_Interp *interp, /* Used for error and status reporting. Also * serves as context for finding and compiling * commands. May not be NULL. */ const char *script, /* The source script to compile. */ - size_t numBytes, /* Number of bytes in script. If -1, the + Tcl_Size numBytes, /* Number of bytes in script. If < 0, the * script consists of all bytes up to the * first null character. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { - int lastCmdIdx = -1; /* Index into envPtr->cmdMapPtr of the last - * command this routine compiles into bytecode. - * Initial value of -1 indicates this routine - * has not yet generated any bytecode. */ - const char *p = script; /* Where we are in our compile. */ + Tcl_Token *lastTokenPtr; + Tcl_Token *tokens; + + if (envPtr->iPtr == NULL) { + Tcl_Panic("TclCompileScript() called on uninitialized CompileEnv"); + } + tokens = TclParseScript(interp, script, numBytes, /* flags */ 0, + &lastTokenPtr, NULL); + CompileScriptTokens(interp, tokens, lastTokenPtr, envPtr); + Tcl_Free(tokens); +} + +static void +CompileScriptTokens( + Tcl_Interp *interp, /* Used for error and status reporting. + * Also serves as context for finding and + * compiling commands. May not be NULL. */ + Tcl_Token *tokens, + Tcl_Token *lastTokenPtr, + CompileEnv *envPtr) /* Holds resulting instructions. */ +{ + Tcl_Token *tokenPtr; + int numCommands = tokens[0].numComponents; int depth = TclGetStackDepth(envPtr); Interp *iPtr = (Interp *) interp; + CmdLocation *cmdLocPtr = NULL; /* Pointer into envPtr->cmdMap for + * the last command this routine + * compiles into bytecode; If we + * exit still value NULL, there + * was no bytecode generated. */ + if (lastTokenPtr < tokens) { + Tcl_Panic("CompileScriptTokens: parse produced no tokens"); + } + if (tokens[0].type != TCL_TOKEN_SCRIPT) { + Tcl_Panic("CompileScriptTokens: invalid token array, expected script"); + } 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; + * 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", (void *)NULL); + TclCompileSyntaxError(interp, envPtr); + return; + } + + tokenPtr = &(tokens[1]); + if (numCommands) { + TclAdvanceLines(&envPtr->line, tokens[0].start, tokenPtr->start); + TclAdvanceContinuations(&envPtr->line, &envPtr->clNext, + tokenPtr->start - envPtr->source); + } + + while (numCommands--) { + int numWords = tokenPtr->numComponents; + const char * commandStart = tokenPtr->start; + + if (tokenPtr > lastTokenPtr) { + Tcl_Panic("CompileScriptTokens: overran token array"); + } + if (tokenPtr->type != TCL_TOKEN_CMD) { + Tcl_Panic("CompileScriptTokens: invalid token array, expected cmd: %d: %.*s", tokenPtr->type, (int)tokenPtr->size, tokenPtr->start); + } + + /* TODO: comment here justifying. */ + if (numWords == 0) { + tokenPtr++; + continue; } #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)); + TclPrintSource(stdout, commandStart, TclMin(tokenPtr->size, 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); + tokenPtr = CompileCommandTokens(interp, tokenPtr, envPtr, &cmdLocPtr); 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) { + if (numCommands) { + TclAdvanceLines(&envPtr->line, commandStart, tokenPtr->start); + TclAdvanceContinuations(&envPtr->line, &envPtr->clNext, + tokenPtr->start - envPtr->source); + } + } + if (tokenPtr <= lastTokenPtr) { + TclCompileTokens(interp, tokenPtr, lastTokenPtr-tokenPtr+1, envPtr); + } else if (cmdLocPtr == NULL) { /* * 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 * simple bytecode that makes that happen. @@ -2279,11 +2339,11 @@ * command compiled, we need to undo that INST_POP so that the result * of the last command becomes the result of the script. The code * here removes that trailing INST_POP. */ - envPtr->cmdMapPtr[lastCmdIdx].numCodeBytes--; + cmdLocPtr->numCodeBytes--; envPtr->codeNext--; envPtr->currStackDepth++; } TclCheckStackDepth(depth+1, envPtr); } @@ -2291,12 +2351,12 @@ /* *---------------------------------------------------------------------- * * TclCompileTokens -- * - * Given an array of tokens parsed from a Tcl command (e.g., the tokens - * that make up a word) this procedure emits instructions to evaluate the + * Given an array of tokens parsed from a Tcl command, e.g. the tokens + * that make up a word, emits instructions to evaluate the * tokens and concatenate their values to form a single result value on * the interpreter's runtime evaluation stack. * * Results: * The return value is a standard Tcl result. If an error occurs, an @@ -2314,12 +2374,13 @@ Tcl_Interp *interp, Tcl_Token *tokenPtr, CompileEnv *envPtr) { const char *p, *name = tokenPtr[1].start; - size_t i, nameBytes = tokenPtr[1].size; - int localVar, localVarName = 1; + Tcl_Size i, nameBytes = tokenPtr[1].size; + Tcl_Size localVar; + int localVarName = 1; /* * Determine how the variable name should be handled: if it contains any * namespace qualifiers it is not a local variable (localVarName=-1); if * it looks like an array element and the token has a single component, it @@ -2382,38 +2443,37 @@ 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. + Tcl_Size 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; + Tcl_Size i, numObjsToConcat, adjust; size_t length; unsigned char *entryCodeNext = envPtr->codeNext; #define NUM_STATIC_POS 20 - int isLiteral, maxNumCL, numCL; - int *clPosition = NULL; + int isLiteral; + Tcl_Size maxNumCL, numCL; + Tcl_Size *clPosition = NULL; int depth = TclGetStackDepth(envPtr); /* - * 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. + * 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; @@ -2425,11 +2485,11 @@ } } if (isLiteral) { maxNumCL = NUM_STATIC_POS; - clPosition = (int *)Tcl_Alloc(maxNumCL * sizeof(int)); + clPosition = (Tcl_Size *)Tcl_Alloc(maxNumCL * sizeof(Tcl_Size)); } adjust = 0; Tcl_DStringInit(&textBuffer); numObjsToConcat = 0; @@ -2445,67 +2505,40 @@ length = TclParseBackslash(tokenPtr->start, tokenPtr->size, NULL, buffer); Tcl_DStringAppend(&textBuffer, buffer, length); /* - * If the backslash sequence we found is in a literal, and - * represented a continuation line, we compute and store its + * If the identified backslash sequence is in a literal and + * represented a continuation line, compute and store its * location (as char offset to the beginning of the _result_ * script). We may have to extend the table of locations. * - * Note that the continuation line information is relevant even if - * the word we are processing is not a literal, as it can affect - * nested commands. See the branch for TCL_TOKEN_COMMAND below, - * where the adjustment we are tracking here is taken into - * 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. + * 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 = (int *)Tcl_Realloc(clPosition, - maxNumCL * sizeof(int)); + clPosition = (Tcl_Size *)Tcl_Realloc(clPosition, + maxNumCL * sizeof(Tcl_Size)); } clPosition[numCL] = clPos; numCL ++; } adjust++; } break; - case TCL_TOKEN_COMMAND: - /* - * Push any accumulated chars appearing before the command. - */ - - if (Tcl_DStringLength(&textBuffer) > 0) { - int literal = TclRegisterDStringLiteral(envPtr, &textBuffer); - - TclEmitPush(literal, envPtr); - numObjsToConcat++; - Tcl_DStringFree(&textBuffer); - - if (numCL) { - TclContinuationsEnter(TclFetchLiteral(envPtr, literal), - numCL, clPosition); - } - numCL = 0; - } - - envPtr->line += adjust; - TclCompileScript(interp, tokenPtr->start+1, - tokenPtr->size-2, envPtr); - envPtr->line -= adjust; - numObjsToConcat++; - break; - case TCL_TOKEN_VARIABLE: /* * Push any accumulated chars appearing before the $. */ @@ -2521,10 +2554,43 @@ TclCompileVarSubst(interp, tokenPtr, envPtr); numObjsToConcat++; count -= tokenPtr->numComponents; tokenPtr += tokenPtr->numComponents; break; + + case TCL_TOKEN_SCRIPT_SUBST: + /* + * Push any accumulated chars appearing before the command. + */ + + if (Tcl_DStringLength(&textBuffer) > 0) { + int literal = TclRegisterDStringLiteral(envPtr, &textBuffer); + TclEmitPush(literal, envPtr); + numObjsToConcat++; + Tcl_DStringFree(&textBuffer); + } + + if (count <= tokenPtr->numComponents) { + Tcl_Panic("token components overflow token array"); + } + + envPtr->line += adjust; + CompileScriptTokens(interp, tokenPtr+1, + tokenPtr + (tokenPtr->numComponents), envPtr); + envPtr->line -= adjust; + numObjsToConcat++; + count -= tokenPtr->numComponents; + tokenPtr += tokenPtr->numComponents; + break; + + case TCL_TOKEN_ERROR: + /* Compile bytecodes to report the parse error at runtime. */ + TclSubstTokens(interp, tokenPtr, 1, NULL, 1, NULL, NULL, 0); + Tcl_LogCommandInfo(interp, envPtr->source, + tokenPtr->start, tokenPtr->size); + TclCompileSyntaxError(interp, envPtr); + goto done; default: Tcl_Panic("Unexpected token type in TclCompileTokens: %d; %.*s", tokenPtr->type, (int)tokenPtr->size, tokenPtr->start); } @@ -2563,10 +2629,11 @@ */ if (envPtr->codeNext == entryCodeNext) { PushStringLiteral(envPtr, ""); } +done: Tcl_DStringFree(&textBuffer); /* * Release the temp table we used to collect the locations of continuation * lines, if any. @@ -2582,17 +2649,17 @@ *---------------------------------------------------------------------- * * TclCompileCmdWord -- * * Given an array of parse tokens for a word containing one or more Tcl - * commands, emit inline instructions to execute them. This procedure - * differs from TclCompileTokens in that a simple word such as a loop - * body enclosed in braces is not just pushed as a string, but is itself - * parsed into tokens and compiled. + * commands, emits inline instructions to execute them. In contrast with + * TclCompileTokens, a simple word such as a loop body enclosed in braces + * is not just pushed as a string, but is itself parsed into tokens and + * compiled. * * Results: - * The return value is a standard Tcl result. If an error occurs, an + * A standard Tcl result. If an error occurs, an * error message is left in the interpreter's result. * * Side effects: * Instructions are added to envPtr to execute the tokens at runtime. * @@ -2602,26 +2669,28 @@ 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. + Tcl_Size count1, /* Number of tokens to consider at tokenPtr. * Must be at least 1. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { + int count = count1; + if ((count == 1) && (tokenPtr->type == TCL_TOKEN_TEXT)) { /* - * Handle the common case: if there is a single text token, compile it + * The common case that there is a single text token. Compile it * into an inline sequence of instructions. */ TclCompileScript(interp, tokenPtr->start, tokenPtr->size, envPtr); } else { /* - * Multiple tokens or the single token involves substitutions. Emit - * instructions to invoke the eval command procedure at runtime on the - * result of evaluating the tokens. + * Either there are multiple tokens, or the single token involves + * substitutions. Emit instructions to invoke the eval command + * procedure at runtime on the result of evaluating the tokens. */ TclCompileTokens(interp, tokenPtr, count, envPtr); TclEmitInvoke(envPtr, INST_EVAL_STK); } @@ -2631,17 +2700,16 @@ *---------------------------------------------------------------------- * * 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. + * 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: - * The return value is a standard Tcl result. If an error occurs, an + * A standard Tcl result. If an error occurs, an * error message is left in the interpreter's result. * * Side effects: * Instructions are added to envPtr to execute the expression. * @@ -2652,17 +2720,18 @@ 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. + Tcl_Size 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. */ @@ -2699,14 +2768,14 @@ /* *---------------------------------------------------------------------- * * TclCompileNoOp -- * - * Function called to compile no-op's + * Compiles no-op's * * Results: - * The return value is TCL_OK, indicating successful compilation. + * TCL_OK if completion was successful. * * Side effects: * Instructions are added to envPtr to execute a no-op at runtime. No * result is pushed onto the stack: the compiler has to take care of this * itself if the last compiled command is a NoOp. @@ -2721,11 +2790,11 @@ * created by Tcl_ParseCommand. */ TCL_UNUSED(Command *), CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; - int i; + Tcl_Size i; tokenPtr = parsePtr->tokenPtr; for (i = 1; i < parsePtr->numWords; i++) { tokenPtr = tokenPtr + tokenPtr->numComponents + 1; @@ -2741,18 +2810,18 @@ /* *---------------------------------------------------------------------- * * TclInitByteCodeObj -- * - * Create a ByteCode structure and initialize it from a CompileEnv + * Creates a ByteCode structure and initializes it from a CompileEnv * compilation environment structure. The ByteCode structure is smaller * and contains just that information needed to execute the bytecode * instructions resulting from compiling a Tcl script. The resulting * structure is placed in the specified object. * * Results: - * A newly constructed ByteCode object is stored in the internal + * A newly-constructed ByteCode object is stored in the internal * representation of the objPtr. * * Side effects: * A single heap object is allocated to hold the new ByteCode structure * and its code, object, command location, and aux data arrays. Note that @@ -2766,34 +2835,30 @@ 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; - } + Tcl_HashEntry *hePtr = Tcl_FindHashEntry(&envPtr->litMap, objPtr); + if (hePtr) { + /* + * 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. + */ + size_t numBytes; + size_t i = PTR2INT(Tcl_GetHashValue(hePtr)); + const char *bytes = Tcl_GetStringFromObj(objPtr, &numBytes); + + envPtr->literalArrayPtr[i] = Tcl_NewStringObj(bytes, numBytes); + Tcl_IncrRefCount(envPtr->literalArrayPtr[i]); + TclReleaseLiteral((Tcl_Interp *)envPtr->iPtr, objPtr); } } ByteCode * TclInitByteCode( @@ -2800,41 +2865,44 @@ CompileEnv *envPtr)/* Points to the CompileEnv structure from * which to create a ByteCode structure. */ { ByteCode *codePtr; size_t codeBytes, objArrayBytes, exceptArrayBytes, cmdLocBytes; - size_t auxDataArrayBytes, structureSize; + size_t structureSize; unsigned char *p; #ifdef TCL_COMPILE_DEBUG unsigned char *nextPtr; #endif int numLitObjects = envPtr->literalArrayNext; Namespace *namespacePtr; - int i, isNew; + int isNew; Interp *iPtr; if (envPtr->iPtr == NULL) { Tcl_Panic("TclInitByteCodeObj() called on uninitialized CompileEnv"); } iPtr = envPtr->iPtr; codeBytes = envPtr->codeNext - envPtr->codeStart; - objArrayBytes = envPtr->literalArrayNext * sizeof(Tcl_Obj *); + objArrayBytes = envPtr->mallocedLiteralArray ? 0 : + envPtr->literalArrayNext * sizeof(Tcl_Obj *); exceptArrayBytes = envPtr->exceptArrayNext * sizeof(ExceptionRange); - auxDataArrayBytes = envPtr->auxDataArrayNext * sizeof(AuxData); cmdLocBytes = GetCmdLocEncodingSize(envPtr); /* * Compute the total number of bytes needed for this bytecode. + * + * Note that code bytes need not be aligned but since later elements are we + * need to pad anyway, either directly after ByteCode or after codeBytes, + * and it's easier and more consistent to do the former. */ - structureSize = sizeof(ByteCode); + structureSize = TCL_ALIGN(sizeof(ByteCode)); /* align code bytes */ structureSize += TCL_ALIGN(codeBytes); /* align object array */ structureSize += TCL_ALIGN(objArrayBytes); /* align exc range arr */ structureSize += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */ - structureSize += auxDataArrayBytes; structureSize += cmdLocBytes; if (envPtr->iPtr->varFramePtr != NULL) { namespacePtr = envPtr->iPtr->varFramePtr->nsPtr; } else { @@ -2860,42 +2928,40 @@ codePtr->numCommands = envPtr->numCommands; codePtr->numSrcBytes = envPtr->numSrcBytes; codePtr->numCodeBytes = codeBytes; codePtr->numLitObjects = numLitObjects; codePtr->numExceptRanges = envPtr->exceptArrayNext; - codePtr->numAuxDataItems = envPtr->auxDataArrayNext; codePtr->numCmdLocBytes = cmdLocBytes; codePtr->maxExceptDepth = envPtr->maxExceptDepth; codePtr->maxStackDepth = envPtr->maxStackDepth; - p += sizeof(ByteCode); + p += TCL_ALIGN(sizeof(ByteCode)); /* align code bytes */ codePtr->codeStart = p; memcpy(p, envPtr->codeStart, codeBytes); - p += TCL_ALIGN(codeBytes); /* align object array */ - codePtr->objArrayPtr = (Tcl_Obj **) p; - for (i = 0; i < numLitObjects; i++) { - codePtr->objArrayPtr[i] = TclFetchLiteral(envPtr, i); + + if (envPtr->mallocedLiteralArray) { + codePtr->objArrayPtr = envPtr->literalArrayPtr; + codePtr->flags |= TCL_BYTECODE_FREE_LITERALS; + } else { + codePtr->objArrayPtr = (Tcl_Obj **) p; + memcpy(p, envPtr->literalArrayPtr, (size_t) objArrayBytes); + p += TCL_ALIGN(objArrayBytes); /* align exception range array */ } - p += TCL_ALIGN(objArrayBytes); /* align exception range array */ if (exceptArrayBytes > 0) { codePtr->exceptArrayPtr = (ExceptionRange *) p; memcpy(p, envPtr->exceptArrayPtr, exceptArrayBytes); } else { codePtr->exceptArrayPtr = NULL; } - p += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */ - if (auxDataArrayBytes > 0) { - codePtr->auxDataArrayPtr = (AuxData *) p; - memcpy(p, envPtr->auxDataArrayPtr, auxDataArrayBytes); - } else { - codePtr->auxDataArrayPtr = NULL; - } - - p += auxDataArrayBytes; + p += exceptArrayBytes; + + codePtr->auxData = envPtr->auxData; + envPtr->auxData = NULL; + #ifndef TCL_COMPILE_DEBUG EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p); #else nextPtr = EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p); if (((size_t)(nextPtr - p)) != cmdLocBytes) { @@ -2950,11 +3016,11 @@ /* * Free the old internal rep then convert the object to a bytecode object * by making its internal rep point to the just compiled ByteCode. */ - ByteCodeSetIntRep(objPtr, typePtr, codePtr); + ByteCodeSetInternalRep(objPtr, typePtr, codePtr); return codePtr; } /* *---------------------------------------------------------------------- @@ -2979,23 +3045,23 @@ * variable is unknown, or if the name is NULL. * *---------------------------------------------------------------------- */ -int +Tcl_Size TclFindCompiledLocal( const char *name, /* Points to first character of the name of a * scalar or array variable. If NULL, a * temporary var should be created. */ - size_t nameBytes, /* Number of bytes in the name. */ + Tcl_Size nameBytes, /* Number of bytes in the name. */ int create, /* If 1, allocate a local frame entry for the * variable if it is new. */ CompileEnv *envPtr) /* Points to the current compile environment*/ { CompiledLocal *localPtr; - int localVar = -1; - int i; + Tcl_Size localVar = TCL_INDEX_NONE; + Tcl_Size i; Proc *procPtr; /* * If not creating a temporary, does a local variable of the specified * name already exist? @@ -3010,30 +3076,30 @@ */ LocalCache *cachePtr = envPtr->iPtr->varFramePtr->localCachePtr; const char *localName; Tcl_Obj **varNamePtr; - size_t len; + Tcl_Size len; if (!cachePtr || !name) { - return -1; + return TCL_INDEX_NONE; } varNamePtr = &cachePtr->varName0; for (i=0; i < cachePtr->numVars; varNamePtr++, i++) { if (*varNamePtr) { - localName = TclGetStringFromObj(*varNamePtr, &len); + localName = Tcl_GetStringFromObj(*varNamePtr, &len); if ((len == nameBytes) && !strncmp(name, localName, len)) { return i; } } } - return -1; + return TCL_INDEX_NONE; } if (name != NULL) { - int localCt = procPtr->numCompiledLocals; + Tcl_Size localCt = procPtr->numCompiledLocals; localPtr = procPtr->firstLocalPtr; for (i = 0; i < localCt; i++) { if (!TclIsVarTemporary(localPtr)) { char *localName = localPtr->name; @@ -3051,11 +3117,11 @@ * Create a new variable if appropriate. */ if (create || (name == NULL)) { localVar = procPtr->numCompiledLocals; - localPtr = (CompiledLocal *)Tcl_Alloc(offsetof(CompiledLocal, name) + nameBytes + 1); + localPtr = (CompiledLocal *)Tcl_Alloc(offsetof(CompiledLocal, name) + 1U + nameBytes); if (procPtr->firstLocalPtr == NULL) { procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr; } else { procPtr->lastLocalPtr->nextPtr = localPtr; procPtr->lastLocalPtr = localPtr; @@ -3082,20 +3148,19 @@ /* *---------------------------------------------------------------------- * * TclExpandCodeArray -- * - * Procedure that uses malloc to allocate more storage for a CompileEnv's - * code array. + * 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. + * 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 @@ -3118,12 +3183,12 @@ if (envPtr->mallocedCodeArray) { envPtr->codeStart = (unsigned char *)Tcl_Realloc(envPtr->codeStart, newBytes); } else { /* - * envPtr->codeStart isn't a Tcl_Alloc'd pointer, so we must code a - * Tcl_Realloc equivalent for ourselves. + * envPtr->exceptArrayPtr isn't a Tcl_Alloc'd pointer, so + * perform the equivalent of Tcl_Realloc directly. */ unsigned char *newPtr = (unsigned char *)Tcl_Alloc(newBytes); memcpy(newPtr, envPtr->codeStart, currBytes); @@ -3153,113 +3218,24 @@ * environment's CmdLocation array is grown if necessary. * *---------------------------------------------------------------------- */ -static void +static CmdLocation * 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). - */ - - size_t currElems = envPtr->cmdMapEnd; - size_t newElems = 2 * currElems; - size_t currBytes = currElems * sizeof(CmdLocation); - size_t newBytes = newElems * sizeof(CmdLocation); - - if (envPtr->mallocedCmdMap) { - envPtr->cmdMapPtr = (CmdLocation *)Tcl_Realloc(envPtr->cmdMapPtr, newBytes); - } else { - /* - * envPtr->cmdMapPtr isn't a Tcl_Alloc'd pointer, so we must code a - * Tcl_Realloc equivalent for ourselves. - */ - - CmdLocation *newPtr = (CmdLocation *)Tcl_Alloc(newBytes); - - memcpy(newPtr, envPtr->cmdMapPtr, currBytes); - envPtr->cmdMapPtr = newPtr; - envPtr->mallocedCmdMap = 1; - } - envPtr->cmdMapEnd = newElems; - } - - if (cmdIndex > 0) { - if (codeOffset < envPtr->cmdMapPtr[cmdIndex-1].codeOffset) { - Tcl_Panic("EnterCmdStartData: cmd map not sorted by code offset"); - } - } - - cmdLocPtr = &envPtr->cmdMapPtr[cmdIndex]; + Tcl_Size srcOffset, /* Offset of first char of the command. */ + Tcl_Size codeOffset) /* Offset of first byte of command code. */ +{ + CmdLocation *cmdLocPtr = BA_CmdLocation_Append(envPtr->cmdMap); cmdLocPtr->codeOffset = codeOffset; cmdLocPtr->srcOffset = srcOffset; - cmdLocPtr->numSrcBytes = -1; - cmdLocPtr->numCodeBytes = -1; -} - -/* - *---------------------------------------------------------------------- - * - * EnterCmdExtentData -- - * - * Registers the source and bytecode length for a command. This - * information is used at runtime to map between instruction pc and - * source locations. - * - * Results: - * None. - * - * Side effects: - * Inserts source and code length information into the compilation - * environment envPtr for the command at index cmdIndex. Starting source - * and bytecode information for the command must already have been - * registered. - * - *---------------------------------------------------------------------- - */ - -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; + cmdLocPtr->numSrcBytes = TCL_INDEX_NONE; + cmdLocPtr->numCodeBytes = TCL_INDEX_NONE; + return cmdLocPtr; } /* *---------------------------------------------------------------------- * TIP #280 @@ -3283,22 +3259,24 @@ static void EnterCmdWordData( ExtCmdLoc *eclPtr, /* Points to the map environment structure in * which to enter command location * information. */ - int srcOffset, /* Offset of first char of the command. */ + Tcl_Size srcOffset, /* Offset of first char of the command. */ Tcl_Token *tokenPtr, const char *cmd, - int numWords, - int line, - int *clNext, - int **wlines, + Tcl_Size numWords, + Tcl_Size line, + Tcl_Size *clNext, + Tcl_Size **wlines, CompileEnv *envPtr) { ECL *ePtr; const char *last; - int wordIdx, wordLine, *wwlines, *wordNext; + Tcl_Size wordIdx, wordLine; + Tcl_Size *wwlines; + Tcl_Size *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 @@ -3313,14 +3291,14 @@ eclPtr->nloc = newElems; } ePtr = &eclPtr->loc[eclPtr->nuloc]; ePtr->srcOffset = srcOffset; - ePtr->line = (int *)Tcl_Alloc(numWords * sizeof(int)); - ePtr->next = (int **)Tcl_Alloc(numWords * sizeof(int *)); + ePtr->line = (Tcl_Size *)Tcl_Alloc(numWords * sizeof(Tcl_Size)); + ePtr->next = (Tcl_Size **)Tcl_Alloc(numWords * sizeof(Tcl_Size *)); ePtr->nline = numWords; - wwlines = (int *)Tcl_Alloc(numWords * sizeof(int)); + wwlines = (Tcl_Size *)Tcl_Alloc(numWords * sizeof(Tcl_Size)); last = cmd; wordLine = line; wordNext = clNext; for (wordIdx=0 ; wordIdxexceptArrayNext; + 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) @@ -3379,11 +3357,11 @@ */ size_t currBytes = envPtr->exceptArrayNext * sizeof(ExceptionRange); size_t currBytes2 = envPtr->exceptArrayNext * sizeof(ExceptionAux); - int newElems = 2*envPtr->exceptArrayEnd; + size_t newElems = 2*envPtr->exceptArrayEnd; size_t newBytes = newElems * sizeof(ExceptionRange); size_t newBytes2 = newElems * sizeof(ExceptionAux); if (envPtr->mallocedExceptArray) { envPtr->exceptArrayPtr = @@ -3410,20 +3388,20 @@ envPtr->exceptArrayNext++; rangePtr = &envPtr->exceptArrayPtr[index]; rangePtr->type = type; rangePtr->nestingLevel = envPtr->exceptDepth; - rangePtr->codeOffset = -1; - rangePtr->numCodeBytes = -1; - rangePtr->breakOffset = -1; - rangePtr->continueOffset = -1; - rangePtr->catchOffset = -1; + rangePtr->codeOffset = TCL_INDEX_NONE; + rangePtr->numCodeBytes = TCL_INDEX_NONE; + rangePtr->breakOffset = TCL_INDEX_NONE; + rangePtr->continueOffset = TCL_INDEX_NONE; + rangePtr->catchOffset = TCL_INDEX_NONE; auxPtr = &envPtr->exceptAuxArrayPtr[index]; auxPtr->supportsContinue = 1; auxPtr->stackDepth = envPtr->currStackDepth; auxPtr->expandTarget = envPtr->expandCount; - auxPtr->expandTargetDepth = -1; + auxPtr->expandTargetDepth = TCL_INDEX_NONE; auxPtr->numBreakTargets = 0; auxPtr->breakTargets = NULL; auxPtr->allocBreakTargets = 0; auxPtr->numContinueTargets = 0; auxPtr->continueTargets = NULL; @@ -3435,11 +3413,11 @@ * --------------------------------------------------------------------- * * TclGetInnermostExceptionRange -- * * Returns the innermost exception range that covers the current code - * creation point, and (optionally) the stack depth that is expected at + * creation point, and optionally the stack depth that is expected at * that point. Relies on the fact that the range has a numCodeBytes = -1 * when it is being populated and that inner ranges come after outer * ranges. * * --------------------------------------------------------------------- @@ -3449,19 +3427,19 @@ TclGetInnermostExceptionRange( CompileEnv *envPtr, int returnCode, ExceptionAux **auxPtrPtr) { - int i = envPtr->exceptArrayNext; + size_t i = envPtr->exceptArrayNext; ExceptionRange *rangePtr = envPtr->exceptArrayPtr + i; while (i > 0) { rangePtr--; i--; - if (CurrentOffset(envPtr) >= rangePtr->codeOffset && - (rangePtr->numCodeBytes == -1 || CurrentOffset(envPtr) < - rangePtr->codeOffset+rangePtr->numCodeBytes) && + if (CurrentOffset(envPtr) >= (int)rangePtr->codeOffset && + (rangePtr->numCodeBytes == TCL_INDEX_NONE || CurrentOffset(envPtr) < + (int)rangePtr->codeOffset+(int)rangePtr->numCodeBytes) && (returnCode != TCL_CONTINUE || envPtr->exceptAuxArrayPtr[i].supportsContinue)) { if (auxPtrPtr) { *auxPtrPtr = envPtr->exceptAuxArrayPtr + i; @@ -3477,11 +3455,11 @@ * * TclAddLoopBreakFixup, TclAddLoopContinueFixup -- * * Adds a place that wants to break/continue to the loop exception range * tracking that will be fixed up once the loop can be finalized. These - * functions will generate an INST_JUMP4 that will be fixed up during the + * functions generate an INST_JUMP4 that is fixed up during the * loop finalization. * * --------------------------------------------------------------------- */ @@ -3498,15 +3476,15 @@ if (++auxPtr->numBreakTargets > auxPtr->allocBreakTargets) { auxPtr->allocBreakTargets *= 2; auxPtr->allocBreakTargets += 2; if (auxPtr->breakTargets) { - auxPtr->breakTargets = (unsigned int *)Tcl_Realloc(auxPtr->breakTargets, - sizeof(int) * auxPtr->allocBreakTargets); + auxPtr->breakTargets = (size_t *)Tcl_Realloc(auxPtr->breakTargets, + sizeof(size_t) * auxPtr->allocBreakTargets); } else { auxPtr->breakTargets = - (unsigned int *)Tcl_Alloc(sizeof(int) * auxPtr->allocBreakTargets); + (size_t *)Tcl_Alloc(sizeof(size_t) * auxPtr->allocBreakTargets); } } auxPtr->breakTargets[auxPtr->numBreakTargets - 1] = CurrentOffset(envPtr); TclEmitInstInt4(INST_JUMP4, 0, envPtr); } @@ -3524,15 +3502,15 @@ if (++auxPtr->numContinueTargets > auxPtr->allocContinueTargets) { auxPtr->allocContinueTargets *= 2; auxPtr->allocContinueTargets += 2; if (auxPtr->continueTargets) { - auxPtr->continueTargets = (unsigned int *)Tcl_Realloc(auxPtr->continueTargets, - sizeof(int) * auxPtr->allocContinueTargets); + auxPtr->continueTargets = (size_t *)Tcl_Realloc(auxPtr->continueTargets, + sizeof(size_t) * auxPtr->allocContinueTargets); } else { auxPtr->continueTargets = - (unsigned int *)Tcl_Alloc(sizeof(int) * auxPtr->allocContinueTargets); + (size_t *)Tcl_Alloc(sizeof(size_t) * auxPtr->allocContinueTargets); } } auxPtr->continueTargets[auxPtr->numContinueTargets - 1] = CurrentOffset(envPtr); TclEmitInstInt4(INST_JUMP4, 0, envPtr); @@ -3541,12 +3519,12 @@ /* * --------------------------------------------------------------------- * * TclCleanupStackForBreakContinue -- * - * Ditch the extra elements from the auxiliary stack and the main stack. - * How to do this exactly depends on whether there are any elements on + * Removes the extra elements from the auxiliary stack and the main stack. + * How this is done depends on whether there are any elements on * the auxiliary stack to pop. * * --------------------------------------------------------------------- */ @@ -3553,18 +3531,18 @@ void TclCleanupStackForBreakContinue( CompileEnv *envPtr, ExceptionAux *auxPtr) { - int savedStackDepth = envPtr->currStackDepth; + size_t savedStackDepth = envPtr->currStackDepth; int toPop = envPtr->expandCount - auxPtr->expandTarget; if (toPop > 0) { while (toPop --> 0) { TclEmitOpcode(INST_EXPAND_DROP, envPtr); } - TclAdjustStackDepth(auxPtr->expandTargetDepth - envPtr->currStackDepth, + TclAdjustStackDepth((int)(auxPtr->expandTargetDepth - envPtr->currStackDepth), envPtr); envPtr->currStackDepth = auxPtr->expandTargetDepth; } toPop = envPtr->currStackDepth - auxPtr->stackDepth; while (toPop --> 0) { @@ -3596,37 +3574,37 @@ /* * Update inner exception ranges with information about the environment * where this expansion started. */ - for (i=0 ; iexceptArrayNext ; i++) { + for (i=0 ; i<(int)envPtr->exceptArrayNext ; i++) { ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i]; ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[i]; /* * Ignore loops unless they're still being built. */ - if (rangePtr->codeOffset > CurrentOffset(envPtr)) { + if ((int)rangePtr->codeOffset > CurrentOffset(envPtr)) { continue; } - if (rangePtr->numCodeBytes != -1) { + if (rangePtr->numCodeBytes != TCL_INDEX_NONE) { continue; } /* - * Adequate condition: further out loops and further in exceptions + * Adequate condition: loops further out and exceptions further in * don't actually need this information. */ if (auxPtr->expandTarget == envPtr->expandCount) { auxPtr->expandTargetDepth = envPtr->currStackDepth; } } /* - * There's now one more expansion being processed on the auxiliary stack. + * One more expansion is now being processed on the auxiliary stack. */ envPtr->expandCount++; } @@ -3635,11 +3613,11 @@ * * TclFinalizeLoopExceptionRange -- * * Finalizes a loop exception range, binding the registered [break] and * [continue] implementations so that they jump to the correct place. - * Note that this must only be called after *all* the exception range + * This must be called only after *all* the exception range * target offsets have been set. * * --------------------------------------------------------------------- */ @@ -3660,18 +3638,18 @@ /* * 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 ; inumBreakTargets ; i++) { + for (i=0 ; i<(int)auxPtr->numBreakTargets ; i++) { site = envPtr->codeStart + auxPtr->breakTargets[i]; offset = rangePtr->breakOffset - auxPtr->breakTargets[i]; TclUpdateInstInt4AtPc(INST_JUMP4, offset, site); } - for (i=0 ; inumContinueTargets ; i++) { + for (i=0 ; i<(int)auxPtr->numContinueTargets ; i++) { site = envPtr->codeStart + auxPtr->continueTargets[i]; - if (rangePtr->continueOffset == -1) { + if (rangePtr->continueOffset == TCL_INDEX_NONE) { int j; /* * WTF? Can't bind, so revert to an INST_CONTINUE. Not enough * space to do anything else. @@ -3704,198 +3682,85 @@ } /* *---------------------------------------------------------------------- * + * TclFetchAuxData -- + * + * Fetch back from the CompileEnv an item of AuxData stored at + * index. + * + * Results: + * The ClientData previously stored by TclCreatAuxData(). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +ClientData +TclFetchAuxData( + CompileEnv *envPtr, /* CompileEnv from which to fetch */ + size_t index) /* Index of AuxData to fetch */ +{ + if (envPtr->auxData == NULL) { + return NULL; + } + return BA_AuxData_At(envPtr->auxData, index)->clientData; +} + +/* + *---------------------------------------------------------------------- + * * TclCreateAuxData -- * - * Procedure that allocates and initializes a new AuxData structure in a + * Allocates and initializes a new AuxData structure in a * CompileEnv's array of compilation auxiliary data records. These * AuxData records hold information created during compilation by * CompileProcs and used by instructions during execution. * * Results: - * Returns the index for the newly created AuxData structure. + * The index of the newly-created AuxData structure in the array. * * Side effects: - * If there is not enough room in the CompileEnv's AuxData array, the - * 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. + * The CompileEnv's AuxData Brodnik array grows as needed. * *---------------------------------------------------------------------- */ -int +Tcl_Size TclCreateAuxData( - ClientData clientData, /* The compilation auxiliary data to store in + void *clientData, /* The compilation auxiliary data to store in * the new aux data record. */ const AuxDataType *typePtr, /* Pointer to the type to attach to this * AuxData */ CompileEnv *envPtr)/* Points to the CompileEnv for which a new * aux data structure is to be allocated. */ { - int index; /* Index for the new AuxData structure. */ - 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 { - /* - * envPtr->auxDataArrayPtr isn't a Tcl_Alloc'd pointer, so we must - * code a Tcl_Realloc equivalent for ourselves. - */ - - AuxData *newPtr = (AuxData *)Tcl_Alloc(newBytes); - - memcpy(newPtr, envPtr->auxDataArrayPtr, currBytes); - envPtr->auxDataArrayPtr = newPtr; - envPtr->mallocedAuxDataArray = 1; - } - envPtr->auxDataArrayEnd = newElems; - } - envPtr->auxDataArrayNext++; - - auxDataPtr = &envPtr->auxDataArrayPtr[index]; + AuxData *auxDataPtr; /* Points to the new AuxData structure */ + + if (envPtr->auxData == NULL) { + envPtr->auxData = BA_AuxData_Create(); + } + + auxDataPtr = BA_AuxData_Append(envPtr->auxData); auxDataPtr->clientData = clientData; auxDataPtr->type = typePtr; - return index; -} - -/* - *---------------------------------------------------------------------- - * - * TclInitJumpFixupArray -- - * - * Initializes a JumpFixupArray structure to hold some number of jump - * fixup entries. - * - * Results: - * None. - * - * Side effects: - * The JumpFixupArray structure is initialized. - * - *---------------------------------------------------------------------- - */ - -void -TclInitJumpFixupArray( - JumpFixupArray *fixupArrayPtr) - /* Points to the JumpFixupArray structure to - * initialize. */ -{ - fixupArrayPtr->fixup = fixupArrayPtr->staticFixupSpace; - fixupArrayPtr->next = 0; - fixupArrayPtr->end = JUMPFIXUP_INIT_ENTRIES - 1; - fixupArrayPtr->mallocedArray = 0; -} - -/* - *---------------------------------------------------------------------- - * - * 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 - * the old array is freed. Jump fixup structures are copied from the old - * array to the new one. - * - *---------------------------------------------------------------------- - */ - -void -TclExpandJumpFixupArray( - JumpFixupArray *fixupArrayPtr) - /* Points to the JumpFixupArray structure to - * enlarge. */ -{ - /* - * 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 - * Tcl_Realloc equivalent for ourselves. - */ - - JumpFixup *newPtr = (JumpFixup *)Tcl_Alloc(newBytes); - - memcpy(newPtr, fixupArrayPtr->fixup, currBytes); - fixupArrayPtr->fixup = newPtr; - fixupArrayPtr->mallocedArray = 1; - } - fixupArrayPtr->end = newElems; -} - -/* - *---------------------------------------------------------------------- - * - * TclFreeJumpFixupArray -- - * - * Free any storage allocated in a jump fixup array structure. - * - * Results: - * None. - * - * Side effects: - * Allocated storage in the JumpFixupArray structure is freed. - * - *---------------------------------------------------------------------- - */ - -void -TclFreeJumpFixupArray( - JumpFixupArray *fixupArrayPtr) - /* Points to the JumpFixupArray structure to - * free. */ -{ - if (fixupArrayPtr->mallocedArray) { - Tcl_Free(fixupArrayPtr->fixup); - } + return BA_AuxData_Size(envPtr->auxData) - 1; } /* *---------------------------------------------------------------------- * * 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. + * 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: @@ -3946,20 +3811,21 @@ /* *---------------------------------------------------------------------- * * TclFixupForwardJump -- * - * Procedure that updates a previously-emitted forward jump to jump a - * specified number of bytes, "jumpDist". If necessary, the jump is grown - * from two to five bytes; this is done if the jump distance is greater - * than "distThreshold" (normally 127 bytes). The jump is described by a - * JumpFixup record previously initialized by TclEmitForwardJump. + * Modifies a previously-emitted forward jump to jump a specified number + * of bytes, "jumpDist". If necessary, the size of the jump instruction is + * increased from two to five bytes. This is done if the jump distance is + * greater than "distThreshold" (normally 127 bytes). The jump is + * described by a JumpFixup record previously initialized by + * TclEmitForwardJump. * * Results: - * 1 if the jump was grown and subsequent instructions had to be moved; - * otherwise 0. This result is returned to allow callers to update any - * additional code offsets they may hold. + * 1 if the jump was grown and subsequent instructions had to be moved, or + * 0 otherwsie. This allows callers to update any additional code offsets + * they may hold. * * Side effects: * The jump may be grown and subsequent instructions moved. If this * happens, the code offsets for any commands and any ExceptionRange * records between the jump and the current code address will be updated @@ -3978,12 +3844,14 @@ int jumpDist, /* Jump distance to set in jump instr. */ int distThreshold) /* Maximum distance before the two byte jump * is grown to five bytes. */ { unsigned char *jumpPc, *p; - int firstCmd, lastCmd, firstRange, lastRange, k; + int firstRange, lastRange, k; size_t numBytes; + CmdLocation *cmdLocPtr = NULL; + BP_CmdLocation ptr; if (jumpDist <= distThreshold) { jumpPc = envPtr->codeStart + jumpFixupPtr->codeOffset; switch (jumpFixupPtr->jumpType) { case TCL_UNCONDITIONAL_JUMP: @@ -3998,14 +3866,14 @@ } return 0; } /* - * We must grow the jump then move subsequent instructions down. Note that - * if we expand the space for generated instructions, code addresses might - * change; be careful about updating any of these addresses held in - * variables. + * Increase the size of the jump instruction, and then move subsequent + * instructions down. Expanding the space for generated instructions means + * that code addresses might change. Be careful about updating any of + * these addresses held in variables. */ if ((envPtr->codeNext + 3) > envPtr->codeEnd) { TclExpandCodeArray(envPtr); } @@ -4031,16 +3899,14 @@ /* * Adjust the code offsets for any commands and any ExceptionRange records * between the jump and the current code address. */ - firstCmd = jumpFixupPtr->cmdIndex; - lastCmd = envPtr->numCommands - 1; - if (firstCmd < lastCmd) { - for (k = firstCmd; k <= lastCmd; k++) { - envPtr->cmdMapPtr[k].codeOffset += 3; - } + for (cmdLocPtr = BA_CmdLocation_Get(envPtr->cmdMap, + jumpFixupPtr->cmdIndex, &ptr); cmdLocPtr; + cmdLocPtr = BP_CmdLocation_Next(&ptr)) { + cmdLocPtr->codeOffset += 3; } firstRange = jumpFixupPtr->exceptIndex; lastRange = envPtr->exceptArrayNext - 1; for (k = firstRange; k <= lastRange; k++) { @@ -4048,11 +3914,11 @@ rangePtr->codeOffset += 3; switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: rangePtr->breakOffset += 3; - if (rangePtr->continueOffset != -1) { + if (rangePtr->continueOffset != TCL_INDEX_NONE) { rangePtr->continueOffset += 3; } break; case CATCH_EXCEPTION_RANGE: rangePtr->catchOffset += 3; @@ -4061,20 +3927,20 @@ Tcl_Panic("TclFixupForwardJump: bad ExceptionRange type %d", rangePtr->type); } } - for (k = 0 ; k < envPtr->exceptArrayNext ; k++) { + for (k = 0 ; k < (int)envPtr->exceptArrayNext ; k++) { ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[k]; int i; - for (i=0 ; inumBreakTargets ; i++) { + for (i=0 ; i<(int)auxPtr->numBreakTargets ; i++) { if (jumpFixupPtr->codeOffset < auxPtr->breakTargets[i]) { auxPtr->breakTargets[i] += 3; } } - for (i=0 ; inumContinueTargets ; i++) { + for (i=0 ; i<(int)auxPtr->numContinueTargets ; i++) { if (jumpFixupPtr->codeOffset < auxPtr->continueTargets[i]) { auxPtr->continueTargets[i] += 3; } } } @@ -4085,21 +3951,21 @@ /* *---------------------------------------------------------------------- * * TclEmitInvoke -- * - * Emit one of the invoke-related instructions, wrapping it if necessary + * Emits one of the invoke-related instructions, wrapping it if necessary * in code that ensures that any break or continue operation passing * through it gets the stack unwinding correct, converting it into an * internal jump if in an appropriate context. * * Results: * None * * Side effects: * Issues the jump with all correct stack management. May create another - * loop exception range; pointers to ExceptionRange and ExceptionAux + * loop exception range. Pointers to ExceptionRange and ExceptionAux * structures should not be held across this call. * *---------------------------------------------------------------------- */ @@ -4153,35 +4019,34 @@ 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). + * 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; they can be different (especially for - * calls from inside a [for] increment clause). + * These must be done separately since they can be different, especially + * for calls from inside a [for] increment clause. */ rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_CONTINUE, &auxContinuePtr); if (rangePtr == NULL || rangePtr->type != LOOP_EXCEPTION_RANGE) { auxContinuePtr = NULL; } else if (auxContinuePtr->stackDepth == envPtr->currStackDepth-wordCount - && auxContinuePtr->expandTarget == envPtr->expandCount-expandCount) { + && (auxContinuePtr->expandTarget+expandCount == envPtr->expandCount)) { auxContinuePtr = NULL; } else { continueRange = auxContinuePtr - envPtr->exceptAuxArrayPtr; } rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_BREAK, &auxBreakPtr); if (rangePtr == NULL || rangePtr->type != LOOP_EXCEPTION_RANGE) { auxBreakPtr = NULL; } else if (auxContinuePtr == NULL - && auxBreakPtr->stackDepth == envPtr->currStackDepth-wordCount - && auxBreakPtr->expandTarget == envPtr->expandCount-expandCount) { + && auxBreakPtr->stackDepth+wordCount == envPtr->currStackDepth + && auxBreakPtr->expandTarget+expandCount == envPtr->expandCount) { auxBreakPtr = NULL; } else { breakRange = auxBreakPtr - envPtr->exceptAuxArrayPtr; } @@ -4223,12 +4088,12 @@ * If we're generating a special wrapper exception range, we need to * finish that up now. */ if (auxBreakPtr != NULL || auxContinuePtr != NULL) { - int savedStackDepth = envPtr->currStackDepth; - int savedExpandCount = envPtr->expandCount; + size_t savedStackDepth = envPtr->currStackDepth; + size_t savedExpandCount = envPtr->expandCount; JumpFixup nonTrapFixup; if (auxBreakPtr != NULL) { auxBreakPtr = envPtr->exceptAuxArrayPtr + breakRange; } @@ -4301,10 +4166,34 @@ } /* *---------------------------------------------------------------------- * + * TclCmdStartAddress -- + * + * Results: + * None. + * + * Side effects: + * Deletes all entries in the hash table of AuxData types. + * + *---------------------------------------------------------------------- + */ + +void * +TclCmdStartAddress( + CompileEnv *envPtr, + int i) +{ + BA_CmdLocation *map = envPtr->cmdMap; + + return envPtr->codeStart + BA_CmdLocation_At(map, i)->codeOffset; +} + +/* + *---------------------------------------------------------------------- + * * GetCmdLocEncodingSize -- * * Computes the total number of bytes needed to encode the command * location information for some compiled code. * @@ -4321,50 +4210,52 @@ GetCmdLocEncodingSize( CompileEnv *envPtr) /* Points to compilation environment structure * containing the CmdLocation structure to * encode. */ { - CmdLocation *mapPtr = envPtr->cmdMapPtr; - int numCmds = envPtr->numCommands; int codeDelta, codeLen, srcDelta, srcLen; int codeDeltaNext, codeLengthNext, srcDeltaNext, srcLengthNext; /* The offsets in their respective byte * sequences where the next encoded offset or * length should go. */ - int prevCodeOffset, prevSrcOffset, i; + int prevCodeOffset, prevSrcOffset; + BA_CmdLocation *map = envPtr->cmdMap; + CmdLocation *cmdLocPtr; + BP_CmdLocation ptr; codeDeltaNext = codeLengthNext = srcDeltaNext = srcLengthNext = 0; prevCodeOffset = prevSrcOffset = 0; - for (i = 0; i < numCmds; i++) { - codeDelta = mapPtr[i].codeOffset - prevCodeOffset; + for (cmdLocPtr = BA_CmdLocation_First(map, &ptr); cmdLocPtr; + cmdLocPtr = BP_CmdLocation_Next(&ptr)) { + codeDelta = cmdLocPtr->codeOffset - prevCodeOffset; if (codeDelta < 0) { Tcl_Panic("GetCmdLocEncodingSize: bad code offset"); } else if (codeDelta <= 127) { codeDeltaNext++; } else { codeDeltaNext += 5; /* 1 byte for 0xFF, 4 for positive delta */ } - prevCodeOffset = mapPtr[i].codeOffset; + prevCodeOffset = cmdLocPtr->codeOffset; - codeLen = mapPtr[i].numCodeBytes; + codeLen = cmdLocPtr->numCodeBytes; if (codeLen < 0) { Tcl_Panic("GetCmdLocEncodingSize: bad code length"); } else if (codeLen <= 127) { codeLengthNext++; } else { codeLengthNext += 5;/* 1 byte for 0xFF, 4 for length */ } - srcDelta = mapPtr[i].srcOffset - prevSrcOffset; + srcDelta = cmdLocPtr->srcOffset - prevSrcOffset; if ((-127 <= srcDelta) && (srcDelta <= 127) && (srcDelta != -1)) { srcDeltaNext++; } else { srcDeltaNext += 5; /* 1 byte for 0xFF, 4 for delta */ } - prevSrcOffset = mapPtr[i].srcOffset; + prevSrcOffset = cmdLocPtr->srcOffset; - srcLen = mapPtr[i].numSrcBytes; + srcLen = cmdLocPtr->numSrcBytes; if (srcLen < 0) { Tcl_Panic("GetCmdLocEncodingSize: bad source length"); } else if (srcLen <= 127) { srcLengthNext++; } else { @@ -4378,20 +4269,20 @@ /* *---------------------------------------------------------------------- * * EncodeCmdLocMap -- * - * Encode the command location information for some compiled code into a + * Encodes the command location information for some compiled code into a * ByteCode structure. The encoded command location map is stored as - * three adjacent byte sequences. + * three-adjacent-byte sequences. * * Results: - * Pointer to the first byte after the encoded command location + * A pointer to the first byte after the encoded command location * information. * * Side effects: - * The encoded information is stored into the block of memory headed by + * Stores encoded information into the block of memory headed by * codePtr. Also records pointers to the start of the four byte sequences * in fields in codePtr's ByteCode header structure. * *---------------------------------------------------------------------- */ @@ -4405,24 +4296,26 @@ * 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; + Tcl_Size codeDelta, codeLen, srcLen, prevOffset; + int srcDelta; + BA_CmdLocation *map = envPtr->cmdMap; + BP_CmdLocation ptr; + CmdLocation *cmdLocPtr; /* * Encode the code offset for each command as a sequence of deltas. */ codePtr->codeDeltaStart = p; prevOffset = 0; - for (i = 0; i < numCmds; i++) { - codeDelta = mapPtr[i].codeOffset - prevOffset; + for (cmdLocPtr = BA_CmdLocation_First(map, &ptr); cmdLocPtr; + cmdLocPtr = BP_CmdLocation_Next(&ptr)) { + codeDelta = cmdLocPtr->codeOffset - prevOffset; if (codeDelta < 0) { Tcl_Panic("EncodeCmdLocMap: bad code offset"); } else if (codeDelta <= 127) { TclStoreInt1AtPtr(codeDelta, p); p++; @@ -4430,20 +4323,21 @@ TclStoreInt1AtPtr(0xFF, p); p++; TclStoreInt4AtPtr(codeDelta, p); p += 4; } - prevOffset = mapPtr[i].codeOffset; + prevOffset = cmdLocPtr->codeOffset; } /* * Encode the code length for each command. */ codePtr->codeLengthStart = p; - for (i = 0; i < numCmds; i++) { - codeLen = mapPtr[i].numCodeBytes; + for (cmdLocPtr = BA_CmdLocation_First(map, &ptr); cmdLocPtr; + cmdLocPtr = BP_CmdLocation_Next(&ptr)) { + codeLen = cmdLocPtr->numCodeBytes; if (codeLen < 0) { Tcl_Panic("EncodeCmdLocMap: bad code length"); } else if (codeLen <= 127) { TclStoreInt1AtPtr(codeLen, p); p++; @@ -4459,31 +4353,33 @@ * Encode the source offset for each command as a sequence of deltas. */ codePtr->srcDeltaStart = p; prevOffset = 0; - for (i = 0; i < numCmds; i++) { - srcDelta = mapPtr[i].srcOffset - prevOffset; + for (cmdLocPtr = BA_CmdLocation_First(map, &ptr); cmdLocPtr; + cmdLocPtr = BP_CmdLocation_Next(&ptr)) { + srcDelta = cmdLocPtr->srcOffset - prevOffset; if ((-127 <= srcDelta) && (srcDelta <= 127) && (srcDelta != -1)) { TclStoreInt1AtPtr(srcDelta, p); p++; } else { TclStoreInt1AtPtr(0xFF, p); p++; TclStoreInt4AtPtr(srcDelta, p); p += 4; } - prevOffset = mapPtr[i].srcOffset; + prevOffset = cmdLocPtr->srcOffset; } /* * Encode the source length for each command. */ codePtr->srcLengthStart = p; - for (i = 0; i < numCmds; i++) { - srcLen = mapPtr[i].numSrcBytes; + for (cmdLocPtr = BA_CmdLocation_First(map, &ptr); cmdLocPtr; + cmdLocPtr = BP_CmdLocation_Next(&ptr)) { + srcLen = cmdLocPtr->numSrcBytes; if (srcLen < 0) { Tcl_Panic("EncodeCmdLocMap: bad source length"); } else if (srcLen <= 127) { TclStoreInt1AtPtr(srcLen, p); p++; @@ -4502,13 +4398,13 @@ /* *---------------------------------------------------------------------- * * RecordByteCodeStats -- * - * Accumulates various compilation-related statistics for each newly - * compiled ByteCode. Called by the TclInitByteCodeObj when Tcl is - * compiled with the -DTCL_COMPILE_STATS flag + * Accumulates compilation-related statistics for each newly-compiled + * ByteCode. Called by the TclInitByteCodeObj when Tcl is compiled with + * the -DTCL_COMPILE_STATS flag * * Results: * None. * * Side effects: @@ -4532,25 +4428,25 @@ return; } statsPtr = &(iPtr->stats); statsPtr->numCompilations++; - statsPtr->totalSrcBytes += (double) codePtr->numSrcBytes; + statsPtr->totalSrcBytes += (double)codePtr->numSrcBytes; statsPtr->totalByteCodeBytes += (double) codePtr->structureSize; - statsPtr->currentSrcBytes += (double) codePtr->numSrcBytes; + statsPtr->currentSrcBytes += (double) (int)codePtr->numSrcBytes; statsPtr->currentByteCodeBytes += (double) codePtr->structureSize; - statsPtr->srcCount[TclLog2(codePtr->numSrcBytes)]++; + statsPtr->srcCount[TclLog2((int)codePtr->numSrcBytes)]++; statsPtr->byteCodeCount[TclLog2((int) codePtr->structureSize)]++; statsPtr->currentInstBytes += (double) codePtr->numCodeBytes; statsPtr->currentLitBytes += (double) codePtr->numLitObjects * sizeof(Tcl_Obj *); statsPtr->currentExceptBytes += (double) codePtr->numExceptRanges * sizeof(ExceptionRange); statsPtr->currentAuxBytes += (double) - codePtr->numAuxDataItems * sizeof(AuxData); + BA_AuxData_Size(codePtr->auxData) * sizeof(AuxData); statsPtr->currentCmdMapBytes += (double) codePtr->numCmdLocBytes; } #endif /* TCL_COMPILE_STATS */ /* Index: generic/tclCompile.h ================================================================== --- generic/tclCompile.h +++ generic/tclCompile.h @@ -87,24 +87,24 @@ * to a catch PC offset. */ } ExceptionRangeType; typedef struct { ExceptionRangeType type; /* The kind of ExceptionRange. */ - int nestingLevel; /* Static depth of the exception range. Used + Tcl_Size nestingLevel; /* Static depth of the exception range. Used * to find the most deeply-nested range * surrounding a PC at runtime. */ - int codeOffset; /* Offset of the first instruction byte of the + Tcl_Size codeOffset; /* Offset of the first instruction byte of the * code range. */ - int numCodeBytes; /* Number of bytes in the code range. */ - int breakOffset; /* If LOOP_EXCEPTION_RANGE, the target PC + Tcl_Size numCodeBytes; /* Number of bytes in the code range. */ + Tcl_Size breakOffset; /* If LOOP_EXCEPTION_RANGE, the target PC * offset for a break command in the range. */ - int continueOffset; /* If LOOP_EXCEPTION_RANGE and not -1, the + Tcl_Size continueOffset; /* If LOOP_EXCEPTION_RANGE and not TCL_INDEX_NONE, the * target PC offset for a continue command in * the code range. Otherwise, ignore this * range when processing a continue * command. */ - int catchOffset; /* If a CATCH_EXCEPTION_RANGE, the target PC + Tcl_Size catchOffset; /* If a CATCH_EXCEPTION_RANGE, the target PC * offset for any "exception" in range. */ } ExceptionRange; /* * Auxiliary data used when issuing (currently just loop) exception ranges, @@ -116,61 +116,46 @@ * continueOffset created for it; if it is a * loop exception range that *doesn't* have * one (see [for] next-clause) then we must * not pick up the range when scanning for a * target to continue to. */ - int stackDepth; /* The stack depth at the point where the + Tcl_Size stackDepth; /* The stack depth at the point where the * exception range was created. This is used * to calculate the number of POPs required to * restore the stack to its prior state. */ - int expandTarget; /* The number of expansions expected on the + Tcl_Size expandTarget; /* The number of expansions expected on the * auxData stack at the time the loop starts; * we can't currently discard them except by * doing INST_INVOKE_EXPANDED; this is a known * problem. */ - int expandTargetDepth; /* The stack depth expected at the outermost + Tcl_Size expandTargetDepth; /* The stack depth expected at the outermost * expansion within the loop. Not meaningful * if there are no open expansions between the * looping level and the point of jump * issue. */ - int numBreakTargets; /* The number of [break]s that want to be + Tcl_Size numBreakTargets; /* The number of [break]s that want to be * targeted to the place where this loop * exception will be bound to. */ - unsigned int *breakTargets; /* The offsets of the INST_JUMP4 instructions + TCL_HASH_TYPE *breakTargets; /* The offsets of the INST_JUMP4 instructions * issued by the [break]s that we must * update. Note that resizing a jump (via * TclFixupForwardJump) can cause the contents * of this array to be updated. When * numBreakTargets==0, this is NULL. */ - int allocBreakTargets; /* The size of the breakTargets array. */ - int numContinueTargets; /* The number of [continue]s that want to be + Tcl_Size allocBreakTargets; /* The size of the breakTargets array. */ + Tcl_Size numContinueTargets; /* The number of [continue]s that want to be * targeted to the place where this loop * exception will be bound to. */ - unsigned int *continueTargets; /* The offsets of the INST_JUMP4 instructions + 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. */ - int allocContinueTargets; /* The size of the continueTargets array. */ + 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 { - 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 @@ -179,29 +164,29 @@ * Also recorded is information coming from the context, i.e. type of the * frame and associated information, like the path of a sourced file. */ typedef struct { - size_t srcOffset; /* Command location to find the entry. */ - int nline; /* Number of words in the command */ - int *line; /* Line information for all words in the + Tcl_Size srcOffset; /* Command location to find the entry. */ + Tcl_Size nline; /* Number of words in the command */ + Tcl_Size *line; /* Line information for all words in the * command. */ - int **next; /* Transient information used by the compiler + Tcl_Size **next; /* Transient information used by the compiler * for tracking of hidden continuation * lines. */ } ECL; typedef struct { int type; /* Context type. */ - int start; /* Starting line for compiled script. Needed + Tcl_Size start; /* Starting line for compiled script. Needed * for the extended recompile check in * tclCompileObj. */ Tcl_Obj *path; /* Path of the sourced file the command is * in. */ ECL *loc; /* Command word locations (lines). */ - int nloc; /* Number of allocated entries in 'loc'. */ - int nuloc; /* Number of used entries in 'loc'. */ + Tcl_Size nloc; /* Number of allocated entries in 'loc'. */ + Tcl_Size nuloc; /* Number of used entries in 'loc'. */ } ExtCmdLoc; /* * CompileProcs need the ability to record information during compilation that * can be used by bytecode instructions during execution. The AuxData @@ -219,11 +204,11 @@ typedef void *(AuxDataDupProc) (void *clientData); typedef void (AuxDataFreeProc) (void *clientData); typedef void (AuxDataPrintProc)(void *clientData, Tcl_Obj *appendObj, struct ByteCode *codePtr, - unsigned int pcOffset); + 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 @@ -267,21 +252,23 @@ const AuxDataType *type; /* Pointer to the AuxData type associated with * this ClientData. */ void *clientData; /* The compilation data itself. */ } AuxData; +/* Forward declarations for fields below */ +struct BrodnikArray_CmdLocation; +TclBrodnikArrayDeclare(AuxData,MODULE_SCOPE); + /* * Structure defining the compilation environment. After compilation, fields * describing bytecode instructions are copied out into the more compact * ByteCode structure defined below. */ #define COMPILEENV_INIT_CODE_BYTES 250 #define COMPILEENV_INIT_NUM_OBJECTS 60 #define COMPILEENV_INIT_EXCEPT_RANGES 5 -#define COMPILEENV_INIT_CMD_MAP_SIZE 40 -#define COMPILEENV_INIT_AUX_DATA_SIZE 5 typedef struct CompileEnv { Interp *iPtr; /* Interpreter containing the code being * compiled. Commands and their compile procs * are specific to an interpreter so the code @@ -288,103 +275,93 @@ * emitted will depend on the interpreter. */ const char *source; /* The source string being compiled by * SetByteCodeFromAny. This pointer is not * owned by the CompileEnv and must not be * freed or changed by it. */ - int numSrcBytes; /* Number of bytes in source. */ + Tcl_Size numSrcBytes; /* Number of bytes in source. */ Proc *procPtr; /* If a procedure is being compiled, a pointer * to its Proc structure; otherwise NULL. Used * to compile local variables. Set from * information provided by ObjInterpProc in * tclProc.c. */ - int numCommands; /* Number of commands compiled. */ - int exceptDepth; /* Current exception range nesting level; -1 + Tcl_Size numCommands; /* Number of commands compiled. */ + Tcl_Size exceptDepth; /* Current exception range nesting level; TCL_INDEX_NONE * if not in any range currently. */ - int maxExceptDepth; /* Max nesting level of exception ranges; -1 + Tcl_Size maxExceptDepth; /* Max nesting level of exception ranges; TCL_INDEX_NONE * if no ranges have been compiled. */ - int maxStackDepth; /* Maximum number of stack elements needed to + Tcl_Size 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. */ + Tcl_Size currStackDepth; /* Current stack depth. */ + Tcl_HashTable litMap; /* Map from literal value to int index where + * that value is stored in literalArrayPtr. + * Used to prevent dup value refs. */ 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. */ +#if TCL_MAJOR_VERSION > 8 + int mallocedExceptArray; /* 1 if ExceptionRange array was expanded and + * exceptArrayPtr points in heap, else 0. */ +#endif + Tcl_Obj **literalArrayPtr; + /* Points of array of literal values. */ + 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. */ - int exceptArrayNext; /* Next free ExceptionRange array index. + Tcl_Size exceptArrayNext; /* Next free ExceptionRange array index. * exceptArrayNext is the number of ranges and * (exceptArrayNext-1) is the index of the * current range's array entry. */ - int exceptArrayEnd; /* Index after the last ExceptionRange array + Tcl_Size exceptArrayEnd; /* Index after the last ExceptionRange array * entry. */ - int mallocedExceptArray; /* 1 if ExceptionRange array was expanded and - * exceptArrayPtr points in heap, else 0. */ +#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. + struct BrodnikArray_CmdLocation *cmdMap; + /* Points to array of CmdLocation. * 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. */ + BA_AuxData *auxData; /* Points to array of AuxData */ unsigned char staticCodeSpace[COMPILEENV_INIT_CODE_BYTES]; /* Initial storage for code. */ - LiteralEntry staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS]; - /* Initial storage of LiteralEntry array. */ + Tcl_Obj *staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS]; + /* Initial storage of literal value array. */ ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES]; /* Initial ExceptionRange array storage. */ ExceptionAux staticExAuxArraySpace[COMPILEENV_INIT_EXCEPT_RANGES]; /* Initial static except auxiliary info array * storage. */ - CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE]; - /* Initial storage for cmd location map. */ - AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE]; - /* Initial storage for aux data array. */ /* TIP #280 */ ExtCmdLoc *extCmdMapPtr; /* Extended command location information for * 'info frame'. */ - int line; /* First line of the script, based on the + Tcl_Size line; /* First line of the script, based on the * invoking context, then the line of the * command currently compiled. */ int atCmdStart; /* Flag to say whether an INST_START_CMD * should be issued; they should never be * issued repeatedly, as that is significantly * inefficient. If set to 2, that instruction * should not be issued at all (by the generic * part of the command compiler). */ - int expandCount; /* Number of INST_EXPAND_START instructions + Tcl_Size expandCount; /* Number of INST_EXPAND_START instructions * encountered that have not yet been paired * with a corresponding * INST_INVOKE_EXPANDED. */ - int *clNext; /* If not NULL, it refers to the next slot in + Tcl_Size *clNext; /* If not NULL, it refers to the next slot in * clLoc to check for an invisible * continuation line. */ } CompileEnv; /* @@ -409,34 +386,36 @@ #define TCL_BYTECODE_RESOLVE_VARS 0x0002 #define TCL_BYTECODE_RECOMPILE 0x0004 +#define TCL_BYTECODE_FREE_LITERALS 0x0008 + typedef struct ByteCode { TclHandle interpHandle; /* Handle for interpreter containing the * compiled code. Commands and their compile * procs are specific to an interpreter so the * code emitted will depend on the * interpreter. */ - size_t compileEpoch; /* Value of iPtr->compileEpoch when this + Tcl_Size compileEpoch; /* Value of iPtr->compileEpoch when this * ByteCode was compiled. Used to invalidate * code when, e.g., commands with compile * procs are redefined. */ Namespace *nsPtr; /* Namespace context in which this code was * compiled. If the code is executed if a * different namespace, it must be * recompiled. */ - size_t nsEpoch; /* Value of nsPtr->resolverEpoch when this + Tcl_Size nsEpoch; /* Value of nsPtr->resolverEpoch when this * ByteCode was compiled. Used to invalidate * code when new namespace resolution rules * are put into effect. */ - size_t refCount; /* Reference count: set 1 when created plus 1 + Tcl_Size refCount; /* Reference count: set 1 when created plus 1 * for each execution of the code currently * active. This structure can be freed when * refCount becomes zero. */ unsigned int flags; /* flags describing state for the codebyte. - * this variable holds ORed values from the + * this variable holds OR'ed values from the * TCL_BYTECODE_ masks defined above */ const char *source; /* The source string from which this ByteCode * was compiled. Note that this pointer is not * owned by the ByteCode and must not be freed * or modified by it. */ @@ -447,21 +426,20 @@ * and must not be freed by it. */ size_t structureSize; /* Number of bytes in the ByteCode structure * itself. Does not include heap space for * literal Tcl objects or storage referenced * by AuxData entries. */ - int numCommands; /* Number of commands compiled. */ - int numSrcBytes; /* Number of source bytes compiled. */ - int numCodeBytes; /* Number of code bytes. */ - int numLitObjects; /* Number of objects in literal array. */ - int numExceptRanges; /* Number of ExceptionRange array elems. */ - int numAuxDataItems; /* Number of AuxData items. */ - int numCmdLocBytes; /* Number of bytes needed for encoded command + Tcl_Size numCommands; /* Number of commands compiled. */ + Tcl_Size numSrcBytes; /* Number of source bytes compiled. */ + Tcl_Size numCodeBytes; /* Number of code bytes. */ + Tcl_Size numLitObjects; /* Number of objects in literal array. */ + Tcl_Size numExceptRanges; /* Number of ExceptionRange array elems. */ + Tcl_Size numCmdLocBytes; /* Number of bytes needed for encoded command * location information. */ - int maxExceptDepth; /* Maximum nesting level of ExceptionRanges; - * -1 if no ranges were compiled. */ - int maxStackDepth; /* Maximum number of stack elements needed to + Tcl_Size maxExceptDepth; /* Maximum nesting level of ExceptionRanges; + * TCL_INDEX_NONE if no ranges were compiled. */ + Tcl_Size maxStackDepth; /* Maximum number of stack elements needed to * execute the code. */ unsigned char *codeStart; /* Points to the first byte of the code. This * is just after the final ByteCode member * cmdMapPtr. */ Tcl_Obj **objArrayPtr; /* Points to the start of the literal object @@ -469,13 +447,11 @@ * byte. */ ExceptionRange *exceptArrayPtr; /* Points to the start of the ExceptionRange * array. This is just after the last object * in the object array. */ - AuxData *auxDataArrayPtr; /* Points to the start of the auxiliary data - * array. This is just after the last entry in - * the ExceptionRange array. */ + BA_AuxData *auxData; /* Array of auxiliary data. */ unsigned char *codeDeltaStart; /* Points to the first of a sequence of bytes * that encode the change in the starting * offset of each command's code. If -127 <= * delta <= 127, it is encoded as 1 byte, @@ -513,24 +489,24 @@ Tcl_Time createTime; /* Absolute time when the ByteCode was * created. */ #endif /* TCL_COMPILE_STATS */ } ByteCode; -#define ByteCodeSetIntRep(objPtr, typePtr, codePtr) \ +#define ByteCodeSetInternalRep(objPtr, typePtr, codePtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (codePtr); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreIntRep((objPtr), (typePtr), &ir); \ + Tcl_StoreInternalRep((objPtr), (typePtr), &ir); \ } while (0) -#define ByteCodeGetIntRep(objPtr, typePtr, codePtr) \ +#define ByteCodeGetInternalRep(objPtr, typePtr, codePtr) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), (typePtr)); \ + 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 @@ -822,10 +798,12 @@ /* TIP 461 */ INST_STR_LT, INST_STR_GT, INST_STR_LE, INST_STR_GE, + + INST_LREPLACE4, /* The last opcode */ LAST_INST_OPCODE }; @@ -863,11 +841,11 @@ OPERAND_SCLS1 /* Index into tclStringClassTable. */ } InstOperandType; typedef struct InstructionDesc { const char *name; /* Name of instruction. */ - size_t numBytes; /* Total number of bytes for instruction. */ + Tcl_Size numBytes; /* Total number of bytes for instruction. */ int stackEffect; /* The worst-case balance stack effect of the * instruction, used for stack requirements * computations. The value INT_MIN signals * that the instruction's worst case effect is * (1-opnd1). */ @@ -898,12 +876,13 @@ STR_CLASS_PUNCT, /* Unicode punctuation characters. */ STR_CLASS_SPACE, /* Unicode space characters. */ STR_CLASS_UPPER, /* Unicode upper-case alphabet characters. */ STR_CLASS_WORD, /* Unicode word (alphabetic, digit, connector * punctuation) characters. */ - STR_CLASS_XDIGIT /* Characters that can be used as digits in + STR_CLASS_XDIGIT, /* Characters that can be used as digits in * hexadecimal numbers ([0-9A-Fa-f]). */ + STR_CLASS_UNICODE /* Unicode characters. */ } InstStringClassType; typedef struct StringClassDesc { char name[8]; /* Name of the class. */ int (*comparator)(int); /* Function to test if a single unicode @@ -945,33 +924,22 @@ * This field is used to adjust the code * offsets in subsequent ExceptionRange * records when a jump is grown from 2 bytes * 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; +TclBrodnikArrayDeclare(JumpFixup,MODULE_SCOPE); /* * The structure describing one variable list of a foreach command. Note that * only foreach commands inside procedure bodies are compiled inline so a * ForeachVarList structure always describes local variables. Furthermore, * only scalar variables are supported for inline-compiled foreach loops. */ typedef struct ForeachVarList { - int numVars; /* The number of variables in the list. */ - int varIndexes[TCLFLEXARRAY];/* An array of the indexes ("slot numbers") + Tcl_Size numVars; /* The number of variables in the list. */ + Tcl_Size varIndexes[TCLFLEXARRAY];/* An array of the indexes ("slot numbers") * for each variable in the procedure's array * of local variables. Only scalar variables * are supported. The actual size of this * field will be large enough to numVars * indexes. THIS MUST BE THE LAST FIELD IN THE @@ -983,15 +951,15 @@ * during program execution. These structures are stored in CompileEnv and * ByteCode structures as auxiliary data. */ typedef struct ForeachInfo { - int numLists; /* The number of both the variable and value + Tcl_Size numLists; /* The number of both the variable and value * lists of the foreach command. */ - int firstValueTemp; /* Index of the first temp var in a proc frame + Tcl_Size firstValueTemp; /* Index of the first temp var in a proc frame * used to point to a value list. */ - int loopCtTemp; /* Index of temp var in a proc frame holding + Tcl_Size loopCtTemp; /* Index of temp var in a proc frame holding * the loop's iteration count. Used to * determine next value list element to assign * each loop var. */ ForeachVarList *varLists[TCLFLEXARRAY];/* An array of pointers to ForeachVarList * structures describing each var list. The @@ -1012,21 +980,21 @@ } JumptableInfo; MODULE_SCOPE const AuxDataType tclJumptableInfoType; #define JUMPTABLEINFO(envPtr, index) \ - ((JumptableInfo*)((envPtr)->auxDataArrayPtr[TclGetUInt4AtPtr(index)].clientData)) + ((JumptableInfo*)(TclFetchAuxData(envPtr, TclGetUInt4AtPtr(index)))) /* * Structure used to hold information about a [dict update] command that is * needed during program execution. These structures are stored in CompileEnv * and ByteCode structures as auxiliary data. */ typedef struct { - size_t length; /* Size of array */ - int varIndices[TCLFLEXARRAY]; /* Array of variable indices to manage when + Tcl_Size length; /* Size of array */ + Tcl_Size varIndices[TCLFLEXARRAY]; /* Array of variable indices to manage when * processing the start and end of a [dict * update]. There is really more than one * entry, and the structure is allocated to * take account of this. MUST BE LAST FIELD IN * STRUCTURE. */ @@ -1049,10 +1017,11 @@ *---------------------------------------------------------------- * 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 @@ -1068,72 +1037,73 @@ * not used outside: *---------------------------------------------------------------- */ MODULE_SCOPE int TclAttemptCompileProc(Tcl_Interp *interp, - Tcl_Parse *parsePtr, int depth, Command *cmdPtr, + Tcl_Parse *parsePtr, Tcl_Size depth, Command *cmdPtr, CompileEnv *envPtr); MODULE_SCOPE void TclCleanupStackForBreakContinue(CompileEnv *envPtr, ExceptionAux *auxPtr); +MODULE_SCOPE void * TclCmdStartAddress(CompileEnv *envPtr, int i); MODULE_SCOPE void TclCompileCmdWord(Tcl_Interp *interp, - Tcl_Token *tokenPtr, int count, + Tcl_Token *tokenPtr, Tcl_Size count, CompileEnv *envPtr); MODULE_SCOPE void TclCompileExpr(Tcl_Interp *interp, const char *script, - size_t numBytes, CompileEnv *envPtr, int optimize); + Tcl_Size numBytes, CompileEnv *envPtr, int optimize); MODULE_SCOPE void TclCompileExprWords(Tcl_Interp *interp, - Tcl_Token *tokenPtr, int numWords, + Tcl_Token *tokenPtr, Tcl_Size numWords, CompileEnv *envPtr); -MODULE_SCOPE void TclCompileInvocation(Tcl_Interp *interp, - Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, size_t numWords, - CompileEnv *envPtr); +MODULE_SCOPE Tcl_Token *TclCompileInvocation(Tcl_Interp *interp, + Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, + Tcl_Size numWords, CompileEnv *envPtr); MODULE_SCOPE void TclCompileScript(Tcl_Interp *interp, - const char *script, size_t numBytes, + const char *script, Tcl_Size numBytes, CompileEnv *envPtr); MODULE_SCOPE void TclCompileSyntaxError(Tcl_Interp *interp, CompileEnv *envPtr); MODULE_SCOPE void TclCompileTokens(Tcl_Interp *interp, - Tcl_Token *tokenPtr, int count, + Tcl_Token *tokenPtr, Tcl_Size count, CompileEnv *envPtr); MODULE_SCOPE void TclCompileVarSubst(Tcl_Interp *interp, Tcl_Token *tokenPtr, CompileEnv *envPtr); -MODULE_SCOPE int TclCreateAuxData(void *clientData, +MODULE_SCOPE Tcl_Size TclCreateAuxData(void *clientData, const AuxDataType *typePtr, CompileEnv *envPtr); -MODULE_SCOPE int TclCreateExceptRange(ExceptionRangeType type, +MODULE_SCOPE Tcl_Size TclCreateExceptRange(ExceptionRangeType type, CompileEnv *envPtr); MODULE_SCOPE ExecEnv * TclCreateExecEnv(Tcl_Interp *interp, size_t size); MODULE_SCOPE Tcl_Obj * TclCreateLiteral(Interp *iPtr, const char *bytes, - size_t length, size_t hash, int *newPtr, - Namespace *nsPtr, int flags, - LiteralEntry **globalPtrPtr); + Tcl_Size length); MODULE_SCOPE void TclDeleteExecEnv(ExecEnv *eePtr); MODULE_SCOPE void TclDeleteLiteralTable(Tcl_Interp *interp, LiteralTable *tablePtr); +MODULE_SCOPE void TclDisposeFailedCompile(CompileEnv *envPtr, + Tcl_Size num); 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 void *TclFetchAuxData(CompileEnv *envPtr, TCL_HASH_TYPE index); +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, size_t before, size_t after, int *indexPtr); MODULE_SCOPE ByteCode * TclInitByteCode(CompileEnv *envPtr); MODULE_SCOPE ByteCode * TclInitByteCodeObj(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, CompileEnv *envPtr); MODULE_SCOPE void TclInitCompileEnv(Tcl_Interp *interp, CompileEnv *envPtr, const char *string, - size_t numBytes, const CmdFrame *invoker, int word); -MODULE_SCOPE void TclInitJumpFixupArray(JumpFixupArray *fixupArrayPtr); + Tcl_Size numBytes, const CmdFrame *invoker, + int word); MODULE_SCOPE void TclInitLiteralTable(LiteralTable *tablePtr); MODULE_SCOPE ExceptionRange *TclGetInnermostExceptionRange(CompileEnv *envPtr, int returnCode, ExceptionAux **auxPtrPtr); MODULE_SCOPE void TclAddLoopBreakFixup(CompileEnv *envPtr, ExceptionAux *auxPtr); @@ -1143,80 +1113,64 @@ int range); #ifdef TCL_COMPILE_STATS MODULE_SCOPE char * TclLiteralStats(LiteralTable *tablePtr); MODULE_SCOPE int TclLog2(int value); #endif -MODULE_SCOPE int TclLocalScalar(const char *bytes, size_t numBytes, +MODULE_SCOPE size_t TclLocalScalar(const char *bytes, size_t numBytes, CompileEnv *envPtr); -MODULE_SCOPE int TclLocalScalarFromToken(Tcl_Token *tokenPtr, +MODULE_SCOPE size_t TclLocalScalarFromToken(Tcl_Token *tokenPtr, CompileEnv *envPtr); MODULE_SCOPE void TclOptimizeBytecode(void *envPtr); #ifdef TCL_COMPILE_DEBUG MODULE_SCOPE void TclPrintByteCodeObj(Tcl_Interp *interp, Tcl_Obj *objPtr); #endif MODULE_SCOPE int TclPrintInstruction(ByteCode *codePtr, const unsigned char *pc); MODULE_SCOPE void TclPrintObject(FILE *outFile, - Tcl_Obj *objPtr, size_t maxChars); + Tcl_Obj *objPtr, Tcl_Size maxChars); MODULE_SCOPE void TclPrintSource(FILE *outFile, - const char *string, size_t maxChars); + const char *string, Tcl_Size maxChars); MODULE_SCOPE void TclPushVarName(Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags, int *localIndexPtr, int *isScalarPtr); MODULE_SCOPE void TclPreserveByteCode(ByteCode *codePtr); MODULE_SCOPE void TclReleaseByteCode(ByteCode *codePtr); MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr); MODULE_SCOPE void TclInvalidateCmdLiteral(Tcl_Interp *interp, const char *name, Namespace *nsPtr); -MODULE_SCOPE int TclSingleOpCmd(void *clientData, - 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[]); +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, +MODULE_SCOPE Tcl_Size TclWordKnownAtCompileTime(Tcl_Token *tokenPtr, Tcl_Obj *valuePtr); MODULE_SCOPE void TclLogCommandInfo(Tcl_Interp *interp, const char *script, const char *command, - size_t length, const unsigned char *pc, + Tcl_Size length, const unsigned char *pc, Tcl_Obj **tosPtr); MODULE_SCOPE Tcl_Obj *TclGetInnerContext(Tcl_Interp *interp, 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_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. *---------------------------------------------------------------- */ -/* - * Simplified form to access AuxData. - * - * void *TclFetchAuxData(CompileEng *envPtr, int index); - */ - -#define TclFetchAuxData(envPtr, index) \ - (envPtr)->auxDataArrayPtr[(index)].clientData - #define LITERAL_ON_HEAP 0x01 #define LITERAL_CMD_NAME 0x02 #define LITERAL_UNSHARED 0x04 /* @@ -1228,11 +1182,11 @@ */ #define TclAdjustStackDepth(delta, envPtr) \ do { \ if ((delta) < 0) { \ - if ((envPtr)->maxStackDepth < (envPtr)->currStackDepth) { \ + if ((int)(envPtr)->maxStackDepth < (int)(envPtr)->currStackDepth) { \ (envPtr)->maxStackDepth = (envPtr)->currStackDepth; \ } \ } \ (envPtr)->currStackDepth += (delta); \ } while (0) @@ -1243,14 +1197,14 @@ #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); \ + 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 @@ -1441,11 +1395,11 @@ * int threshold); */ #define TclFixupForwardJumpToHere(envPtr, fixupPtr, threshold) \ TclFixupForwardJump((envPtr), (fixupPtr), \ - (envPtr)->codeNext-(envPtr)->codeStart-(fixupPtr)->codeOffset, \ + (envPtr)->codeNext-(envPtr)->codeStart-(int)(fixupPtr)->codeOffset, \ (threshold)) /* * Macros to get a signed integer (GET_INT{1,2}) or an unsigned int * (GET_UINT{1,2}) from a pointer. There are two variants for each return type @@ -1470,37 +1424,37 @@ # define TclGetInt1AtPtr(p) ((int) *((char *) p)) #elif defined(HAVE_SIGNED_CHAR) # define TclGetInt1AtPtr(p) ((int) *((signed char *) p)) #else # define TclGetInt1AtPtr(p) \ - (((int) *((char *) p)) | ((*(p) & 0200) ? (-256) : 0)) + ((int) ((*((char *) p)) | ((*(p) & 0200) ? (-256) : 0))) #endif #define TclGetInt4AtPtr(p) \ - (((int) (TclGetUInt1AtPtr(p) << 24)) | \ - (*((p)+1) << 16) | \ - (*((p)+2) << 8) | \ - (*((p)+3))) + ((int) ((TclGetUInt1AtPtr(p) << 24) | \ + (*((p)+1) << 16) | \ + (*((p)+2) << 8) | \ + (*((p)+3)))) #define TclGetUInt1AtPtr(p) \ ((unsigned int) *(p)) #define TclGetUInt4AtPtr(p) \ - ((unsigned int) (*(p) << 24) | \ - (*((p)+1) << 16) | \ - (*((p)+2) << 8) | \ - (*((p)+3))) + ((unsigned int) ((*(p) << 24) | \ + (*((p)+1) << 16) | \ + (*((p)+2) << 8) | \ + (*((p)+3)))) /* - * Macros used to compute the minimum and maximum of two integers. The ANSI C + * Macros used to compute the minimum and maximum of two values. The ANSI C * "prototypes" for these macros are: * - * int TclMin(int i, int j); - * int TclMax(int i, int j); + * size_t TclMin(size_t i, size_t j); + * size_t TclMax(size_t i, size_t j); */ -#define TclMin(i, j) ((((int) i) < ((int) j))? (i) : (j)) -#define TclMax(i, j) ((((int) i) > ((int) j))? (i) : (j)) +#define TclMin(i, j) ((((size_t) i) + 1 < ((size_t) j) + 1 )? (i) : (j)) +#define TclMax(i, j) ((((size_t) i) + 1 > ((size_t) j) + 1 )? (i) : (j)) /* * Convenience macros for use when compiling bodies of commands. The ANSI C * "prototype" for these macros are: * @@ -1526,19 +1480,19 @@ /* * Convenience macros for use when pushing literals. The ANSI C "prototype" for * these macros are: * * static void PushLiteral(CompileEnv *envPtr, - * const char *string, size_t length); + * const char *string, Tcl_Size length); * static void PushStringLiteral(CompileEnv *envPtr, * const char *string); */ #define PushLiteral(envPtr, string, length) \ - TclEmitPush(TclRegisterLiteral(envPtr, string, length, 0), (envPtr)) + TclEmitPush(TclRegisterLiteral((envPtr), (string), (length), 0), (envPtr)) #define PushStringLiteral(envPtr, string) \ - PushLiteral(envPtr, string, sizeof(string "") - 1) + PushLiteral((envPtr), (string), sizeof(string "") - 1) /* * Macro to advance to the next token; it is more mnemonic than the address * arithmetic that it replaces. The ANSI C "prototype" for this macro is: * @@ -1563,13 +1517,13 @@ * maximal depth of nested CATCH ranges in order to alloc runtime * memory. These macros should compute precisely that? OTOH, the nesting depth * of LOOP ranges is an interesting datum for debugging purposes, and that is * what we compute now. * - * static int ExceptionRangeStarts(CompileEnv *envPtr, int index); - * static void ExceptionRangeEnds(CompileEnv *envPtr, int index); - * static void ExceptionRangeTarget(CompileEnv *envPtr, int index, LABEL); + * static int ExceptionRangeStarts(CompileEnv *envPtr, Tcl_Size index); + * static void ExceptionRangeEnds(CompileEnv *envPtr, Tcl_Size index); + * static void ExceptionRangeTarget(CompileEnv *envPtr, Tcl_Size index, LABEL); */ #define ExceptionRangeStarts(envPtr, index) \ (((envPtr)->exceptDepth++), \ ((envPtr)->maxExceptDepth = \ @@ -1576,11 +1530,11 @@ TclMax((envPtr)->exceptDepth, (envPtr)->maxExceptDepth)), \ ((envPtr)->exceptArrayPtr[(index)].codeOffset = CurrentOffset(envPtr))) #define ExceptionRangeEnds(envPtr, index) \ (((envPtr)->exceptDepth--), \ ((envPtr)->exceptArrayPtr[(index)].numCodeBytes = \ - CurrentOffset(envPtr) - (envPtr)->exceptArrayPtr[(index)].codeOffset)) + CurrentOffset(envPtr) - (int)(envPtr)->exceptArrayPtr[(index)].codeOffset)) #define ExceptionRangeTarget(envPtr, index, targetType) \ ((envPtr)->exceptArrayPtr[(index)].targetType = CurrentOffset(envPtr)) /* * Check if there is an LVT for compiled locals @@ -1624,11 +1578,11 @@ * Macro to encapsulate the variable definition and setup. */ #define DefineLineInformation \ ExtCmdLoc *mapPtr = envPtr->extCmdMapPtr; \ - int eclIndex = mapPtr->nuloc - 1 + Tcl_Size eclIndex = mapPtr->nuloc - 1 #define SetLineInformation(word) \ envPtr->line = mapPtr->loc[eclIndex].line[(word)]; \ envPtr->clNext = mapPtr->loc[eclIndex].next[(word)] @@ -1665,10 +1619,16 @@ */ #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). */ /* @@ -1802,11 +1762,11 @@ 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", \ + snprintf(n, sizeof(n), "/tmp/tclDTraceDebug-%" TCL_Z_MODIFIER "u.log", \ (size_t) getpid()); \ tclDTraceDebugLog = fopen(n, "a"); \ } #define TclDTraceDbgMsg(p, m, ...) \ Index: generic/tclConfig.c ================================================================== --- generic/tclConfig.c +++ generic/tclConfig.c @@ -2,11 +2,11 @@ * 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 + * Copyright © 2002 Andreas Kupries * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -176,39 +176,38 @@ *---------------------------------------------------------------------- * * QueryConfigObjCmd -- * * Implementation of "::::pkgconfig", the command to query - * configuration information embedded into a binary library. + * configuration information embedded into a library. * * Results: - * A standard tcl result. + * A standard Tcl result. * * Side effects: * See the manual for what this command does. * *---------------------------------------------------------------------- */ static int QueryConfigObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, - struct Tcl_Obj *const *objv) + Tcl_Obj *const *objv) { QCCD *cdPtr = (QCCD *)clientData; Tcl_Obj *pkgName = cdPtr->pkg; Tcl_Obj *pDB, *pkgDict, *val, *listPtr; - size_t n = 0; - int index, m; + 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)) { @@ -228,15 +227,15 @@ * present. */ Tcl_SetObjResult(interp, Tcl_NewStringObj("package not known", -1)); Tcl_SetErrorCode(interp, "TCL", "FATAL", "PKGCFG_BASE", - TclGetString(pkgName), NULL); + TclGetString(pkgName), (void *)NULL); return TCL_ERROR; } - switch ((enum subcmds) index) { + switch (index) { case CFG_GET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "key"); return TCL_ERROR; } @@ -243,11 +242,11 @@ if (Tcl_DictObjGet(interp, pkgDict, objv[2], &val) != TCL_OK || val == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("key not known", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONFIG", - TclGetString(objv[2]), NULL); + TclGetString(objv[2]), (void *)NULL); return TCL_ERROR; } if (cdPtr->encoding) { venc = Tcl_GetEncoding(interp, cdPtr->encoding); @@ -257,11 +256,14 @@ } /* * Value is stored as-is in a byte array, see Bug [9b2e636361], * so we have to decode it first. */ - value = (const char *) TclGetByteArrayFromObj(val, &n); + value = (const char *) Tcl_GetBytesFromObj(interp, val, &n); + if (value == NULL) { + return TCL_ERROR; + } value = Tcl_ExternalToUtfDString(venc, value, n, &conv); Tcl_SetObjResult(interp, Tcl_NewStringObj(value, Tcl_DStringLength(&conv))); Tcl_DStringFree(&conv); return TCL_OK; @@ -276,11 +278,11 @@ listPtr = Tcl_NewListObj(m, NULL); if (!listPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "insufficient memory to create list", -1)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); return TCL_ERROR; } if (m) { Tcl_DictSearch s; @@ -320,11 +322,11 @@ *------------------------------------------------------------------------- */ static void QueryConfigDelete( - ClientData clientData) + void *clientData) { QCCD *cdPtr = (QCCD *)clientData; Tcl_Obj *pkgName = cdPtr->pkg; Tcl_Obj *pDB = GetConfigDict(cdPtr->interp); @@ -387,11 +389,11 @@ *---------------------------------------------------------------------- */ static void ConfigDictDeleteProc( - ClientData clientData, /* Pointer to Tcl_Obj. */ + void *clientData, /* Pointer to Tcl_Obj. */ TCL_UNUSED(Tcl_Interp *)) { Tcl_DecrRefCount((Tcl_Obj *)clientData); } Index: generic/tclDate.c ================================================================== --- generic/tclDate.c +++ generic/tclDate.c @@ -74,11 +74,11 @@ * 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) 1992-1995 Karl Lehenbauer & 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. * @@ -183,13 +183,13 @@ * Posix requires 1900. */ #define TM_YEAR_BASE 1900 -#define HOUR(x) ((int) (60 * x)) +#define HOUR(x) ((int) (60 * (x))) #define SECSPERDAY (24L * 60L * 60L) -#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) +#define IsLeapYear(x) (((x) % 4 == 0) && ((x) % 100 != 0 || (x) % 400 == 0)) /* * An entry in the lexical lookup table. */ @@ -350,11 +350,10 @@ # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T -# include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned # endif #endif @@ -2424,11 +2423,11 @@ { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */ { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */ { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */ { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */ #if 0 - /* For completeness. NST is also Newfoundland Stanard, nad SST is + /* For completeness. NST is also Newfoundland Standard, and SST is * also Swedish Summer. */ { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */ { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */ #endif /* 0 */ { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */ @@ -2744,11 +2743,11 @@ int TclClockOldscanObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Tcl interpreter */ - int objc, /* Count of paraneters */ + int objc, /* Count of parameters */ Tcl_Obj *const *objv) /* Parameters */ { Tcl_Obj *result, *resultElement; int yr, mo, da; DateInfo dateInfo; @@ -2793,56 +2792,56 @@ status = yyparse(&dateInfo); if (status == 1) { Tcl_SetObjResult(interp, dateInfo.messages); Tcl_DecrRefCount(dateInfo.messages); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "BUG", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", (void *)NULL); return TCL_ERROR; } TclNewObj(result); TclNewObj(resultElement); Index: generic/tclDecls.h ================================================================== --- generic/tclDecls.h +++ generic/tclDecls.h @@ -10,10 +10,12 @@ */ #ifndef _TCLDECLS #define _TCLDECLS +#include /* for size_t */ + #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl # define TCL_STORAGE_CLASS DLLEXPORT #else # ifdef USE_TCL_STUBS @@ -57,41 +59,28 @@ const char *name, const char *version, int exact, void *clientDataPtr); /* 2 */ EXTERN TCL_NORETURN void Tcl_Panic(const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 3 */ -EXTERN void * Tcl_Alloc(size_t size); +EXTERN void * Tcl_Alloc(TCL_HASH_TYPE size); /* 4 */ EXTERN void Tcl_Free(void *ptr); /* 5 */ -EXTERN void * Tcl_Realloc(void *ptr, size_t size); +EXTERN void * Tcl_Realloc(void *ptr, TCL_HASH_TYPE size); /* 6 */ -EXTERN void * Tcl_DbCkalloc(size_t size, const char *file, +EXTERN void * Tcl_DbCkalloc(TCL_HASH_TYPE size, const char *file, int line); /* 7 */ EXTERN void Tcl_DbCkfree(void *ptr, const char *file, int line); /* 8 */ -EXTERN void * Tcl_DbCkrealloc(void *ptr, size_t size, +EXTERN void * Tcl_DbCkrealloc(void *ptr, TCL_HASH_TYPE size, const char *file, int line); -#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ /* 9 */ EXTERN void Tcl_CreateFileHandler(int fd, int mask, Tcl_FileProc *proc, void *clientData); -#endif /* UNIX */ -#ifdef MAC_OSX_TCL /* MACOSX */ -/* 9 */ -EXTERN void Tcl_CreateFileHandler(int fd, int mask, - Tcl_FileProc *proc, void *clientData); -#endif /* MACOSX */ -#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ /* 10 */ EXTERN void Tcl_DeleteFileHandler(int fd); -#endif /* UNIX */ -#ifdef MAC_OSX_TCL /* MACOSX */ -/* 10 */ -EXTERN void Tcl_DeleteFileHandler(int fd); -#endif /* MACOSX */ /* 11 */ EXTERN void Tcl_SetTimer(const Tcl_Time *timePtr); /* 12 */ EXTERN void Tcl_Sleep(int ms); /* 13 */ @@ -101,13 +90,13 @@ Tcl_Obj *objPtr); /* 15 */ EXTERN void Tcl_AppendStringsToObj(Tcl_Obj *objPtr, ...); /* 16 */ EXTERN void Tcl_AppendToObj(Tcl_Obj *objPtr, const char *bytes, - size_t length); + Tcl_Size length); /* 17 */ -EXTERN Tcl_Obj * Tcl_ConcatObj(int objc, Tcl_Obj *const objv[]); +EXTERN Tcl_Obj * Tcl_ConcatObj(Tcl_Size objc, Tcl_Obj *const objv[]); /* 18 */ EXTERN int Tcl_ConvertToType(Tcl_Interp *interp, Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 19 */ EXTERN void Tcl_DbDecrRefCount(Tcl_Obj *objPtr, const char *file, @@ -119,36 +108,37 @@ EXTERN int Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file, int line); /* Slot 22 is reserved */ /* 23 */ EXTERN Tcl_Obj * Tcl_DbNewByteArrayObj(const unsigned char *bytes, - size_t length, const char *file, int line); + Tcl_Size numBytes, const char *file, + int line); /* 24 */ EXTERN Tcl_Obj * Tcl_DbNewDoubleObj(double doubleValue, const char *file, int line); /* 25 */ -EXTERN Tcl_Obj * Tcl_DbNewListObj(int objc, Tcl_Obj *const *objv, +EXTERN Tcl_Obj * Tcl_DbNewListObj(Tcl_Size objc, Tcl_Obj *const *objv, const char *file, int line); /* Slot 26 is reserved */ /* 27 */ EXTERN Tcl_Obj * Tcl_DbNewObj(const char *file, int line); /* 28 */ -EXTERN Tcl_Obj * Tcl_DbNewStringObj(const char *bytes, size_t length, - const char *file, int line); +EXTERN Tcl_Obj * Tcl_DbNewStringObj(const char *bytes, + Tcl_Size length, const char *file, int line); /* 29 */ EXTERN Tcl_Obj * Tcl_DuplicateObj(Tcl_Obj *objPtr); /* 30 */ EXTERN void TclFreeObj(Tcl_Obj *objPtr); /* 31 */ EXTERN int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, - int *boolPtr); + int *intPtr); /* 32 */ EXTERN int Tcl_GetBooleanFromObj(Tcl_Interp *interp, - Tcl_Obj *objPtr, int *boolPtr); + Tcl_Obj *objPtr, int *intPtr); /* 33 */ EXTERN unsigned char * Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, - int *lengthPtr); + Tcl_Size *numBytesPtr); /* 34 */ EXTERN int Tcl_GetDouble(Tcl_Interp *interp, const char *src, double *doublePtr); /* 35 */ EXTERN int Tcl_GetDoubleFromObj(Tcl_Interp *interp, @@ -164,67 +154,69 @@ EXTERN int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 40 */ EXTERN const Tcl_ObjType * Tcl_GetObjType(const char *typeName); /* 41 */ -EXTERN char * Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr); +EXTERN char * TclGetStringFromObj(Tcl_Obj *objPtr, void *lengthPtr); /* 42 */ EXTERN void Tcl_InvalidateStringRep(Tcl_Obj *objPtr); /* 43 */ EXTERN int Tcl_ListObjAppendList(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 44 */ EXTERN int Tcl_ListObjAppendElement(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 45 */ -EXTERN int Tcl_ListObjGetElements(Tcl_Interp *interp, - Tcl_Obj *listPtr, int *objcPtr, +EXTERN int TclListObjGetElements(Tcl_Interp *interp, + Tcl_Obj *listPtr, void *objcPtr, Tcl_Obj ***objvPtr); /* 46 */ EXTERN int Tcl_ListObjIndex(Tcl_Interp *interp, - Tcl_Obj *listPtr, int index, + Tcl_Obj *listPtr, Tcl_Size index, Tcl_Obj **objPtrPtr); /* 47 */ -EXTERN int Tcl_ListObjLength(Tcl_Interp *interp, - Tcl_Obj *listPtr, int *lengthPtr); +EXTERN int TclListObjLength(Tcl_Interp *interp, + Tcl_Obj *listPtr, void *lengthPtr); /* 48 */ EXTERN int Tcl_ListObjReplace(Tcl_Interp *interp, - Tcl_Obj *listPtr, int first, int count, - int objc, Tcl_Obj *const objv[]); + Tcl_Obj *listPtr, Tcl_Size first, + Tcl_Size count, Tcl_Size objc, + Tcl_Obj *const objv[]); /* Slot 49 is reserved */ /* 50 */ EXTERN Tcl_Obj * Tcl_NewByteArrayObj(const unsigned char *bytes, - size_t length); + Tcl_Size numBytes); /* 51 */ EXTERN Tcl_Obj * Tcl_NewDoubleObj(double doubleValue); /* Slot 52 is reserved */ /* 53 */ -EXTERN Tcl_Obj * Tcl_NewListObj(int objc, Tcl_Obj *const objv[]); +EXTERN Tcl_Obj * Tcl_NewListObj(Tcl_Size objc, Tcl_Obj *const objv[]); /* Slot 54 is reserved */ /* 55 */ EXTERN Tcl_Obj * Tcl_NewObj(void); /* 56 */ -EXTERN Tcl_Obj * Tcl_NewStringObj(const char *bytes, size_t length); +EXTERN Tcl_Obj * Tcl_NewStringObj(const char *bytes, Tcl_Size length); /* Slot 57 is reserved */ /* 58 */ EXTERN unsigned char * Tcl_SetByteArrayLength(Tcl_Obj *objPtr, - size_t length); + Tcl_Size numBytes); /* 59 */ EXTERN void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, - const unsigned char *bytes, size_t length); + const unsigned char *bytes, + Tcl_Size numBytes); /* 60 */ EXTERN void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue); /* Slot 61 is reserved */ /* 62 */ -EXTERN void Tcl_SetListObj(Tcl_Obj *objPtr, int objc, +EXTERN void Tcl_SetListObj(Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* Slot 63 is reserved */ /* 64 */ -EXTERN void Tcl_SetObjLength(Tcl_Obj *objPtr, size_t length); +EXTERN void Tcl_SetObjLength(Tcl_Obj *objPtr, Tcl_Size length); /* 65 */ EXTERN void Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes, - size_t length); + Tcl_Size length); /* Slot 66 is reserved */ /* Slot 67 is reserved */ /* 68 */ EXTERN void Tcl_AllowExceptions(Tcl_Interp *interp); /* 69 */ @@ -253,30 +245,31 @@ EXTERN void Tcl_CallWhenDeleted(Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, void *clientData); /* 80 */ EXTERN void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, void *clientData); -/* Slot 81 is reserved */ +/* 81 */ +EXTERN int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan); /* 82 */ EXTERN int Tcl_CommandComplete(const char *cmd); /* 83 */ -EXTERN char * Tcl_Concat(int argc, const char *const *argv); +EXTERN char * Tcl_Concat(Tcl_Size argc, const char *const *argv); /* 84 */ -EXTERN size_t Tcl_ConvertElement(const char *src, char *dst, +EXTERN Tcl_Size Tcl_ConvertElement(const char *src, char *dst, int flags); /* 85 */ -EXTERN size_t Tcl_ConvertCountedElement(const char *src, - size_t length, char *dst, int flags); +EXTERN Tcl_Size Tcl_ConvertCountedElement(const char *src, + Tcl_Size length, char *dst, int flags); /* 86 */ EXTERN int Tcl_CreateAlias(Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, - const char *targetCmd, int argc, + const char *targetCmd, Tcl_Size argc, const char *const *argv); /* 87 */ EXTERN int Tcl_CreateAliasObj(Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, - const char *targetCmd, int objc, + const char *targetCmd, Tcl_Size objc, Tcl_Obj *const objv[]); /* 88 */ EXTERN Tcl_Channel Tcl_CreateChannel(const Tcl_ChannelType *typePtr, const char *chanName, void *instanceData, int mask); @@ -311,11 +304,11 @@ int isSafe); /* 98 */ EXTERN Tcl_TimerToken Tcl_CreateTimerHandler(int milliseconds, Tcl_TimerProc *proc, void *clientData); /* 99 */ -EXTERN Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, int level, +EXTERN Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, Tcl_Size level, Tcl_CmdTraceProc *proc, void *clientData); /* 100 */ EXTERN void Tcl_DeleteAssocData(Tcl_Interp *interp, const char *name); /* 101 */ @@ -345,11 +338,11 @@ /* 109 */ EXTERN void Tcl_DeleteHashTable(Tcl_HashTable *tablePtr); /* 110 */ EXTERN void Tcl_DeleteInterp(Tcl_Interp *interp); /* 111 */ -EXTERN void Tcl_DetachPids(int numPids, Tcl_Pid *pidPtr); +EXTERN void Tcl_DetachPids(Tcl_Size numPids, Tcl_Pid *pidPtr); /* 112 */ EXTERN void Tcl_DeleteTimerHandler(Tcl_TimerToken token); /* 113 */ EXTERN void Tcl_DeleteTrace(Tcl_Interp *interp, Tcl_Trace trace); /* 114 */ @@ -359,11 +352,11 @@ EXTERN int Tcl_DoOneEvent(int flags); /* 116 */ EXTERN void Tcl_DoWhenIdle(Tcl_IdleProc *proc, void *clientData); /* 117 */ EXTERN char * Tcl_DStringAppend(Tcl_DString *dsPtr, - const char *bytes, size_t length); + const char *bytes, Tcl_Size length); /* 118 */ EXTERN char * Tcl_DStringAppendElement(Tcl_DString *dsPtr, const char *element); /* 119 */ EXTERN void Tcl_DStringEndSublist(Tcl_DString *dsPtr); @@ -377,11 +370,11 @@ /* 123 */ EXTERN void Tcl_DStringResult(Tcl_Interp *interp, Tcl_DString *dsPtr); /* 124 */ EXTERN void Tcl_DStringSetLength(Tcl_DString *dsPtr, - size_t length); + Tcl_Size length); /* 125 */ EXTERN void Tcl_DStringStartSublist(Tcl_DString *dsPtr); /* 126 */ EXTERN int Tcl_Eof(Tcl_Channel chan); /* 127 */ @@ -452,11 +445,11 @@ Tcl_InterpDeleteProc **procPtr); /* 151 */ EXTERN Tcl_Channel Tcl_GetChannel(Tcl_Interp *interp, const char *chanName, int *modePtr); /* 152 */ -EXTERN int Tcl_GetChannelBufferSize(Tcl_Channel chan); +EXTERN Tcl_Size Tcl_GetChannelBufferSize(Tcl_Channel chan); /* 153 */ EXTERN int Tcl_GetChannelHandle(Tcl_Channel chan, int direction, void **handlePtr); /* 154 */ EXTERN void * Tcl_GetChannelInstanceData(Tcl_Channel chan); @@ -487,28 +480,20 @@ EXTERN Tcl_Interp * Tcl_GetParent(Tcl_Interp *interp); /* 165 */ EXTERN const char * Tcl_GetNameOfExecutable(void); /* 166 */ EXTERN Tcl_Obj * Tcl_GetObjResult(Tcl_Interp *interp); -#if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ /* 167 */ EXTERN int Tcl_GetOpenFile(Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, void **filePtr); -#endif /* UNIX */ -#ifdef MAC_OSX_TCL /* MACOSX */ -/* 167 */ -EXTERN int Tcl_GetOpenFile(Tcl_Interp *interp, - const char *chanID, int forWriting, - int checkUsage, void **filePtr); -#endif /* MACOSX */ /* 168 */ EXTERN Tcl_PathType Tcl_GetPathType(const char *path); /* 169 */ -EXTERN size_t Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr); +EXTERN Tcl_Size Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr); /* 170 */ -EXTERN size_t Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr); +EXTERN Tcl_Size Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr); /* 171 */ EXTERN int Tcl_GetServiceMode(void); /* 172 */ EXTERN Tcl_Interp * Tcl_GetChild(Tcl_Interp *interp, const char *name); /* 173 */ @@ -536,24 +521,23 @@ /* 184 */ EXTERN int Tcl_InterpDeleted(Tcl_Interp *interp); /* 185 */ EXTERN int Tcl_IsSafe(Tcl_Interp *interp); /* 186 */ -EXTERN char * Tcl_JoinPath(int argc, const char *const *argv, +EXTERN char * Tcl_JoinPath(Tcl_Size argc, const char *const *argv, Tcl_DString *resultPtr); /* 187 */ EXTERN int Tcl_LinkVar(Tcl_Interp *interp, const char *varName, void *addr, int type); /* Slot 188 is reserved */ /* 189 */ EXTERN Tcl_Channel Tcl_MakeFileChannel(void *handle, int mode); -/* 190 */ -EXTERN int Tcl_MakeSafe(Tcl_Interp *interp); +/* Slot 190 is reserved */ /* 191 */ EXTERN Tcl_Channel Tcl_MakeTcpClientChannel(void *tcpSocket); /* 192 */ -EXTERN char * Tcl_Merge(int argc, const char *const *argv); +EXTERN char * Tcl_Merge(Tcl_Size argc, const char *const *argv); /* 193 */ EXTERN Tcl_HashEntry * Tcl_NextHashEntry(Tcl_HashSearch *searchPtr); /* 194 */ EXTERN void Tcl_NotifyChannel(Tcl_Channel channel, int mask); /* 195 */ @@ -562,20 +546,20 @@ /* 196 */ EXTERN Tcl_Obj * Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 197 */ -EXTERN Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc, - const char **argv, int flags); +EXTERN Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, + Tcl_Size argc, const char **argv, int flags); /* 198 */ EXTERN Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions); /* 199 */ EXTERN Tcl_Channel Tcl_OpenTcpClient(Tcl_Interp *interp, int port, const char *address, const char *myaddr, - int myport, int async); + int myport, int flags); /* 200 */ EXTERN Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port, const char *host, Tcl_TcpAcceptProc *acceptProc, void *callbackData); @@ -587,15 +571,14 @@ /* 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); +EXTERN void Tcl_QueueEvent(Tcl_Event *evPtr, int position); /* 206 */ -EXTERN size_t Tcl_Read(Tcl_Channel chan, char *bufPtr, - size_t toRead); +EXTERN Tcl_Size Tcl_Read(Tcl_Channel chan, char *bufPtr, + Tcl_Size toRead); /* 207 */ EXTERN void Tcl_ReapDetachedProcs(void); /* 208 */ EXTERN int Tcl_RecordAndEval(Tcl_Interp *interp, const char *cmd, int flags); @@ -615,21 +598,21 @@ const char *text, const char *start); /* 214 */ EXTERN int Tcl_RegExpMatch(Tcl_Interp *interp, const char *text, const char *pattern); /* 215 */ -EXTERN void Tcl_RegExpRange(Tcl_RegExp regexp, size_t index, +EXTERN void Tcl_RegExpRange(Tcl_RegExp regexp, Tcl_Size index, const char **startPtr, const char **endPtr); /* 216 */ EXTERN void Tcl_Release(void *clientData); /* 217 */ EXTERN void Tcl_ResetResult(Tcl_Interp *interp); /* 218 */ -EXTERN size_t Tcl_ScanElement(const char *src, int *flagPtr); +EXTERN Tcl_Size Tcl_ScanElement(const char *src, int *flagPtr); /* 219 */ -EXTERN size_t Tcl_ScanCountedElement(const char *src, - size_t length, int *flagPtr); +EXTERN Tcl_Size Tcl_ScanCountedElement(const char *src, + Tcl_Size length, int *flagPtr); /* Slot 220 is reserved */ /* 221 */ EXTERN int Tcl_ServiceAll(void); /* 222 */ EXTERN int Tcl_ServiceEvent(int flags); @@ -636,11 +619,12 @@ /* 223 */ EXTERN void Tcl_SetAssocData(Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc *proc, void *clientData); /* 224 */ -EXTERN void Tcl_SetChannelBufferSize(Tcl_Channel chan, int sz); +EXTERN void Tcl_SetChannelBufferSize(Tcl_Channel chan, + Tcl_Size sz); /* 225 */ EXTERN int Tcl_SetChannelOption(Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, const char *newValue); /* 226 */ @@ -653,11 +637,12 @@ EXTERN void Tcl_SetErrorCode(Tcl_Interp *interp, ...); /* 229 */ EXTERN void Tcl_SetMaxBlockTime(const Tcl_Time *timePtr); /* Slot 230 is reserved */ /* 231 */ -EXTERN int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth); +EXTERN Tcl_Size Tcl_SetRecursionLimit(Tcl_Interp *interp, + Tcl_Size depth); /* Slot 232 is reserved */ /* 233 */ EXTERN int Tcl_SetServiceMode(int mode); /* 234 */ EXTERN void Tcl_SetObjErrorCode(Tcl_Interp *interp, @@ -677,15 +662,14 @@ /* 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); +EXTERN int TclSplitList(Tcl_Interp *interp, const char *listStr, + void *argcPtr, const char ***argvPtr); /* 243 */ -EXTERN void Tcl_SplitPath(const char *path, int *argcPtr, +EXTERN void TclSplitPath(const char *path, void *argcPtr, const char ***argvPtr); /* Slot 244 is reserved */ /* Slot 245 is reserved */ /* Slot 246 is reserved */ /* Slot 247 is reserved */ @@ -695,12 +679,12 @@ Tcl_VarTraceProc *proc, void *clientData); /* 249 */ EXTERN char * Tcl_TranslateFileName(Tcl_Interp *interp, const char *name, Tcl_DString *bufferPtr); /* 250 */ -EXTERN size_t Tcl_Ungets(Tcl_Channel chan, const char *str, - size_t len, int atHead); +EXTERN Tcl_Size Tcl_Ungets(Tcl_Channel chan, const char *str, + Tcl_Size len, int atHead); /* 251 */ EXTERN void Tcl_UnlinkVar(Tcl_Interp *interp, const char *varName); /* 252 */ EXTERN int Tcl_UnregisterChannel(Tcl_Interp *interp, @@ -730,14 +714,14 @@ EXTERN void * Tcl_VarTraceInfo2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *procPtr, void *prevClientData); /* 263 */ -EXTERN size_t Tcl_Write(Tcl_Channel chan, const char *s, - size_t slen); +EXTERN Tcl_Size Tcl_Write(Tcl_Channel chan, const char *s, + Tcl_Size slen); /* 264 */ -EXTERN void Tcl_WrongNumArgs(Tcl_Interp *interp, int objc, +EXTERN void Tcl_WrongNumArgs(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], const char *message); /* 265 */ EXTERN int Tcl_DumpActiveMemory(const char *fileName); /* 266 */ EXTERN void Tcl_ValidateAllMemory(const char *file, int line); @@ -790,29 +774,29 @@ EXTERN void Tcl_DeleteThreadExitHandler(Tcl_ExitProc *proc, void *clientData); /* Slot 290 is reserved */ /* 291 */ EXTERN int Tcl_EvalEx(Tcl_Interp *interp, const char *script, - size_t numBytes, int flags); + Tcl_Size numBytes, int flags); /* 292 */ -EXTERN int Tcl_EvalObjv(Tcl_Interp *interp, int objc, +EXTERN int Tcl_EvalObjv(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 293 */ EXTERN int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 294 */ EXTERN TCL_NORETURN void Tcl_ExitThread(int status); /* 295 */ EXTERN int Tcl_ExternalToUtf(Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, - size_t srcLen, int flags, + Tcl_Size srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, - size_t dstLen, int *srcReadPtr, + Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 296 */ EXTERN char * Tcl_ExternalToUtfDString(Tcl_Encoding encoding, - const char *src, size_t srcLen, + const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr); /* 297 */ EXTERN void Tcl_FinalizeThread(void); /* 298 */ EXTERN void Tcl_FinalizeNotifier(void *clientData); @@ -827,15 +811,15 @@ /* 303 */ EXTERN void Tcl_GetEncodingNames(Tcl_Interp *interp); /* 304 */ EXTERN int Tcl_GetIndexFromObjStruct(Tcl_Interp *interp, Tcl_Obj *objPtr, const void *tablePtr, - size_t offset, const char *msg, int flags, - int *indexPtr); + Tcl_Size offset, const char *msg, int flags, + void *indexPtr); /* 305 */ EXTERN void * Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, - size_t size); + Tcl_Size size); /* 306 */ EXTERN Tcl_Obj * Tcl_GetVar2Ex(Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 307 */ EXTERN void * Tcl_InitNotifier(void); @@ -847,14 +831,14 @@ EXTERN void Tcl_ConditionNotify(Tcl_Condition *condPtr); /* 311 */ EXTERN void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr, const Tcl_Time *timePtr); /* 312 */ -EXTERN size_t Tcl_NumUtfChars(const char *src, size_t length); +EXTERN Tcl_Size TclNumUtfChars(const char *src, Tcl_Size length); /* 313 */ -EXTERN size_t Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, - size_t charsToRead, int appendFlag); +EXTERN Tcl_Size Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, + Tcl_Size charsToRead, int appendFlag); /* Slot 314 is reserved */ /* Slot 315 is reserved */ /* 316 */ EXTERN int Tcl_SetSystemEncoding(Tcl_Interp *interp, const char *name); @@ -864,61 +848,61 @@ int flags); /* 318 */ EXTERN void Tcl_ThreadAlert(Tcl_ThreadId threadId); /* 319 */ EXTERN void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, - Tcl_Event *evPtr, Tcl_QueuePosition position); + Tcl_Event *evPtr, int position); /* 320 */ -EXTERN int Tcl_UniCharAtIndex(const char *src, size_t index); +EXTERN int Tcl_UniCharAtIndex(const char *src, Tcl_Size index); /* 321 */ EXTERN int Tcl_UniCharToLower(int ch); /* 322 */ EXTERN int Tcl_UniCharToTitle(int ch); /* 323 */ EXTERN int Tcl_UniCharToUpper(int ch); /* 324 */ -EXTERN int Tcl_UniCharToUtf(int ch, char *buf); +EXTERN Tcl_Size Tcl_UniCharToUtf(int ch, char *buf); /* 325 */ -EXTERN const char * Tcl_UtfAtIndex(const char *src, size_t index); +EXTERN const char * TclUtfAtIndex(const char *src, Tcl_Size index); /* 326 */ -EXTERN int Tcl_UtfCharComplete(const char *src, size_t length); +EXTERN int TclUtfCharComplete(const char *src, Tcl_Size length); /* 327 */ -EXTERN size_t Tcl_UtfBackslash(const char *src, int *readPtr, +EXTERN Tcl_Size Tcl_UtfBackslash(const char *src, int *readPtr, char *dst); /* 328 */ EXTERN const char * Tcl_UtfFindFirst(const char *src, int ch); /* 329 */ EXTERN const char * Tcl_UtfFindLast(const char *src, int ch); /* 330 */ -EXTERN const char * Tcl_UtfNext(const char *src); +EXTERN const char * TclUtfNext(const char *src); /* 331 */ -EXTERN const char * Tcl_UtfPrev(const char *src, const char *start); +EXTERN const char * TclUtfPrev(const char *src, const char *start); /* 332 */ EXTERN int Tcl_UtfToExternal(Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, - size_t srcLen, int flags, + Tcl_Size srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, - size_t dstLen, int *srcReadPtr, + Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 333 */ EXTERN char * Tcl_UtfToExternalDString(Tcl_Encoding encoding, - const char *src, size_t srcLen, + const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr); /* 334 */ -EXTERN int Tcl_UtfToLower(char *src); +EXTERN Tcl_Size Tcl_UtfToLower(char *src); /* 335 */ -EXTERN int Tcl_UtfToTitle(char *src); +EXTERN Tcl_Size Tcl_UtfToTitle(char *src); /* 336 */ -EXTERN int Tcl_UtfToChar16(const char *src, +EXTERN Tcl_Size Tcl_UtfToChar16(const char *src, unsigned short *chPtr); /* 337 */ -EXTERN int Tcl_UtfToUpper(char *src); +EXTERN Tcl_Size Tcl_UtfToUpper(char *src); /* 338 */ -EXTERN size_t Tcl_WriteChars(Tcl_Channel chan, const char *src, - size_t srcLen); +EXTERN Tcl_Size Tcl_WriteChars(Tcl_Channel chan, const char *src, + Tcl_Size srcLen); /* 339 */ -EXTERN size_t Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr); +EXTERN Tcl_Size Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr); /* 340 */ EXTERN char * Tcl_GetString(Tcl_Obj *objPtr); /* Slot 341 is reserved */ /* Slot 342 is reserved */ /* 343 */ @@ -937,48 +921,49 @@ EXTERN int Tcl_UniCharIsSpace(int ch); /* 350 */ EXTERN int Tcl_UniCharIsUpper(int ch); /* 351 */ EXTERN int Tcl_UniCharIsWordChar(int ch); -/* Slot 352 is reserved */ +/* 352 */ +EXTERN Tcl_Size Tcl_Char16Len(const unsigned short *uniStr); /* Slot 353 is reserved */ /* 354 */ EXTERN char * Tcl_Char16ToUtfDString(const unsigned short *uniStr, - size_t uniLength, Tcl_DString *dsPtr); + Tcl_Size uniLength, Tcl_DString *dsPtr); /* 355 */ EXTERN unsigned short * Tcl_UtfToChar16DString(const char *src, - size_t length, Tcl_DString *dsPtr); + Tcl_Size length, Tcl_DString *dsPtr); /* 356 */ EXTERN Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj, int flags); /* Slot 357 is reserved */ /* 358 */ EXTERN void Tcl_FreeParse(Tcl_Parse *parsePtr); /* 359 */ EXTERN void Tcl_LogCommandInfo(Tcl_Interp *interp, const char *script, const char *command, - size_t length); + Tcl_Size length); /* 360 */ EXTERN int Tcl_ParseBraces(Tcl_Interp *interp, - const char *start, size_t numBytes, + const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 361 */ EXTERN int Tcl_ParseCommand(Tcl_Interp *interp, - const char *start, size_t numBytes, + const char *start, Tcl_Size numBytes, int nested, Tcl_Parse *parsePtr); /* 362 */ EXTERN int Tcl_ParseExpr(Tcl_Interp *interp, const char *start, - size_t numBytes, Tcl_Parse *parsePtr); + Tcl_Size numBytes, Tcl_Parse *parsePtr); /* 363 */ EXTERN int Tcl_ParseQuotedString(Tcl_Interp *interp, - const char *start, size_t numBytes, + const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 364 */ EXTERN int Tcl_ParseVarName(Tcl_Interp *interp, - const char *start, size_t numBytes, + const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr, int append); /* 365 */ EXTERN char * Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 366 */ EXTERN int Tcl_Chdir(const char *dirName); @@ -1003,58 +988,63 @@ /* 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); + 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, - size_t numChars); + Tcl_Size numChars); /* 379 */ EXTERN void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, - const Tcl_UniChar *unicode, size_t numChars); + const Tcl_UniChar *unicode, + Tcl_Size numChars); /* 380 */ -EXTERN size_t Tcl_GetCharLength(Tcl_Obj *objPtr); +EXTERN Tcl_Size TclGetCharLength(Tcl_Obj *objPtr); /* 381 */ -EXTERN int Tcl_GetUniChar(Tcl_Obj *objPtr, size_t index); +EXTERN int TclGetUniChar(Tcl_Obj *objPtr, Tcl_Size index); /* Slot 382 is reserved */ /* 383 */ -EXTERN Tcl_Obj * Tcl_GetRange(Tcl_Obj *objPtr, size_t first, - size_t last); -/* Slot 384 is reserved */ +EXTERN Tcl_Obj * TclGetRange(Tcl_Obj *objPtr, Tcl_Size first, + Tcl_Size last); +/* 384 */ +EXTERN void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, + const Tcl_UniChar *unicode, Tcl_Size length); /* 385 */ EXTERN int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *textObj, Tcl_Obj *patternObj); /* 386 */ -EXTERN void Tcl_SetNotifier(Tcl_NotifierProcs *notifierProcPtr); +EXTERN void Tcl_SetNotifier( + const Tcl_NotifierProcs *notifierProcPtr); /* 387 */ EXTERN Tcl_Mutex * Tcl_GetAllocMutex(void); /* 388 */ EXTERN int Tcl_GetChannelNames(Tcl_Interp *interp); /* 389 */ EXTERN int Tcl_GetChannelNamesEx(Tcl_Interp *interp, const char *pattern); /* 390 */ EXTERN int Tcl_ProcObjCmd(void *clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]); + Tcl_Size objc, Tcl_Obj *const objv[]); /* 391 */ EXTERN void Tcl_ConditionFinalize(Tcl_Condition *condPtr); /* 392 */ EXTERN void Tcl_MutexFinalize(Tcl_Mutex *mutex); /* 393 */ EXTERN int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, - size_t stackSize, int flags); + TCL_HASH_TYPE stackSize, int flags); /* 394 */ -EXTERN size_t Tcl_ReadRaw(Tcl_Channel chan, char *dst, - size_t bytesToRead); +EXTERN Tcl_Size Tcl_ReadRaw(Tcl_Channel chan, char *dst, + Tcl_Size bytesToRead); /* 395 */ -EXTERN size_t Tcl_WriteRaw(Tcl_Channel chan, const char *src, - size_t srcLen); +EXTERN Tcl_Size Tcl_WriteRaw(Tcl_Channel chan, const char *src, + Tcl_Size srcLen); /* 396 */ EXTERN Tcl_Channel Tcl_GetTopChannel(Tcl_Channel chan); /* 397 */ EXTERN int Tcl_ChannelBuffered(Tcl_Channel chan); /* 398 */ @@ -1130,27 +1120,27 @@ /* 427 */ EXTERN void Tcl_UntraceCommand(Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, void *clientData); /* 428 */ -EXTERN void * Tcl_AttemptAlloc(size_t size); +EXTERN void * Tcl_AttemptAlloc(TCL_HASH_TYPE size); /* 429 */ -EXTERN void * Tcl_AttemptDbCkalloc(size_t size, const char *file, - int line); +EXTERN void * Tcl_AttemptDbCkalloc(TCL_HASH_TYPE size, + const char *file, int line); /* 430 */ -EXTERN void * Tcl_AttemptRealloc(void *ptr, size_t size); +EXTERN void * Tcl_AttemptRealloc(void *ptr, TCL_HASH_TYPE size); /* 431 */ -EXTERN void * Tcl_AttemptDbCkrealloc(void *ptr, size_t size, +EXTERN void * Tcl_AttemptDbCkrealloc(void *ptr, TCL_HASH_TYPE size, const char *file, int line); /* 432 */ EXTERN int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, - size_t length); + Tcl_Size length); /* 433 */ EXTERN Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel); /* 434 */ -EXTERN Tcl_UniChar * Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, - int *lengthPtr); +EXTERN Tcl_UniChar * TclGetUnicodeFromObj(Tcl_Obj *objPtr, + void *lengthPtr); /* Slot 435 is reserved */ /* Slot 436 is reserved */ /* 437 */ EXTERN Tcl_Obj * Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); @@ -1170,12 +1160,12 @@ /* 443 */ EXTERN int Tcl_FSDeleteFile(Tcl_Obj *pathPtr); /* 444 */ EXTERN int Tcl_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, const char *sym2, - Tcl_PackageInitProc **proc1Ptr, - Tcl_PackageInitProc **proc2Ptr, + Tcl_LibraryInitProc **proc1Ptr, + Tcl_LibraryInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 445 */ EXTERN int Tcl_FSMatchInDirectory(Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, @@ -1216,21 +1206,21 @@ EXTERN int Tcl_FSChdir(Tcl_Obj *pathPtr); /* 459 */ EXTERN int Tcl_FSConvertToPathType(Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 460 */ -EXTERN Tcl_Obj * Tcl_FSJoinPath(Tcl_Obj *listObj, int elements); +EXTERN Tcl_Obj * Tcl_FSJoinPath(Tcl_Obj *listObj, Tcl_Size elements); /* 461 */ -EXTERN Tcl_Obj * Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *lenPtr); +EXTERN Tcl_Obj * TclFSSplitPath(Tcl_Obj *pathPtr, void *lenPtr); /* 462 */ EXTERN int Tcl_FSEqualPaths(Tcl_Obj *firstPtr, Tcl_Obj *secondPtr); /* 463 */ EXTERN Tcl_Obj * Tcl_FSGetNormalizedPath(Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 464 */ -EXTERN Tcl_Obj * Tcl_FSJoinToPath(Tcl_Obj *pathPtr, int objc, +EXTERN Tcl_Obj * Tcl_FSJoinToPath(Tcl_Obj *pathPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* 465 */ EXTERN void * Tcl_FSGetInternalRep(Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr); /* 466 */ @@ -1268,16 +1258,17 @@ EXTERN int Tcl_OutputBuffered(Tcl_Channel chan); /* 480 */ EXTERN void Tcl_FSMountsChanged(const Tcl_Filesystem *fsPtr); /* 481 */ EXTERN int Tcl_EvalTokensStandard(Tcl_Interp *interp, - Tcl_Token *tokenPtr, size_t count); + Tcl_Token *tokenPtr, Tcl_Size count); /* 482 */ EXTERN void Tcl_GetTime(Tcl_Time *timeBuf); /* 483 */ -EXTERN Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, int level, - int flags, Tcl_CmdObjTraceProc *objProc, +EXTERN Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, + Tcl_Size level, int flags, + Tcl_CmdObjTraceProc *objProc, void *clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 484 */ EXTERN int Tcl_GetCommandInfoFromToken(Tcl_Command token, Tcl_CmdInfo *infoPtr); @@ -1296,14 +1287,14 @@ EXTERN void Tcl_SetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt wideValue); /* 490 */ EXTERN Tcl_StatBuf * Tcl_AllocStatBuf(void); /* 491 */ -EXTERN Tcl_WideInt Tcl_Seek(Tcl_Channel chan, Tcl_WideInt offset, +EXTERN long long Tcl_Seek(Tcl_Channel chan, long long offset, int mode); /* 492 */ -EXTERN Tcl_WideInt Tcl_Tell(Tcl_Channel chan); +EXTERN long long Tcl_Tell(Tcl_Channel chan); /* 493 */ EXTERN Tcl_DriverWideSeekProc * Tcl_ChannelWideSeekProc( const Tcl_ChannelType *chanTypePtr); /* 494 */ EXTERN int Tcl_DictObjPut(Tcl_Interp *interp, Tcl_Obj *dictPtr, @@ -1313,12 +1304,12 @@ Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr); /* 496 */ EXTERN int Tcl_DictObjRemove(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr); /* 497 */ -EXTERN int Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, - int *sizePtr); +EXTERN int TclDictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, + void *sizePtr); /* 498 */ EXTERN int Tcl_DictObjFirst(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); @@ -1328,15 +1319,15 @@ int *donePtr); /* 500 */ EXTERN void Tcl_DictObjDone(Tcl_DictSearch *searchPtr); /* 501 */ EXTERN int Tcl_DictObjPutKeyList(Tcl_Interp *interp, - Tcl_Obj *dictPtr, int keyc, + Tcl_Obj *dictPtr, Tcl_Size keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr); /* 502 */ EXTERN int Tcl_DictObjRemoveKeyList(Tcl_Interp *interp, - Tcl_Obj *dictPtr, int keyc, + Tcl_Obj *dictPtr, Tcl_Size keyc, Tcl_Obj *const *keyv); /* 503 */ EXTERN Tcl_Obj * Tcl_NewDictObj(void); /* 504 */ EXTERN Tcl_Obj * Tcl_DbNewDictObj(const char *file, int line); @@ -1399,11 +1390,11 @@ EXTERN int Tcl_LimitCheck(Tcl_Interp *interp); /* 524 */ EXTERN int Tcl_LimitExceeded(Tcl_Interp *interp); /* 525 */ EXTERN void Tcl_LimitSetCommands(Tcl_Interp *interp, - int commandLimit); + Tcl_Size commandLimit); /* 526 */ EXTERN void Tcl_LimitSetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr); /* 527 */ EXTERN void Tcl_LimitSetGranularity(Tcl_Interp *interp, int type, @@ -1496,11 +1487,11 @@ /* 559 */ EXTERN int Tcl_TakeBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, void *value); /* 560 */ EXTERN int Tcl_TruncateChannel(Tcl_Channel chan, - Tcl_WideInt length); + long long length); /* 561 */ EXTERN Tcl_DriverTruncateProc * Tcl_ChannelTruncateProc( const Tcl_ChannelType *chanTypePtr); /* 562 */ EXTERN void Tcl_SetChannelErrorInterp(Tcl_Interp *interp, @@ -1531,26 +1522,26 @@ /* 572 */ EXTERN const char * Tcl_GetEncodingNameFromEnvironment( Tcl_DString *bufPtr); /* 573 */ EXTERN int Tcl_PkgRequireProc(Tcl_Interp *interp, - const char *name, int objc, + const char *name, Tcl_Size objc, Tcl_Obj *const objv[], void *clientDataPtr); /* 574 */ EXTERN void Tcl_AppendObjToErrorInfo(Tcl_Interp *interp, Tcl_Obj *objPtr); /* 575 */ EXTERN void Tcl_AppendLimitedToObj(Tcl_Obj *objPtr, - const char *bytes, size_t length, - size_t limit, const char *ellipsis); + const char *bytes, Tcl_Size length, + Tcl_Size limit, const char *ellipsis); /* 576 */ EXTERN Tcl_Obj * Tcl_Format(Tcl_Interp *interp, const char *format, - int objc, Tcl_Obj *const objv[]); + Tcl_Size objc, Tcl_Obj *const objv[]); /* 577 */ EXTERN int Tcl_AppendFormatToObj(Tcl_Interp *interp, Tcl_Obj *objPtr, const char *format, - int objc, Tcl_Obj *const objv[]); + Tcl_Size objc, Tcl_Obj *const objv[]); /* 578 */ EXTERN Tcl_Obj * Tcl_ObjPrintf(const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 579 */ EXTERN void Tcl_AppendPrintfToObj(Tcl_Obj *objPtr, const char *format, ...) TCL_FORMAT_PRINTF(2, 3); @@ -1571,23 +1562,24 @@ Tcl_CmdDeleteProc *deleteProc); /* 584 */ EXTERN int Tcl_NREvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 585 */ -EXTERN int Tcl_NREvalObjv(Tcl_Interp *interp, int objc, +EXTERN int Tcl_NREvalObjv(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 586 */ EXTERN int Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd, - int objc, Tcl_Obj *const objv[], int flags); + Tcl_Size objc, Tcl_Obj *const objv[], + int flags); /* 587 */ EXTERN void Tcl_NRAddCallback(Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, void *data0, void *data1, void *data2, void *data3); /* 588 */ EXTERN int Tcl_NRCallObjProc(Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, void *clientData, - int objc, Tcl_Obj *const objv[]); + Tcl_Size objc, Tcl_Obj *const objv[]); /* 589 */ EXTERN unsigned Tcl_GetFSDeviceFromStat(const Tcl_StatBuf *statPtr); /* 590 */ EXTERN unsigned Tcl_GetFSInodeFromStat(const Tcl_StatBuf *statPtr); /* 591 */ @@ -1599,31 +1591,31 @@ /* 594 */ EXTERN int Tcl_GetGroupIdFromStat(const Tcl_StatBuf *statPtr); /* 595 */ EXTERN int Tcl_GetDeviceTypeFromStat(const Tcl_StatBuf *statPtr); /* 596 */ -EXTERN Tcl_WideInt Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr); +EXTERN long long Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr); /* 597 */ -EXTERN Tcl_WideInt Tcl_GetModificationTimeFromStat( +EXTERN long long Tcl_GetModificationTimeFromStat( const Tcl_StatBuf *statPtr); /* 598 */ -EXTERN Tcl_WideInt Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr); +EXTERN long long Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr); /* 599 */ -EXTERN Tcl_WideUInt Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr); +EXTERN unsigned long long Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr); /* 600 */ -EXTERN Tcl_WideUInt Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr); +EXTERN unsigned long long Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr); /* 601 */ EXTERN unsigned Tcl_GetBlockSizeFromStat(const Tcl_StatBuf *statPtr); /* 602 */ EXTERN int Tcl_SetEnsembleParameterList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *paramList); /* 603 */ EXTERN int Tcl_GetEnsembleParameterList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **paramListPtr); /* 604 */ -EXTERN int Tcl_ParseArgsObjv(Tcl_Interp *interp, - const Tcl_ArgvInfo *argTable, int *objcPtr, +EXTERN int TclParseArgsObjv(Tcl_Interp *interp, + const Tcl_ArgvInfo *argTable, void *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 605 */ EXTERN int Tcl_GetErrorLine(Tcl_Interp *interp); /* 606 */ EXTERN void Tcl_SetErrorLine(Tcl_Interp *interp, int lineNum); @@ -1638,18 +1630,18 @@ EXTERN int Tcl_ZlibDeflate(Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj); /* 611 */ EXTERN int Tcl_ZlibInflate(Tcl_Interp *interp, int format, - Tcl_Obj *data, size_t buffersize, + Tcl_Obj *data, Tcl_Size buffersize, Tcl_Obj *gzipHeaderDictObj); /* 612 */ EXTERN unsigned int Tcl_ZlibCRC32(unsigned int crc, - const unsigned char *buf, size_t len); + const unsigned char *buf, Tcl_Size len); /* 613 */ EXTERN unsigned int Tcl_ZlibAdler32(unsigned int adler, - const unsigned char *buf, size_t len); + const unsigned char *buf, Tcl_Size len); /* 614 */ EXTERN int Tcl_ZlibStreamInit(Tcl_Interp *interp, int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle); /* 615 */ @@ -1661,11 +1653,11 @@ /* 618 */ EXTERN int Tcl_ZlibStreamPut(Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush); /* 619 */ EXTERN int Tcl_ZlibStreamGet(Tcl_ZlibStream zshandle, - Tcl_Obj *data, size_t count); + Tcl_Obj *data, Tcl_Size count); /* 620 */ EXTERN int Tcl_ZlibStreamClose(Tcl_ZlibStream zshandle); /* 621 */ EXTERN int Tcl_ZlibStreamReset(Tcl_ZlibStream zshandle); /* 622 */ @@ -1697,38 +1689,38 @@ Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); /* 631 */ EXTERN Tcl_Channel Tcl_OpenTcpServerEx(Tcl_Interp *interp, const char *service, const char *host, - unsigned int flags, + unsigned int flags, int backlog, Tcl_TcpAcceptProc *acceptProc, void *callbackData); /* 632 */ EXTERN int TclZipfs_Mount(Tcl_Interp *interp, - const char *mountPoint, const char *zipname, + const char *zipname, const char *mountPoint, const char *passwd); /* 633 */ EXTERN int TclZipfs_Unmount(Tcl_Interp *interp, const char *mountPoint); /* 634 */ EXTERN Tcl_Obj * TclZipfs_TclLibrary(void); /* 635 */ EXTERN int TclZipfs_MountBuffer(Tcl_Interp *interp, - const char *mountPoint, unsigned char *data, - size_t datalen, int copy); + const void *data, size_t datalen, + const char *mountPoint, int copy); /* 636 */ -EXTERN void Tcl_FreeIntRep(Tcl_Obj *objPtr); +EXTERN void Tcl_FreeInternalRep(Tcl_Obj *objPtr); /* 637 */ EXTERN char * Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes, - size_t numBytes); + TCL_HASH_TYPE numBytes); /* 638 */ -EXTERN Tcl_ObjIntRep * Tcl_FetchIntRep(Tcl_Obj *objPtr, +EXTERN Tcl_ObjInternalRep * Tcl_FetchInternalRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 639 */ -EXTERN void Tcl_StoreIntRep(Tcl_Obj *objPtr, +EXTERN void Tcl_StoreInternalRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, - const Tcl_ObjIntRep *irPtr); + const Tcl_ObjInternalRep *irPtr); /* 640 */ EXTERN int Tcl_HasStringRep(Tcl_Obj *objPtr); /* 641 */ EXTERN void Tcl_IncrRefCount(Tcl_Obj *objPtr); /* 642 */ @@ -1736,23 +1728,146 @@ /* 643 */ EXTERN int Tcl_IsShared(Tcl_Obj *objPtr); /* 644 */ EXTERN int Tcl_LinkArray(Tcl_Interp *interp, const char *varName, void *addr, int type, - size_t size); + Tcl_Size size); /* 645 */ EXTERN int Tcl_GetIntForIndex(Tcl_Interp *interp, - Tcl_Obj *objPtr, size_t endValue, - size_t *indexPtr); + Tcl_Obj *objPtr, Tcl_Size endValue, + Tcl_Size *indexPtr); /* 646 */ -EXTERN int Tcl_UtfToUniChar(const char *src, int *chPtr); +EXTERN Tcl_Size Tcl_UtfToUniChar(const char *src, int *chPtr); /* 647 */ EXTERN char * Tcl_UniCharToUtfDString(const int *uniStr, - size_t uniLength, Tcl_DString *dsPtr); + Tcl_Size uniLength, Tcl_DString *dsPtr); /* 648 */ EXTERN int * Tcl_UtfToUniCharDString(const char *src, - size_t length, Tcl_DString *dsPtr); + Tcl_Size length, Tcl_DString *dsPtr); +/* 649 */ +EXTERN unsigned char * TclGetBytesFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, void *numBytesPtr); +/* 650 */ +EXTERN unsigned char * Tcl_GetBytesFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, Tcl_Size *numBytesPtr); +/* 651 */ +EXTERN char * Tcl_GetStringFromObj(Tcl_Obj *objPtr, + Tcl_Size *lengthPtr); +/* 652 */ +EXTERN Tcl_UniChar * Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, + Tcl_Size *lengthPtr); +/* 653 */ +EXTERN int Tcl_GetSizeIntFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, Tcl_Size *sizePtr); +/* 654 */ +EXTERN int Tcl_UtfCharComplete(const char *src, Tcl_Size length); +/* 655 */ +EXTERN const char * Tcl_UtfNext(const char *src); +/* 656 */ +EXTERN const char * Tcl_UtfPrev(const char *src, const char *start); +/* 657 */ +EXTERN int Tcl_UniCharIsUnicode(int ch); +/* 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); +/* Slot 686 is reserved */ +/* Slot 687 is reserved */ +/* 688 */ +EXTERN void TclUnusedStubEntry(void); typedef struct { const struct TclPlatStubs *tclPlatStubs; const struct TclIntStubs *tclIntStubs; const struct TclIntPlatStubs *tclIntPlatStubs; @@ -1763,89 +1878,73 @@ 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_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, size_t length); /* 16 */ - Tcl_Obj * (*tcl_ConcatObj) (int objc, Tcl_Obj *const objv[]); /* 17 */ + void (*tcl_AppendToObj) (Tcl_Obj *objPtr, const char *bytes, Tcl_Size length); /* 16 */ + Tcl_Obj * (*tcl_ConcatObj) (Tcl_Size objc, Tcl_Obj *const objv[]); /* 17 */ int (*tcl_ConvertToType) (Tcl_Interp *interp, Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 18 */ void (*tcl_DbDecrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 19 */ void (*tcl_DbIncrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 20 */ int (*tcl_DbIsShared) (Tcl_Obj *objPtr, const char *file, int line); /* 21 */ void (*reserved22)(void); - Tcl_Obj * (*tcl_DbNewByteArrayObj) (const unsigned char *bytes, size_t length, const char *file, int line); /* 23 */ + Tcl_Obj * (*tcl_DbNewByteArrayObj) (const unsigned char *bytes, Tcl_Size numBytes, const char *file, int line); /* 23 */ Tcl_Obj * (*tcl_DbNewDoubleObj) (double doubleValue, const char *file, int line); /* 24 */ - Tcl_Obj * (*tcl_DbNewListObj) (int objc, Tcl_Obj *const *objv, const char *file, int line); /* 25 */ + Tcl_Obj * (*tcl_DbNewListObj) (Tcl_Size objc, Tcl_Obj *const *objv, const char *file, int line); /* 25 */ void (*reserved26)(void); Tcl_Obj * (*tcl_DbNewObj) (const char *file, int line); /* 27 */ - Tcl_Obj * (*tcl_DbNewStringObj) (const char *bytes, size_t length, const char *file, int line); /* 28 */ + Tcl_Obj * (*tcl_DbNewStringObj) (const char *bytes, Tcl_Size length, const char *file, int line); /* 28 */ Tcl_Obj * (*tcl_DuplicateObj) (Tcl_Obj *objPtr); /* 29 */ void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */ - int (*tcl_GetBoolean) (Tcl_Interp *interp, const char *src, int *boolPtr); /* 31 */ - int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *boolPtr); /* 32 */ - unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 33 */ + int (*tcl_GetBoolean) (Tcl_Interp *interp, const char *src, int *intPtr); /* 31 */ + int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 32 */ + unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, Tcl_Size *numBytesPtr); /* 33 */ int (*tcl_GetDouble) (Tcl_Interp *interp, const char *src, double *doublePtr); /* 34 */ int (*tcl_GetDoubleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 35 */ void (*reserved36)(void); int (*tcl_GetInt) (Tcl_Interp *interp, const char *src, int *intPtr); /* 37 */ int (*tcl_GetIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 38 */ int (*tcl_GetLongFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 39 */ const Tcl_ObjType * (*tcl_GetObjType) (const char *typeName); /* 40 */ - char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 41 */ + char * (*tclGetStringFromObj) (Tcl_Obj *objPtr, void *lengthPtr); /* 41 */ void (*tcl_InvalidateStringRep) (Tcl_Obj *objPtr); /* 42 */ int (*tcl_ListObjAppendList) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 43 */ int (*tcl_ListObjAppendElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 44 */ - int (*tcl_ListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 45 */ - int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj **objPtrPtr); /* 46 */ - int (*tcl_ListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr); /* 47 */ - int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, int first, int count, int objc, Tcl_Obj *const objv[]); /* 48 */ + int (*tclListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, void *objcPtr, Tcl_Obj ***objvPtr); /* 45 */ + int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index, Tcl_Obj **objPtrPtr); /* 46 */ + int (*tclListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, void *lengthPtr); /* 47 */ + int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size first, Tcl_Size count, Tcl_Size objc, Tcl_Obj *const objv[]); /* 48 */ void (*reserved49)(void); - Tcl_Obj * (*tcl_NewByteArrayObj) (const unsigned char *bytes, size_t length); /* 50 */ + Tcl_Obj * (*tcl_NewByteArrayObj) (const unsigned char *bytes, Tcl_Size numBytes); /* 50 */ Tcl_Obj * (*tcl_NewDoubleObj) (double doubleValue); /* 51 */ void (*reserved52)(void); - Tcl_Obj * (*tcl_NewListObj) (int objc, Tcl_Obj *const objv[]); /* 53 */ + Tcl_Obj * (*tcl_NewListObj) (Tcl_Size objc, Tcl_Obj *const objv[]); /* 53 */ void (*reserved54)(void); Tcl_Obj * (*tcl_NewObj) (void); /* 55 */ - Tcl_Obj * (*tcl_NewStringObj) (const char *bytes, size_t length); /* 56 */ + Tcl_Obj * (*tcl_NewStringObj) (const char *bytes, Tcl_Size length); /* 56 */ void (*reserved57)(void); - unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, size_t length); /* 58 */ - void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, const unsigned char *bytes, size_t length); /* 59 */ + unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, Tcl_Size numBytes); /* 58 */ + void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, const unsigned char *bytes, Tcl_Size numBytes); /* 59 */ void (*tcl_SetDoubleObj) (Tcl_Obj *objPtr, double doubleValue); /* 60 */ void (*reserved61)(void); - void (*tcl_SetListObj) (Tcl_Obj *objPtr, int objc, Tcl_Obj *const objv[]); /* 62 */ + void (*tcl_SetListObj) (Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* 62 */ void (*reserved63)(void); - void (*tcl_SetObjLength) (Tcl_Obj *objPtr, size_t length); /* 64 */ - void (*tcl_SetStringObj) (Tcl_Obj *objPtr, const char *bytes, size_t length); /* 65 */ + void (*tcl_SetObjLength) (Tcl_Obj *objPtr, Tcl_Size length); /* 64 */ + void (*tcl_SetStringObj) (Tcl_Obj *objPtr, const char *bytes, Tcl_Size length); /* 65 */ void (*reserved66)(void); void (*reserved67)(void); void (*tcl_AllowExceptions) (Tcl_Interp *interp); /* 68 */ void (*tcl_AppendElement) (Tcl_Interp *interp, const char *element); /* 69 */ void (*tcl_AppendResult) (Tcl_Interp *interp, ...); /* 70 */ @@ -1857,17 +1956,17 @@ void (*reserved76)(void); void (*reserved77)(void); int (*tcl_BadChannelOption) (Tcl_Interp *interp, const char *optionName, const char *optionList); /* 78 */ void (*tcl_CallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, void *clientData); /* 79 */ void (*tcl_CancelIdleCall) (Tcl_IdleProc *idleProc, void *clientData); /* 80 */ - void (*reserved81)(void); + int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */ int (*tcl_CommandComplete) (const char *cmd); /* 82 */ - char * (*tcl_Concat) (int argc, const char *const *argv); /* 83 */ - size_t (*tcl_ConvertElement) (const char *src, char *dst, int flags); /* 84 */ - size_t (*tcl_ConvertCountedElement) (const char *src, size_t length, char *dst, int flags); /* 85 */ - int (*tcl_CreateAlias) (Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, const char *targetCmd, int argc, const char *const *argv); /* 86 */ - int (*tcl_CreateAliasObj) (Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, const char *targetCmd, int objc, Tcl_Obj *const objv[]); /* 87 */ + char * (*tcl_Concat) (Tcl_Size argc, const char *const *argv); /* 83 */ + Tcl_Size (*tcl_ConvertElement) (const char *src, char *dst, int flags); /* 84 */ + Tcl_Size (*tcl_ConvertCountedElement) (const char *src, Tcl_Size length, char *dst, int flags); /* 85 */ + int (*tcl_CreateAlias) (Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, const char *targetCmd, Tcl_Size argc, const char *const *argv); /* 86 */ + int (*tcl_CreateAliasObj) (Tcl_Interp *childInterp, const char *childCmd, Tcl_Interp *target, const char *targetCmd, Tcl_Size objc, Tcl_Obj *const objv[]); /* 87 */ Tcl_Channel (*tcl_CreateChannel) (const Tcl_ChannelType *typePtr, const char *chanName, void *instanceData, int mask); /* 88 */ void (*tcl_CreateChannelHandler) (Tcl_Channel chan, int mask, Tcl_ChannelProc *proc, void *clientData); /* 89 */ void (*tcl_CreateCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, void *clientData); /* 90 */ Tcl_Command (*tcl_CreateCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_CmdProc *proc, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 91 */ void (*tcl_CreateEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, void *clientData); /* 92 */ @@ -1875,11 +1974,11 @@ Tcl_Interp * (*tcl_CreateInterp) (void); /* 94 */ void (*reserved95)(void); Tcl_Command (*tcl_CreateObjCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 96 */ Tcl_Interp * (*tcl_CreateChild) (Tcl_Interp *interp, const char *name, int isSafe); /* 97 */ Tcl_TimerToken (*tcl_CreateTimerHandler) (int milliseconds, Tcl_TimerProc *proc, void *clientData); /* 98 */ - Tcl_Trace (*tcl_CreateTrace) (Tcl_Interp *interp, int level, Tcl_CmdTraceProc *proc, void *clientData); /* 99 */ + Tcl_Trace (*tcl_CreateTrace) (Tcl_Interp *interp, Tcl_Size level, Tcl_CmdTraceProc *proc, void *clientData); /* 99 */ void (*tcl_DeleteAssocData) (Tcl_Interp *interp, const char *name); /* 100 */ void (*tcl_DeleteChannelHandler) (Tcl_Channel chan, Tcl_ChannelProc *proc, void *clientData); /* 101 */ void (*tcl_DeleteCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, void *clientData); /* 102 */ int (*tcl_DeleteCommand) (Tcl_Interp *interp, const char *cmdName); /* 103 */ int (*tcl_DeleteCommandFromToken) (Tcl_Interp *interp, Tcl_Command command); /* 104 */ @@ -1887,24 +1986,24 @@ void (*tcl_DeleteEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, void *clientData); /* 106 */ void (*tcl_DeleteExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 107 */ void (*tcl_DeleteHashEntry) (Tcl_HashEntry *entryPtr); /* 108 */ void (*tcl_DeleteHashTable) (Tcl_HashTable *tablePtr); /* 109 */ void (*tcl_DeleteInterp) (Tcl_Interp *interp); /* 110 */ - void (*tcl_DetachPids) (int numPids, Tcl_Pid *pidPtr); /* 111 */ + void (*tcl_DetachPids) (Tcl_Size numPids, Tcl_Pid *pidPtr); /* 111 */ void (*tcl_DeleteTimerHandler) (Tcl_TimerToken token); /* 112 */ void (*tcl_DeleteTrace) (Tcl_Interp *interp, Tcl_Trace trace); /* 113 */ void (*tcl_DontCallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, void *clientData); /* 114 */ int (*tcl_DoOneEvent) (int flags); /* 115 */ void (*tcl_DoWhenIdle) (Tcl_IdleProc *proc, void *clientData); /* 116 */ - char * (*tcl_DStringAppend) (Tcl_DString *dsPtr, const char *bytes, size_t length); /* 117 */ + char * (*tcl_DStringAppend) (Tcl_DString *dsPtr, const char *bytes, Tcl_Size length); /* 117 */ char * (*tcl_DStringAppendElement) (Tcl_DString *dsPtr, const char *element); /* 118 */ void (*tcl_DStringEndSublist) (Tcl_DString *dsPtr); /* 119 */ void (*tcl_DStringFree) (Tcl_DString *dsPtr); /* 120 */ void (*tcl_DStringGetResult) (Tcl_Interp *interp, Tcl_DString *dsPtr); /* 121 */ void (*tcl_DStringInit) (Tcl_DString *dsPtr); /* 122 */ void (*tcl_DStringResult) (Tcl_Interp *interp, Tcl_DString *dsPtr); /* 123 */ - void (*tcl_DStringSetLength) (Tcl_DString *dsPtr, size_t length); /* 124 */ + void (*tcl_DStringSetLength) (Tcl_DString *dsPtr, Tcl_Size length); /* 124 */ void (*tcl_DStringStartSublist) (Tcl_DString *dsPtr); /* 125 */ int (*tcl_Eof) (Tcl_Channel chan); /* 126 */ const char * (*tcl_ErrnoId) (void); /* 127 */ const char * (*tcl_ErrnoMsg) (int err); /* 128 */ void (*reserved129)(void); @@ -1928,11 +2027,11 @@ 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 */ + 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 */ @@ -1943,22 +2042,14 @@ 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_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); @@ -1970,56 +2061,56 @@ void (*tcl_InitHashTable) (Tcl_HashTable *tablePtr, int keyType); /* 181 */ int (*tcl_InputBlocked) (Tcl_Channel chan); /* 182 */ int (*tcl_InputBuffered) (Tcl_Channel chan); /* 183 */ int (*tcl_InterpDeleted) (Tcl_Interp *interp); /* 184 */ int (*tcl_IsSafe) (Tcl_Interp *interp); /* 185 */ - char * (*tcl_JoinPath) (int argc, const char *const *argv, Tcl_DString *resultPtr); /* 186 */ + char * (*tcl_JoinPath) (Tcl_Size argc, const char *const *argv, Tcl_DString *resultPtr); /* 186 */ int (*tcl_LinkVar) (Tcl_Interp *interp, const char *varName, void *addr, int type); /* 187 */ void (*reserved188)(void); Tcl_Channel (*tcl_MakeFileChannel) (void *handle, int mode); /* 189 */ - int (*tcl_MakeSafe) (Tcl_Interp *interp); /* 190 */ + void (*reserved190)(void); Tcl_Channel (*tcl_MakeTcpClientChannel) (void *tcpSocket); /* 191 */ - char * (*tcl_Merge) (int argc, const char *const *argv); /* 192 */ + char * (*tcl_Merge) (Tcl_Size argc, const char *const *argv); /* 192 */ Tcl_HashEntry * (*tcl_NextHashEntry) (Tcl_HashSearch *searchPtr); /* 193 */ void (*tcl_NotifyChannel) (Tcl_Channel channel, int mask); /* 194 */ Tcl_Obj * (*tcl_ObjGetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 195 */ Tcl_Obj * (*tcl_ObjSetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 196 */ - Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, int argc, const char **argv, int flags); /* 197 */ + Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, Tcl_Size argc, const char **argv, int flags); /* 197 */ Tcl_Channel (*tcl_OpenFileChannel) (Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions); /* 198 */ - Tcl_Channel (*tcl_OpenTcpClient) (Tcl_Interp *interp, int port, const char *address, const char *myaddr, int myport, int async); /* 199 */ + Tcl_Channel (*tcl_OpenTcpClient) (Tcl_Interp *interp, int port, const char *address, const char *myaddr, int myport, int flags); /* 199 */ Tcl_Channel (*tcl_OpenTcpServer) (Tcl_Interp *interp, int port, const char *host, Tcl_TcpAcceptProc *acceptProc, void *callbackData); /* 200 */ void (*tcl_Preserve) (void *data); /* 201 */ void (*tcl_PrintDouble) (Tcl_Interp *interp, double value, char *dst); /* 202 */ int (*tcl_PutEnv) (const char *assignment); /* 203 */ const char * (*tcl_PosixError) (Tcl_Interp *interp); /* 204 */ - void (*tcl_QueueEvent) (Tcl_Event *evPtr, Tcl_QueuePosition position); /* 205 */ - size_t (*tcl_Read) (Tcl_Channel chan, char *bufPtr, size_t toRead); /* 206 */ + void (*tcl_QueueEvent) (Tcl_Event *evPtr, int position); /* 205 */ + Tcl_Size (*tcl_Read) (Tcl_Channel chan, char *bufPtr, Tcl_Size toRead); /* 206 */ void (*tcl_ReapDetachedProcs) (void); /* 207 */ int (*tcl_RecordAndEval) (Tcl_Interp *interp, const char *cmd, int flags); /* 208 */ int (*tcl_RecordAndEvalObj) (Tcl_Interp *interp, Tcl_Obj *cmdPtr, int flags); /* 209 */ void (*tcl_RegisterChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 210 */ void (*tcl_RegisterObjType) (const Tcl_ObjType *typePtr); /* 211 */ Tcl_RegExp (*tcl_RegExpCompile) (Tcl_Interp *interp, const char *pattern); /* 212 */ int (*tcl_RegExpExec) (Tcl_Interp *interp, Tcl_RegExp regexp, const char *text, const char *start); /* 213 */ int (*tcl_RegExpMatch) (Tcl_Interp *interp, const char *text, const char *pattern); /* 214 */ - void (*tcl_RegExpRange) (Tcl_RegExp regexp, size_t index, const char **startPtr, const char **endPtr); /* 215 */ + void (*tcl_RegExpRange) (Tcl_RegExp regexp, Tcl_Size index, const char **startPtr, const char **endPtr); /* 215 */ void (*tcl_Release) (void *clientData); /* 216 */ void (*tcl_ResetResult) (Tcl_Interp *interp); /* 217 */ - size_t (*tcl_ScanElement) (const char *src, int *flagPtr); /* 218 */ - size_t (*tcl_ScanCountedElement) (const char *src, size_t length, int *flagPtr); /* 219 */ + Tcl_Size (*tcl_ScanElement) (const char *src, int *flagPtr); /* 218 */ + Tcl_Size (*tcl_ScanCountedElement) (const char *src, Tcl_Size length, int *flagPtr); /* 219 */ void (*reserved220)(void); int (*tcl_ServiceAll) (void); /* 221 */ int (*tcl_ServiceEvent) (int flags); /* 222 */ void (*tcl_SetAssocData) (Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc *proc, void *clientData); /* 223 */ - void (*tcl_SetChannelBufferSize) (Tcl_Channel chan, int sz); /* 224 */ + void (*tcl_SetChannelBufferSize) (Tcl_Channel chan, Tcl_Size sz); /* 224 */ int (*tcl_SetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, const char *newValue); /* 225 */ int (*tcl_SetCommandInfo) (Tcl_Interp *interp, const char *cmdName, const Tcl_CmdInfo *infoPtr); /* 226 */ void (*tcl_SetErrno) (int err); /* 227 */ void (*tcl_SetErrorCode) (Tcl_Interp *interp, ...); /* 228 */ void (*tcl_SetMaxBlockTime) (const Tcl_Time *timePtr); /* 229 */ void (*reserved230)(void); - int (*tcl_SetRecursionLimit) (Tcl_Interp *interp, int depth); /* 231 */ + Tcl_Size (*tcl_SetRecursionLimit) (Tcl_Interp *interp, Tcl_Size depth); /* 231 */ void (*reserved232)(void); int (*tcl_SetServiceMode) (int mode); /* 233 */ void (*tcl_SetObjErrorCode) (Tcl_Interp *interp, Tcl_Obj *errorObjPtr); /* 234 */ void (*tcl_SetObjResult) (Tcl_Interp *interp, Tcl_Obj *resultObjPtr); /* 235 */ void (*tcl_SetStdChannel) (Tcl_Channel channel, int type); /* 236 */ @@ -2026,19 +2117,19 @@ void (*reserved237)(void); const char * (*tcl_SetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, const char *newValue, int flags); /* 238 */ const char * (*tcl_SignalId) (int sig); /* 239 */ const char * (*tcl_SignalMsg) (int sig); /* 240 */ void (*tcl_SourceRCFile) (Tcl_Interp *interp); /* 241 */ - int (*tcl_SplitList) (Tcl_Interp *interp, const char *listStr, int *argcPtr, const char ***argvPtr); /* 242 */ - void (*tcl_SplitPath) (const char *path, int *argcPtr, const char ***argvPtr); /* 243 */ + int (*tclSplitList) (Tcl_Interp *interp, const char *listStr, void *argcPtr, const char ***argvPtr); /* 242 */ + void (*tclSplitPath) (const char *path, void *argcPtr, const char ***argvPtr); /* 243 */ void (*reserved244)(void); void (*reserved245)(void); void (*reserved246)(void); void (*reserved247)(void); int (*tcl_TraceVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, void *clientData); /* 248 */ char * (*tcl_TranslateFileName) (Tcl_Interp *interp, const char *name, Tcl_DString *bufferPtr); /* 249 */ - size_t (*tcl_Ungets) (Tcl_Channel chan, const char *str, size_t len, int atHead); /* 250 */ + Tcl_Size (*tcl_Ungets) (Tcl_Channel chan, const char *str, Tcl_Size len, int atHead); /* 250 */ void (*tcl_UnlinkVar) (Tcl_Interp *interp, const char *varName); /* 251 */ int (*tcl_UnregisterChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 252 */ void (*reserved253)(void); int (*tcl_UnsetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 254 */ void (*reserved255)(void); @@ -2047,12 +2138,12 @@ void (*reserved258)(void); int (*tcl_UpVar2) (Tcl_Interp *interp, const char *frameName, const char *part1, const char *part2, const char *localName, int flags); /* 259 */ int (*tcl_VarEval) (Tcl_Interp *interp, ...); /* 260 */ void (*reserved261)(void); void * (*tcl_VarTraceInfo2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *procPtr, void *prevClientData); /* 262 */ - size_t (*tcl_Write) (Tcl_Channel chan, const char *s, size_t slen); /* 263 */ - void (*tcl_WrongNumArgs) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *message); /* 264 */ + Tcl_Size (*tcl_Write) (Tcl_Channel chan, const char *s, Tcl_Size slen); /* 263 */ + void (*tcl_WrongNumArgs) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], const char *message); /* 264 */ int (*tcl_DumpActiveMemory) (const char *fileName); /* 265 */ void (*tcl_ValidateAllMemory) (const char *file, int line); /* 266 */ void (*reserved267)(void); void (*reserved268)(void); char * (*tcl_HashStats) (Tcl_HashTable *tablePtr); /* 269 */ @@ -2075,59 +2166,59 @@ void (*tcl_AppendObjToObj) (Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr); /* 286 */ Tcl_Encoding (*tcl_CreateEncoding) (const Tcl_EncodingType *typePtr); /* 287 */ void (*tcl_CreateThreadExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 288 */ void (*tcl_DeleteThreadExitHandler) (Tcl_ExitProc *proc, void *clientData); /* 289 */ void (*reserved290)(void); - int (*tcl_EvalEx) (Tcl_Interp *interp, const char *script, size_t numBytes, int flags); /* 291 */ - int (*tcl_EvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 292 */ + int (*tcl_EvalEx) (Tcl_Interp *interp, const char *script, Tcl_Size numBytes, int flags); /* 291 */ + int (*tcl_EvalObjv) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 292 */ int (*tcl_EvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 293 */ TCL_NORETURN1 void (*tcl_ExitThread) (int status); /* 294 */ - int (*tcl_ExternalToUtf) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, size_t srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, size_t dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 295 */ - char * (*tcl_ExternalToUtfDString) (Tcl_Encoding encoding, const char *src, size_t srcLen, Tcl_DString *dsPtr); /* 296 */ + int (*tcl_ExternalToUtf) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 295 */ + char * (*tcl_ExternalToUtfDString) (Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr); /* 296 */ void (*tcl_FinalizeThread) (void); /* 297 */ void (*tcl_FinalizeNotifier) (void *clientData); /* 298 */ void (*tcl_FreeEncoding) (Tcl_Encoding encoding); /* 299 */ Tcl_ThreadId (*tcl_GetCurrentThread) (void); /* 300 */ Tcl_Encoding (*tcl_GetEncoding) (Tcl_Interp *interp, const char *name); /* 301 */ const char * (*tcl_GetEncodingName) (Tcl_Encoding encoding); /* 302 */ void (*tcl_GetEncodingNames) (Tcl_Interp *interp); /* 303 */ - int (*tcl_GetIndexFromObjStruct) (Tcl_Interp *interp, Tcl_Obj *objPtr, const void *tablePtr, size_t offset, const char *msg, int flags, int *indexPtr); /* 304 */ - void * (*tcl_GetThreadData) (Tcl_ThreadDataKey *keyPtr, size_t size); /* 305 */ + int (*tcl_GetIndexFromObjStruct) (Tcl_Interp *interp, Tcl_Obj *objPtr, const void *tablePtr, Tcl_Size offset, const char *msg, int flags, void *indexPtr); /* 304 */ + void * (*tcl_GetThreadData) (Tcl_ThreadDataKey *keyPtr, Tcl_Size size); /* 305 */ Tcl_Obj * (*tcl_GetVar2Ex) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 306 */ void * (*tcl_InitNotifier) (void); /* 307 */ void (*tcl_MutexLock) (Tcl_Mutex *mutexPtr); /* 308 */ void (*tcl_MutexUnlock) (Tcl_Mutex *mutexPtr); /* 309 */ void (*tcl_ConditionNotify) (Tcl_Condition *condPtr); /* 310 */ void (*tcl_ConditionWait) (Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr, const Tcl_Time *timePtr); /* 311 */ - size_t (*tcl_NumUtfChars) (const char *src, size_t length); /* 312 */ - size_t (*tcl_ReadChars) (Tcl_Channel channel, Tcl_Obj *objPtr, size_t charsToRead, int appendFlag); /* 313 */ + Tcl_Size (*tclNumUtfChars) (const char *src, Tcl_Size length); /* 312 */ + Tcl_Size (*tcl_ReadChars) (Tcl_Channel channel, Tcl_Obj *objPtr, Tcl_Size charsToRead, int appendFlag); /* 313 */ void (*reserved314)(void); void (*reserved315)(void); int (*tcl_SetSystemEncoding) (Tcl_Interp *interp, const char *name); /* 316 */ Tcl_Obj * (*tcl_SetVar2Ex) (Tcl_Interp *interp, const char *part1, const char *part2, Tcl_Obj *newValuePtr, int flags); /* 317 */ void (*tcl_ThreadAlert) (Tcl_ThreadId threadId); /* 318 */ - void (*tcl_ThreadQueueEvent) (Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 319 */ - int (*tcl_UniCharAtIndex) (const char *src, size_t index); /* 320 */ + void (*tcl_ThreadQueueEvent) (Tcl_ThreadId threadId, Tcl_Event *evPtr, int position); /* 319 */ + int (*tcl_UniCharAtIndex) (const char *src, Tcl_Size index); /* 320 */ int (*tcl_UniCharToLower) (int ch); /* 321 */ int (*tcl_UniCharToTitle) (int ch); /* 322 */ int (*tcl_UniCharToUpper) (int ch); /* 323 */ - int (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */ - const char * (*tcl_UtfAtIndex) (const char *src, size_t index); /* 325 */ - int (*tcl_UtfCharComplete) (const char *src, size_t length); /* 326 */ - size_t (*tcl_UtfBackslash) (const char *src, int *readPtr, char *dst); /* 327 */ + Tcl_Size (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */ + const char * (*tclUtfAtIndex) (const char *src, Tcl_Size index); /* 325 */ + int (*tclUtfCharComplete) (const char *src, Tcl_Size length); /* 326 */ + Tcl_Size (*tcl_UtfBackslash) (const char *src, int *readPtr, char *dst); /* 327 */ const char * (*tcl_UtfFindFirst) (const char *src, int ch); /* 328 */ const char * (*tcl_UtfFindLast) (const char *src, int ch); /* 329 */ - const char * (*tcl_UtfNext) (const char *src); /* 330 */ - const char * (*tcl_UtfPrev) (const char *src, const char *start); /* 331 */ - int (*tcl_UtfToExternal) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, size_t srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, size_t dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 332 */ - char * (*tcl_UtfToExternalDString) (Tcl_Encoding encoding, const char *src, size_t srcLen, Tcl_DString *dsPtr); /* 333 */ - int (*tcl_UtfToLower) (char *src); /* 334 */ - int (*tcl_UtfToTitle) (char *src); /* 335 */ - int (*tcl_UtfToChar16) (const char *src, unsigned short *chPtr); /* 336 */ - int (*tcl_UtfToUpper) (char *src); /* 337 */ - size_t (*tcl_WriteChars) (Tcl_Channel chan, const char *src, size_t srcLen); /* 338 */ - size_t (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */ + const char * (*tclUtfNext) (const char *src); /* 330 */ + const char * (*tclUtfPrev) (const char *src, const char *start); /* 331 */ + int (*tcl_UtfToExternal) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, Tcl_Size dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 332 */ + char * (*tcl_UtfToExternalDString) (Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr); /* 333 */ + Tcl_Size (*tcl_UtfToLower) (char *src); /* 334 */ + Tcl_Size (*tcl_UtfToTitle) (char *src); /* 335 */ + Tcl_Size (*tcl_UtfToChar16) (const char *src, unsigned short *chPtr); /* 336 */ + Tcl_Size (*tcl_UtfToUpper) (char *src); /* 337 */ + Tcl_Size (*tcl_WriteChars) (Tcl_Channel chan, const char *src, Tcl_Size srcLen); /* 338 */ + Tcl_Size (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */ char * (*tcl_GetString) (Tcl_Obj *objPtr); /* 340 */ void (*reserved341)(void); void (*reserved342)(void); void (*tcl_AlertNotifier) (void *clientData); /* 343 */ void (*tcl_ServiceModeHook) (int mode); /* 344 */ @@ -2136,23 +2227,23 @@ int (*tcl_UniCharIsDigit) (int ch); /* 347 */ int (*tcl_UniCharIsLower) (int ch); /* 348 */ int (*tcl_UniCharIsSpace) (int ch); /* 349 */ int (*tcl_UniCharIsUpper) (int ch); /* 350 */ int (*tcl_UniCharIsWordChar) (int ch); /* 351 */ - void (*reserved352)(void); + Tcl_Size (*tcl_Char16Len) (const unsigned short *uniStr); /* 352 */ void (*reserved353)(void); - char * (*tcl_Char16ToUtfDString) (const unsigned short *uniStr, size_t uniLength, Tcl_DString *dsPtr); /* 354 */ - unsigned short * (*tcl_UtfToChar16DString) (const char *src, size_t length, Tcl_DString *dsPtr); /* 355 */ + char * (*tcl_Char16ToUtfDString) (const unsigned short *uniStr, Tcl_Size uniLength, Tcl_DString *dsPtr); /* 354 */ + unsigned short * (*tcl_UtfToChar16DString) (const char *src, Tcl_Size length, Tcl_DString *dsPtr); /* 355 */ Tcl_RegExp (*tcl_GetRegExpFromObj) (Tcl_Interp *interp, Tcl_Obj *patObj, int flags); /* 356 */ void (*reserved357)(void); void (*tcl_FreeParse) (Tcl_Parse *parsePtr); /* 358 */ - void (*tcl_LogCommandInfo) (Tcl_Interp *interp, const char *script, const char *command, size_t length); /* 359 */ - int (*tcl_ParseBraces) (Tcl_Interp *interp, const char *start, size_t numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 360 */ - int (*tcl_ParseCommand) (Tcl_Interp *interp, const char *start, size_t numBytes, int nested, Tcl_Parse *parsePtr); /* 361 */ - int (*tcl_ParseExpr) (Tcl_Interp *interp, const char *start, size_t numBytes, Tcl_Parse *parsePtr); /* 362 */ - int (*tcl_ParseQuotedString) (Tcl_Interp *interp, const char *start, size_t numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 363 */ - int (*tcl_ParseVarName) (Tcl_Interp *interp, const char *start, size_t numBytes, Tcl_Parse *parsePtr, int append); /* 364 */ + void (*tcl_LogCommandInfo) (Tcl_Interp *interp, const char *script, const char *command, Tcl_Size length); /* 359 */ + int (*tcl_ParseBraces) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 360 */ + int (*tcl_ParseCommand) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, int nested, Tcl_Parse *parsePtr); /* 361 */ + int (*tcl_ParseExpr) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr); /* 362 */ + int (*tcl_ParseQuotedString) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr, int append, const char **termPtr); /* 363 */ + int (*tcl_ParseVarName) (Tcl_Interp *interp, const char *start, Tcl_Size numBytes, Tcl_Parse *parsePtr, int append); /* 364 */ char * (*tcl_GetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 365 */ int (*tcl_Chdir) (const char *dirName); /* 366 */ int (*tcl_Access) (const char *path, int mode); /* 367 */ int (*tcl_Stat) (const char *path, struct stat *bufPtr); /* 368 */ int (*tcl_UtfNcmp) (const char *s1, const char *s2, size_t n); /* 369 */ @@ -2160,30 +2251,30 @@ int (*tcl_StringCaseMatch) (const char *str, const char *pattern, int nocase); /* 371 */ int (*tcl_UniCharIsControl) (int ch); /* 372 */ int (*tcl_UniCharIsGraph) (int ch); /* 373 */ int (*tcl_UniCharIsPrint) (int ch); /* 374 */ int (*tcl_UniCharIsPunct) (int ch); /* 375 */ - int (*tcl_RegExpExecObj) (Tcl_Interp *interp, Tcl_RegExp regexp, Tcl_Obj *textObj, size_t offset, size_t nmatches, int flags); /* 376 */ + int (*tcl_RegExpExecObj) (Tcl_Interp *interp, Tcl_RegExp regexp, Tcl_Obj *textObj, Tcl_Size offset, Tcl_Size nmatches, int flags); /* 376 */ void (*tcl_RegExpGetInfo) (Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr); /* 377 */ - Tcl_Obj * (*tcl_NewUnicodeObj) (const Tcl_UniChar *unicode, size_t numChars); /* 378 */ - void (*tcl_SetUnicodeObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, size_t numChars); /* 379 */ - size_t (*tcl_GetCharLength) (Tcl_Obj *objPtr); /* 380 */ - int (*tcl_GetUniChar) (Tcl_Obj *objPtr, size_t index); /* 381 */ + Tcl_Obj * (*tcl_NewUnicodeObj) (const Tcl_UniChar *unicode, Tcl_Size numChars); /* 378 */ + void (*tcl_SetUnicodeObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, Tcl_Size numChars); /* 379 */ + Tcl_Size (*tclGetCharLength) (Tcl_Obj *objPtr); /* 380 */ + int (*tclGetUniChar) (Tcl_Obj *objPtr, Tcl_Size index); /* 381 */ void (*reserved382)(void); - Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, size_t first, size_t last); /* 383 */ - void (*reserved384)(void); + Tcl_Obj * (*tclGetRange) (Tcl_Obj *objPtr, Tcl_Size first, Tcl_Size last); /* 383 */ + void (*tcl_AppendUnicodeToObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, Tcl_Size length); /* 384 */ int (*tcl_RegExpMatchObj) (Tcl_Interp *interp, Tcl_Obj *textObj, Tcl_Obj *patternObj); /* 385 */ - void (*tcl_SetNotifier) (Tcl_NotifierProcs *notifierProcPtr); /* 386 */ + void (*tcl_SetNotifier) (const Tcl_NotifierProcs *notifierProcPtr); /* 386 */ Tcl_Mutex * (*tcl_GetAllocMutex) (void); /* 387 */ int (*tcl_GetChannelNames) (Tcl_Interp *interp); /* 388 */ int (*tcl_GetChannelNamesEx) (Tcl_Interp *interp, const char *pattern); /* 389 */ - int (*tcl_ProcObjCmd) (void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 390 */ + int (*tcl_ProcObjCmd) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); /* 390 */ void (*tcl_ConditionFinalize) (Tcl_Condition *condPtr); /* 391 */ void (*tcl_MutexFinalize) (Tcl_Mutex *mutex); /* 392 */ - int (*tcl_CreateThread) (Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, size_t stackSize, int flags); /* 393 */ - size_t (*tcl_ReadRaw) (Tcl_Channel chan, char *dst, size_t bytesToRead); /* 394 */ - size_t (*tcl_WriteRaw) (Tcl_Channel chan, const char *src, size_t srcLen); /* 395 */ + int (*tcl_CreateThread) (Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, TCL_HASH_TYPE stackSize, int flags); /* 393 */ + Tcl_Size (*tcl_ReadRaw) (Tcl_Channel chan, char *dst, Tcl_Size bytesToRead); /* 394 */ + Tcl_Size (*tcl_WriteRaw) (Tcl_Channel chan, const char *src, Tcl_Size srcLen); /* 395 */ Tcl_Channel (*tcl_GetTopChannel) (Tcl_Channel chan); /* 396 */ int (*tcl_ChannelBuffered) (Tcl_Channel chan); /* 397 */ const char * (*tcl_ChannelName) (const Tcl_ChannelType *chanTypePtr); /* 398 */ Tcl_ChannelTypeVersion (*tcl_ChannelVersion) (const Tcl_ChannelType *chanTypePtr); /* 399 */ Tcl_DriverBlockModeProc * (*tcl_ChannelBlockModeProc) (const Tcl_ChannelType *chanTypePtr); /* 400 */ @@ -2212,27 +2303,27 @@ void (*tcl_InitCustomHashTable) (Tcl_HashTable *tablePtr, int keyType, const Tcl_HashKeyType *typePtr); /* 423 */ void (*tcl_InitObjHashTable) (Tcl_HashTable *tablePtr); /* 424 */ void * (*tcl_CommandTraceInfo) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *procPtr, void *prevClientData); /* 425 */ int (*tcl_TraceCommand) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, void *clientData); /* 426 */ void (*tcl_UntraceCommand) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, void *clientData); /* 427 */ - void * (*tcl_AttemptAlloc) (size_t size); /* 428 */ - void * (*tcl_AttemptDbCkalloc) (size_t size, const char *file, int line); /* 429 */ - void * (*tcl_AttemptRealloc) (void *ptr, size_t size); /* 430 */ - void * (*tcl_AttemptDbCkrealloc) (void *ptr, size_t size, const char *file, int line); /* 431 */ - int (*tcl_AttemptSetObjLength) (Tcl_Obj *objPtr, size_t length); /* 432 */ + void * (*tcl_AttemptAlloc) (TCL_HASH_TYPE size); /* 428 */ + void * (*tcl_AttemptDbCkalloc) (TCL_HASH_TYPE size, const char *file, int line); /* 429 */ + void * (*tcl_AttemptRealloc) (void *ptr, TCL_HASH_TYPE size); /* 430 */ + void * (*tcl_AttemptDbCkrealloc) (void *ptr, TCL_HASH_TYPE size, const char *file, int line); /* 431 */ + int (*tcl_AttemptSetObjLength) (Tcl_Obj *objPtr, Tcl_Size length); /* 432 */ Tcl_ThreadId (*tcl_GetChannelThread) (Tcl_Channel channel); /* 433 */ - Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 434 */ + Tcl_UniChar * (*tclGetUnicodeFromObj) (Tcl_Obj *objPtr, void *lengthPtr); /* 434 */ void (*reserved435)(void); void (*reserved436)(void); Tcl_Obj * (*tcl_SubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 437 */ int (*tcl_DetachChannel) (Tcl_Interp *interp, Tcl_Channel channel); /* 438 */ int (*tcl_IsStandardChannel) (Tcl_Channel channel); /* 439 */ int (*tcl_FSCopyFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 440 */ int (*tcl_FSCopyDirectory) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr); /* 441 */ int (*tcl_FSCreateDirectory) (Tcl_Obj *pathPtr); /* 442 */ int (*tcl_FSDeleteFile) (Tcl_Obj *pathPtr); /* 443 */ - int (*tcl_FSLoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, const char *sym2, Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 444 */ + int (*tcl_FSLoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, const char *sym2, Tcl_LibraryInitProc **proc1Ptr, Tcl_LibraryInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 444 */ int (*tcl_FSMatchInDirectory) (Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); /* 445 */ Tcl_Obj * (*tcl_FSLink) (Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkAction); /* 446 */ int (*tcl_FSRemoveDirectory) (Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr); /* 447 */ int (*tcl_FSRenameFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 448 */ int (*tcl_FSLstat) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 449 */ @@ -2244,15 +2335,15 @@ int (*tcl_FSAccess) (Tcl_Obj *pathPtr, int mode); /* 455 */ Tcl_Channel (*tcl_FSOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *modeString, int permissions); /* 456 */ Tcl_Obj * (*tcl_FSGetCwd) (Tcl_Interp *interp); /* 457 */ int (*tcl_FSChdir) (Tcl_Obj *pathPtr); /* 458 */ int (*tcl_FSConvertToPathType) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 459 */ - Tcl_Obj * (*tcl_FSJoinPath) (Tcl_Obj *listObj, int elements); /* 460 */ - Tcl_Obj * (*tcl_FSSplitPath) (Tcl_Obj *pathPtr, int *lenPtr); /* 461 */ + Tcl_Obj * (*tcl_FSJoinPath) (Tcl_Obj *listObj, Tcl_Size elements); /* 460 */ + Tcl_Obj * (*tclFSSplitPath) (Tcl_Obj *pathPtr, void *lenPtr); /* 461 */ int (*tcl_FSEqualPaths) (Tcl_Obj *firstPtr, Tcl_Obj *secondPtr); /* 462 */ Tcl_Obj * (*tcl_FSGetNormalizedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 463 */ - Tcl_Obj * (*tcl_FSJoinToPath) (Tcl_Obj *pathPtr, int objc, Tcl_Obj *const objv[]); /* 464 */ + Tcl_Obj * (*tcl_FSJoinToPath) (Tcl_Obj *pathPtr, Tcl_Size objc, Tcl_Obj *const objv[]); /* 464 */ void * (*tcl_FSGetInternalRep) (Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr); /* 465 */ Tcl_Obj * (*tcl_FSGetTranslatedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 466 */ int (*tcl_FSEvalFile) (Tcl_Interp *interp, Tcl_Obj *fileName); /* 467 */ Tcl_Obj * (*tcl_FSNewNativePath) (const Tcl_Filesystem *fromFilesystem, void *clientData); /* 468 */ const void * (*tcl_FSGetNativePath) (Tcl_Obj *pathPtr); /* 469 */ @@ -2265,32 +2356,32 @@ const char * (*tcl_FSGetTranslatedStringPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 476 */ const Tcl_Filesystem * (*tcl_FSGetFileSystemForPath) (Tcl_Obj *pathPtr); /* 477 */ Tcl_PathType (*tcl_FSGetPathType) (Tcl_Obj *pathPtr); /* 478 */ int (*tcl_OutputBuffered) (Tcl_Channel chan); /* 479 */ void (*tcl_FSMountsChanged) (const Tcl_Filesystem *fsPtr); /* 480 */ - int (*tcl_EvalTokensStandard) (Tcl_Interp *interp, Tcl_Token *tokenPtr, size_t count); /* 481 */ + int (*tcl_EvalTokensStandard) (Tcl_Interp *interp, Tcl_Token *tokenPtr, Tcl_Size count); /* 481 */ void (*tcl_GetTime) (Tcl_Time *timeBuf); /* 482 */ - Tcl_Trace (*tcl_CreateObjTrace) (Tcl_Interp *interp, int level, int flags, Tcl_CmdObjTraceProc *objProc, void *clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 483 */ + Tcl_Trace (*tcl_CreateObjTrace) (Tcl_Interp *interp, Tcl_Size level, int flags, Tcl_CmdObjTraceProc *objProc, void *clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 483 */ int (*tcl_GetCommandInfoFromToken) (Tcl_Command token, Tcl_CmdInfo *infoPtr); /* 484 */ int (*tcl_SetCommandInfoFromToken) (Tcl_Command token, const Tcl_CmdInfo *infoPtr); /* 485 */ Tcl_Obj * (*tcl_DbNewWideIntObj) (Tcl_WideInt wideValue, const char *file, int line); /* 486 */ int (*tcl_GetWideIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideInt *widePtr); /* 487 */ Tcl_Obj * (*tcl_NewWideIntObj) (Tcl_WideInt wideValue); /* 488 */ void (*tcl_SetWideIntObj) (Tcl_Obj *objPtr, Tcl_WideInt wideValue); /* 489 */ Tcl_StatBuf * (*tcl_AllocStatBuf) (void); /* 490 */ - Tcl_WideInt (*tcl_Seek) (Tcl_Channel chan, Tcl_WideInt offset, int mode); /* 491 */ - Tcl_WideInt (*tcl_Tell) (Tcl_Channel chan); /* 492 */ + long long (*tcl_Seek) (Tcl_Channel chan, long long offset, int mode); /* 491 */ + long long (*tcl_Tell) (Tcl_Channel chan); /* 492 */ Tcl_DriverWideSeekProc * (*tcl_ChannelWideSeekProc) (const Tcl_ChannelType *chanTypePtr); /* 493 */ int (*tcl_DictObjPut) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj *valuePtr); /* 494 */ int (*tcl_DictObjGet) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr); /* 495 */ int (*tcl_DictObjRemove) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr); /* 496 */ - int (*tcl_DictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr); /* 497 */ + int (*tclDictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, void *sizePtr); /* 497 */ int (*tcl_DictObjFirst) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 498 */ void (*tcl_DictObjNext) (Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 499 */ void (*tcl_DictObjDone) (Tcl_DictSearch *searchPtr); /* 500 */ - int (*tcl_DictObjPutKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr); /* 501 */ - int (*tcl_DictObjRemoveKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv); /* 502 */ + int (*tcl_DictObjPutKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Size keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr); /* 501 */ + int (*tcl_DictObjRemoveKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Size keyc, Tcl_Obj *const *keyv); /* 502 */ Tcl_Obj * (*tcl_NewDictObj) (void); /* 503 */ Tcl_Obj * (*tcl_DbNewDictObj) (const char *file, int line); /* 504 */ void (*tcl_RegisterConfig) (Tcl_Interp *interp, const char *pkgName, const Tcl_Config *configuration, const char *valEncoding); /* 505 */ Tcl_Namespace * (*tcl_CreateNamespace) (Tcl_Interp *interp, const char *name, void *clientData, Tcl_NamespaceDeleteProc *deleteProc); /* 506 */ void (*tcl_DeleteNamespace) (Tcl_Namespace *nsPtr); /* 507 */ @@ -2309,11 +2400,11 @@ void (*tcl_LimitAddHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, void *clientData, Tcl_LimitHandlerDeleteProc *deleteProc); /* 520 */ void (*tcl_LimitRemoveHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, void *clientData); /* 521 */ int (*tcl_LimitReady) (Tcl_Interp *interp); /* 522 */ int (*tcl_LimitCheck) (Tcl_Interp *interp); /* 523 */ int (*tcl_LimitExceeded) (Tcl_Interp *interp); /* 524 */ - void (*tcl_LimitSetCommands) (Tcl_Interp *interp, int commandLimit); /* 525 */ + void (*tcl_LimitSetCommands) (Tcl_Interp *interp, Tcl_Size commandLimit); /* 525 */ void (*tcl_LimitSetTime) (Tcl_Interp *interp, Tcl_Time *timeLimitPtr); /* 526 */ void (*tcl_LimitSetGranularity) (Tcl_Interp *interp, int type, int granularity); /* 527 */ int (*tcl_LimitTypeEnabled) (Tcl_Interp *interp, int type); /* 528 */ int (*tcl_LimitTypeExceeded) (Tcl_Interp *interp, int type); /* 529 */ void (*tcl_LimitTypeSet) (Tcl_Interp *interp, int type); /* 530 */ @@ -2344,11 +2435,11 @@ Tcl_Obj * (*tcl_NewBignumObj) (void *value); /* 555 */ Tcl_Obj * (*tcl_DbNewBignumObj) (void *value, const char *file, int line); /* 556 */ void (*tcl_SetBignumObj) (Tcl_Obj *obj, void *value); /* 557 */ int (*tcl_GetBignumFromObj) (Tcl_Interp *interp, Tcl_Obj *obj, void *value); /* 558 */ int (*tcl_TakeBignumFromObj) (Tcl_Interp *interp, Tcl_Obj *obj, void *value); /* 559 */ - int (*tcl_TruncateChannel) (Tcl_Channel chan, Tcl_WideInt length); /* 560 */ + int (*tcl_TruncateChannel) (Tcl_Channel chan, long long length); /* 560 */ Tcl_DriverTruncateProc * (*tcl_ChannelTruncateProc) (const Tcl_ChannelType *chanTypePtr); /* 561 */ void (*tcl_SetChannelErrorInterp) (Tcl_Interp *interp, Tcl_Obj *msg); /* 562 */ void (*tcl_GetChannelErrorInterp) (Tcl_Interp *interp, Tcl_Obj **msg); /* 563 */ void (*tcl_SetChannelError) (Tcl_Channel chan, Tcl_Obj *msg); /* 564 */ void (*tcl_GetChannelError) (Tcl_Channel chan, Tcl_Obj **msg); /* 565 */ @@ -2357,57 +2448,57 @@ int (*tcl_SetNamespaceUnknownHandler) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *handlerPtr); /* 568 */ int (*tcl_GetEncodingFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr); /* 569 */ Tcl_Obj * (*tcl_GetEncodingSearchPath) (void); /* 570 */ int (*tcl_SetEncodingSearchPath) (Tcl_Obj *searchPath); /* 571 */ const char * (*tcl_GetEncodingNameFromEnvironment) (Tcl_DString *bufPtr); /* 572 */ - int (*tcl_PkgRequireProc) (Tcl_Interp *interp, const char *name, int objc, Tcl_Obj *const objv[], void *clientDataPtr); /* 573 */ + int (*tcl_PkgRequireProc) (Tcl_Interp *interp, const char *name, Tcl_Size objc, Tcl_Obj *const objv[], void *clientDataPtr); /* 573 */ void (*tcl_AppendObjToErrorInfo) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 574 */ - void (*tcl_AppendLimitedToObj) (Tcl_Obj *objPtr, const char *bytes, size_t length, size_t limit, const char *ellipsis); /* 575 */ - Tcl_Obj * (*tcl_Format) (Tcl_Interp *interp, const char *format, int objc, Tcl_Obj *const objv[]); /* 576 */ - int (*tcl_AppendFormatToObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, const char *format, int objc, Tcl_Obj *const objv[]); /* 577 */ + void (*tcl_AppendLimitedToObj) (Tcl_Obj *objPtr, const char *bytes, Tcl_Size length, Tcl_Size limit, const char *ellipsis); /* 575 */ + Tcl_Obj * (*tcl_Format) (Tcl_Interp *interp, const char *format, Tcl_Size objc, Tcl_Obj *const objv[]); /* 576 */ + int (*tcl_AppendFormatToObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, const char *format, Tcl_Size objc, Tcl_Obj *const objv[]); /* 577 */ Tcl_Obj * (*tcl_ObjPrintf) (const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 578 */ void (*tcl_AppendPrintfToObj) (Tcl_Obj *objPtr, const char *format, ...) TCL_FORMAT_PRINTF(2, 3); /* 579 */ int (*tcl_CancelEval) (Tcl_Interp *interp, Tcl_Obj *resultObjPtr, void *clientData, int flags); /* 580 */ int (*tcl_Canceled) (Tcl_Interp *interp, int flags); /* 581 */ int (*tcl_CreatePipe) (Tcl_Interp *interp, Tcl_Channel *rchan, Tcl_Channel *wchan, int flags); /* 582 */ Tcl_Command (*tcl_NRCreateCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 583 */ int (*tcl_NREvalObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 584 */ - int (*tcl_NREvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 585 */ - int (*tcl_NRCmdSwap) (Tcl_Interp *interp, Tcl_Command cmd, int objc, Tcl_Obj *const objv[], int flags); /* 586 */ + int (*tcl_NREvalObjv) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 585 */ + int (*tcl_NRCmdSwap) (Tcl_Interp *interp, Tcl_Command cmd, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 586 */ void (*tcl_NRAddCallback) (Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, void *data0, void *data1, void *data2, void *data3); /* 587 */ - int (*tcl_NRCallObjProc) (Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, void *clientData, int objc, Tcl_Obj *const objv[]); /* 588 */ + int (*tcl_NRCallObjProc) (Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, void *clientData, Tcl_Size objc, Tcl_Obj *const objv[]); /* 588 */ unsigned (*tcl_GetFSDeviceFromStat) (const Tcl_StatBuf *statPtr); /* 589 */ unsigned (*tcl_GetFSInodeFromStat) (const Tcl_StatBuf *statPtr); /* 590 */ unsigned (*tcl_GetModeFromStat) (const Tcl_StatBuf *statPtr); /* 591 */ int (*tcl_GetLinkCountFromStat) (const Tcl_StatBuf *statPtr); /* 592 */ int (*tcl_GetUserIdFromStat) (const Tcl_StatBuf *statPtr); /* 593 */ int (*tcl_GetGroupIdFromStat) (const Tcl_StatBuf *statPtr); /* 594 */ int (*tcl_GetDeviceTypeFromStat) (const Tcl_StatBuf *statPtr); /* 595 */ - Tcl_WideInt (*tcl_GetAccessTimeFromStat) (const Tcl_StatBuf *statPtr); /* 596 */ - Tcl_WideInt (*tcl_GetModificationTimeFromStat) (const Tcl_StatBuf *statPtr); /* 597 */ - Tcl_WideInt (*tcl_GetChangeTimeFromStat) (const Tcl_StatBuf *statPtr); /* 598 */ - Tcl_WideUInt (*tcl_GetSizeFromStat) (const Tcl_StatBuf *statPtr); /* 599 */ - Tcl_WideUInt (*tcl_GetBlocksFromStat) (const Tcl_StatBuf *statPtr); /* 600 */ + long long (*tcl_GetAccessTimeFromStat) (const Tcl_StatBuf *statPtr); /* 596 */ + long long (*tcl_GetModificationTimeFromStat) (const Tcl_StatBuf *statPtr); /* 597 */ + long long (*tcl_GetChangeTimeFromStat) (const Tcl_StatBuf *statPtr); /* 598 */ + unsigned long long (*tcl_GetSizeFromStat) (const Tcl_StatBuf *statPtr); /* 599 */ + unsigned long long (*tcl_GetBlocksFromStat) (const Tcl_StatBuf *statPtr); /* 600 */ unsigned (*tcl_GetBlockSizeFromStat) (const Tcl_StatBuf *statPtr); /* 601 */ int (*tcl_SetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *paramList); /* 602 */ int (*tcl_GetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **paramListPtr); /* 603 */ - int (*tcl_ParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 604 */ + int (*tclParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, void *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 604 */ int (*tcl_GetErrorLine) (Tcl_Interp *interp); /* 605 */ void (*tcl_SetErrorLine) (Tcl_Interp *interp, int lineNum); /* 606 */ void (*tcl_TransferResult) (Tcl_Interp *sourceInterp, int code, Tcl_Interp *targetInterp); /* 607 */ int (*tcl_InterpActive) (Tcl_Interp *interp); /* 608 */ void (*tcl_BackgroundException) (Tcl_Interp *interp, int code); /* 609 */ int (*tcl_ZlibDeflate) (Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj); /* 610 */ - int (*tcl_ZlibInflate) (Tcl_Interp *interp, int format, Tcl_Obj *data, size_t buffersize, Tcl_Obj *gzipHeaderDictObj); /* 611 */ - unsigned int (*tcl_ZlibCRC32) (unsigned int crc, const unsigned char *buf, size_t len); /* 612 */ - unsigned int (*tcl_ZlibAdler32) (unsigned int adler, const unsigned char *buf, size_t len); /* 613 */ + int (*tcl_ZlibInflate) (Tcl_Interp *interp, int format, Tcl_Obj *data, Tcl_Size buffersize, Tcl_Obj *gzipHeaderDictObj); /* 611 */ + unsigned int (*tcl_ZlibCRC32) (unsigned int crc, const unsigned char *buf, Tcl_Size len); /* 612 */ + unsigned int (*tcl_ZlibAdler32) (unsigned int adler, const unsigned char *buf, Tcl_Size len); /* 613 */ int (*tcl_ZlibStreamInit) (Tcl_Interp *interp, int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle); /* 614 */ Tcl_Obj * (*tcl_ZlibStreamGetCommandName) (Tcl_ZlibStream zshandle); /* 615 */ int (*tcl_ZlibStreamEof) (Tcl_ZlibStream zshandle); /* 616 */ int (*tcl_ZlibStreamChecksum) (Tcl_ZlibStream zshandle); /* 617 */ int (*tcl_ZlibStreamPut) (Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush); /* 618 */ - int (*tcl_ZlibStreamGet) (Tcl_ZlibStream zshandle, Tcl_Obj *data, size_t count); /* 619 */ + int (*tcl_ZlibStreamGet) (Tcl_ZlibStream zshandle, Tcl_Obj *data, Tcl_Size count); /* 619 */ int (*tcl_ZlibStreamClose) (Tcl_ZlibStream zshandle); /* 620 */ int (*tcl_ZlibStreamReset) (Tcl_ZlibStream zshandle); /* 621 */ void (*tcl_SetStartupScript) (Tcl_Obj *path, const char *encoding); /* 622 */ Tcl_Obj * (*tcl_GetStartupScript) (const char **encodingPtr); /* 623 */ int (*tcl_CloseEx) (Tcl_Interp *interp, Tcl_Channel chan, int flags); /* 624 */ @@ -2415,28 +2506,68 @@ int (*tcl_NRSubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 626 */ int (*tcl_LoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *const symv[], int flags, void *procPtrs, Tcl_LoadHandle *handlePtr); /* 627 */ void * (*tcl_FindSymbol) (Tcl_Interp *interp, Tcl_LoadHandle handle, const char *symbol); /* 628 */ int (*tcl_FSUnloadFile) (Tcl_Interp *interp, Tcl_LoadHandle handlePtr); /* 629 */ void (*tcl_ZlibStreamSetCompressionDictionary) (Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); /* 630 */ - Tcl_Channel (*tcl_OpenTcpServerEx) (Tcl_Interp *interp, const char *service, const char *host, unsigned int flags, Tcl_TcpAcceptProc *acceptProc, void *callbackData); /* 631 */ - int (*tclZipfs_Mount) (Tcl_Interp *interp, const char *mountPoint, const char *zipname, const char *passwd); /* 632 */ + Tcl_Channel (*tcl_OpenTcpServerEx) (Tcl_Interp *interp, const char *service, const char *host, unsigned int flags, int backlog, Tcl_TcpAcceptProc *acceptProc, void *callbackData); /* 631 */ + int (*tclZipfs_Mount) (Tcl_Interp *interp, const char *zipname, const char *mountPoint, const char *passwd); /* 632 */ int (*tclZipfs_Unmount) (Tcl_Interp *interp, const char *mountPoint); /* 633 */ Tcl_Obj * (*tclZipfs_TclLibrary) (void); /* 634 */ - int (*tclZipfs_MountBuffer) (Tcl_Interp *interp, const char *mountPoint, unsigned char *data, size_t datalen, int copy); /* 635 */ - void (*tcl_FreeIntRep) (Tcl_Obj *objPtr); /* 636 */ - char * (*tcl_InitStringRep) (Tcl_Obj *objPtr, const char *bytes, size_t numBytes); /* 637 */ - Tcl_ObjIntRep * (*tcl_FetchIntRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 638 */ - void (*tcl_StoreIntRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, const Tcl_ObjIntRep *irPtr); /* 639 */ + int (*tclZipfs_MountBuffer) (Tcl_Interp *interp, const void *data, size_t datalen, const char *mountPoint, int copy); /* 635 */ + void (*tcl_FreeInternalRep) (Tcl_Obj *objPtr); /* 636 */ + char * (*tcl_InitStringRep) (Tcl_Obj *objPtr, const char *bytes, TCL_HASH_TYPE numBytes); /* 637 */ + Tcl_ObjInternalRep * (*tcl_FetchInternalRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 638 */ + void (*tcl_StoreInternalRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, const Tcl_ObjInternalRep *irPtr); /* 639 */ int (*tcl_HasStringRep) (Tcl_Obj *objPtr); /* 640 */ void (*tcl_IncrRefCount) (Tcl_Obj *objPtr); /* 641 */ void (*tcl_DecrRefCount) (Tcl_Obj *objPtr); /* 642 */ int (*tcl_IsShared) (Tcl_Obj *objPtr); /* 643 */ - int (*tcl_LinkArray) (Tcl_Interp *interp, const char *varName, void *addr, int type, size_t size); /* 644 */ - int (*tcl_GetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, size_t endValue, size_t *indexPtr); /* 645 */ - int (*tcl_UtfToUniChar) (const char *src, int *chPtr); /* 646 */ - char * (*tcl_UniCharToUtfDString) (const int *uniStr, size_t uniLength, Tcl_DString *dsPtr); /* 647 */ - int * (*tcl_UtfToUniCharDString) (const char *src, size_t length, Tcl_DString *dsPtr); /* 648 */ + int (*tcl_LinkArray) (Tcl_Interp *interp, const char *varName, void *addr, int type, Tcl_Size size); /* 644 */ + int (*tcl_GetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size endValue, Tcl_Size *indexPtr); /* 645 */ + Tcl_Size (*tcl_UtfToUniChar) (const char *src, int *chPtr); /* 646 */ + char * (*tcl_UniCharToUtfDString) (const int *uniStr, Tcl_Size uniLength, Tcl_DString *dsPtr); /* 647 */ + int * (*tcl_UtfToUniCharDString) (const char *src, Tcl_Size length, Tcl_DString *dsPtr); /* 648 */ + unsigned char * (*tclGetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, void *numBytesPtr); /* 649 */ + unsigned char * (*tcl_GetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size *numBytesPtr); /* 650 */ + char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 651 */ + Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, Tcl_Size *lengthPtr); /* 652 */ + int (*tcl_GetSizeIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size *sizePtr); /* 653 */ + int (*tcl_UtfCharComplete) (const char *src, Tcl_Size length); /* 654 */ + const char * (*tcl_UtfNext) (const char *src); /* 655 */ + const char * (*tcl_UtfPrev) (const char *src, const char *start); /* 656 */ + int (*tcl_UniCharIsUnicode) (int ch); /* 657 */ + int (*tcl_ExternalToUtfDStringEx) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, int flags, Tcl_DString *dsPtr, Tcl_Size *errorLocationPtr); /* 658 */ + int (*tcl_UtfToExternalDStringEx) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, Tcl_Size srcLen, int flags, Tcl_DString *dsPtr, Tcl_Size *errorLocationPtr); /* 659 */ + int (*tcl_AsyncMarkFromSignal) (Tcl_AsyncHandler async, int sigNumber); /* 660 */ + int (*tcl_ListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size *objcPtr, Tcl_Obj ***objvPtr); /* 661 */ + int (*tcl_ListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size *lengthPtr); /* 662 */ + int (*tcl_DictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Size *sizePtr); /* 663 */ + int (*tcl_SplitList) (Tcl_Interp *interp, const char *listStr, Tcl_Size *argcPtr, const char ***argvPtr); /* 664 */ + void (*tcl_SplitPath) (const char *path, Tcl_Size *argcPtr, const char ***argvPtr); /* 665 */ + Tcl_Obj * (*tcl_FSSplitPath) (Tcl_Obj *pathPtr, Tcl_Size *lenPtr); /* 666 */ + int (*tcl_ParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, Tcl_Size *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 667 */ + Tcl_Size (*tcl_UniCharLen) (const int *uniStr); /* 668 */ + Tcl_Size (*tcl_NumUtfChars) (const char *src, Tcl_Size length); /* 669 */ + Tcl_Size (*tcl_GetCharLength) (Tcl_Obj *objPtr); /* 670 */ + const char * (*tcl_UtfAtIndex) (const char *src, Tcl_Size index); /* 671 */ + Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, Tcl_Size first, Tcl_Size last); /* 672 */ + int (*tcl_GetUniChar) (Tcl_Obj *objPtr, Tcl_Size index); /* 673 */ + int (*tcl_GetBool) (Tcl_Interp *interp, const char *src, int flags, char *charPtr); /* 674 */ + int (*tcl_GetBoolFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, char *charPtr); /* 675 */ + Tcl_Command (*tcl_CreateObjCommand2) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc2 *proc2, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 676 */ + Tcl_Trace (*tcl_CreateObjTrace2) (Tcl_Interp *interp, Tcl_Size level, int flags, Tcl_CmdObjTraceProc2 *objProc2, void *clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 677 */ + Tcl_Command (*tcl_NRCreateCommand2) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc2 *proc, Tcl_ObjCmdProc2 *nreProc2, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 678 */ + int (*tcl_NRCallObjProc2) (Tcl_Interp *interp, Tcl_ObjCmdProc2 *objProc2, void *clientData, Tcl_Size objc, Tcl_Obj *const objv[]); /* 679 */ + int (*tcl_GetNumberFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, void **clientDataPtr, int *typePtr); /* 680 */ + int (*tcl_GetNumber) (Tcl_Interp *interp, const char *bytes, Tcl_Size numBytes, void **clientDataPtr, int *typePtr); /* 681 */ + int (*tcl_RemoveChannelMode) (Tcl_Interp *interp, Tcl_Channel chan, int mode); /* 682 */ + Tcl_Size (*tcl_GetEncodingNulLength) (Tcl_Encoding encoding); /* 683 */ + int (*tcl_GetWideUIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideUInt *uwidePtr); /* 684 */ + Tcl_Obj * (*tcl_DStringToObj) (Tcl_DString *dsPtr); /* 685 */ + void (*reserved686)(void); + void (*reserved687)(void); + void (*tclUnusedStubEntry) (void); /* 688 */ } TclStubs; extern const TclStubs *tclStubsPtr; #ifdef __cplusplus @@ -2465,26 +2596,14 @@ (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_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 \ @@ -2538,24 +2657,24 @@ (tclStubsPtr->tcl_GetIntFromObj) /* 38 */ #define Tcl_GetLongFromObj \ (tclStubsPtr->tcl_GetLongFromObj) /* 39 */ #define Tcl_GetObjType \ (tclStubsPtr->tcl_GetObjType) /* 40 */ -#define Tcl_GetStringFromObj \ - (tclStubsPtr->tcl_GetStringFromObj) /* 41 */ +#define TclGetStringFromObj \ + (tclStubsPtr->tclGetStringFromObj) /* 41 */ #define Tcl_InvalidateStringRep \ (tclStubsPtr->tcl_InvalidateStringRep) /* 42 */ #define Tcl_ListObjAppendList \ (tclStubsPtr->tcl_ListObjAppendList) /* 43 */ #define Tcl_ListObjAppendElement \ (tclStubsPtr->tcl_ListObjAppendElement) /* 44 */ -#define Tcl_ListObjGetElements \ - (tclStubsPtr->tcl_ListObjGetElements) /* 45 */ +#define TclListObjGetElements \ + (tclStubsPtr->tclListObjGetElements) /* 45 */ #define Tcl_ListObjIndex \ (tclStubsPtr->tcl_ListObjIndex) /* 46 */ -#define Tcl_ListObjLength \ - (tclStubsPtr->tcl_ListObjLength) /* 47 */ +#define TclListObjLength \ + (tclStubsPtr->tclListObjLength) /* 47 */ #define Tcl_ListObjReplace \ (tclStubsPtr->tcl_ListObjReplace) /* 48 */ /* Slot 49 is reserved */ #define Tcl_NewByteArrayObj \ (tclStubsPtr->tcl_NewByteArrayObj) /* 50 */ @@ -2608,11 +2727,12 @@ (tclStubsPtr->tcl_BadChannelOption) /* 78 */ #define Tcl_CallWhenDeleted \ (tclStubsPtr->tcl_CallWhenDeleted) /* 79 */ #define Tcl_CancelIdleCall \ (tclStubsPtr->tcl_CancelIdleCall) /* 80 */ -/* Slot 81 is reserved */ +#define Tcl_Close \ + (tclStubsPtr->tcl_Close) /* 81 */ #define Tcl_CommandComplete \ (tclStubsPtr->tcl_CommandComplete) /* 82 */ #define Tcl_Concat \ (tclStubsPtr->tcl_Concat) /* 83 */ #define Tcl_ConvertElement \ @@ -2774,18 +2894,12 @@ (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 \ @@ -2821,12 +2935,11 @@ #define Tcl_LinkVar \ (tclStubsPtr->tcl_LinkVar) /* 187 */ /* Slot 188 is reserved */ #define Tcl_MakeFileChannel \ (tclStubsPtr->tcl_MakeFileChannel) /* 189 */ -#define Tcl_MakeSafe \ - (tclStubsPtr->tcl_MakeSafe) /* 190 */ +/* Slot 190 is reserved */ #define Tcl_MakeTcpClientChannel \ (tclStubsPtr->tcl_MakeTcpClientChannel) /* 191 */ #define Tcl_Merge \ (tclStubsPtr->tcl_Merge) /* 192 */ #define Tcl_NextHashEntry \ @@ -2921,14 +3034,14 @@ (tclStubsPtr->tcl_SignalId) /* 239 */ #define Tcl_SignalMsg \ (tclStubsPtr->tcl_SignalMsg) /* 240 */ #define Tcl_SourceRCFile \ (tclStubsPtr->tcl_SourceRCFile) /* 241 */ -#define Tcl_SplitList \ - (tclStubsPtr->tcl_SplitList) /* 242 */ -#define Tcl_SplitPath \ - (tclStubsPtr->tcl_SplitPath) /* 243 */ +#define TclSplitList \ + (tclStubsPtr->tclSplitList) /* 242 */ +#define TclSplitPath \ + (tclStubsPtr->tclSplitPath) /* 243 */ /* Slot 244 is reserved */ /* Slot 245 is reserved */ /* Slot 246 is reserved */ /* Slot 247 is reserved */ #define Tcl_TraceVar2 \ @@ -3043,12 +3156,12 @@ (tclStubsPtr->tcl_MutexUnlock) /* 309 */ #define Tcl_ConditionNotify \ (tclStubsPtr->tcl_ConditionNotify) /* 310 */ #define Tcl_ConditionWait \ (tclStubsPtr->tcl_ConditionWait) /* 311 */ -#define Tcl_NumUtfChars \ - (tclStubsPtr->tcl_NumUtfChars) /* 312 */ +#define TclNumUtfChars \ + (tclStubsPtr->tclNumUtfChars) /* 312 */ #define Tcl_ReadChars \ (tclStubsPtr->tcl_ReadChars) /* 313 */ /* Slot 314 is reserved */ /* Slot 315 is reserved */ #define Tcl_SetSystemEncoding \ @@ -3067,24 +3180,24 @@ (tclStubsPtr->tcl_UniCharToTitle) /* 322 */ #define Tcl_UniCharToUpper \ (tclStubsPtr->tcl_UniCharToUpper) /* 323 */ #define Tcl_UniCharToUtf \ (tclStubsPtr->tcl_UniCharToUtf) /* 324 */ -#define Tcl_UtfAtIndex \ - (tclStubsPtr->tcl_UtfAtIndex) /* 325 */ -#define Tcl_UtfCharComplete \ - (tclStubsPtr->tcl_UtfCharComplete) /* 326 */ +#define TclUtfAtIndex \ + (tclStubsPtr->tclUtfAtIndex) /* 325 */ +#define TclUtfCharComplete \ + (tclStubsPtr->tclUtfCharComplete) /* 326 */ #define Tcl_UtfBackslash \ (tclStubsPtr->tcl_UtfBackslash) /* 327 */ #define Tcl_UtfFindFirst \ (tclStubsPtr->tcl_UtfFindFirst) /* 328 */ #define Tcl_UtfFindLast \ (tclStubsPtr->tcl_UtfFindLast) /* 329 */ -#define Tcl_UtfNext \ - (tclStubsPtr->tcl_UtfNext) /* 330 */ -#define Tcl_UtfPrev \ - (tclStubsPtr->tcl_UtfPrev) /* 331 */ +#define TclUtfNext \ + (tclStubsPtr->tclUtfNext) /* 330 */ +#define TclUtfPrev \ + (tclStubsPtr->tclUtfPrev) /* 331 */ #define Tcl_UtfToExternal \ (tclStubsPtr->tcl_UtfToExternal) /* 332 */ #define Tcl_UtfToExternalDString \ (tclStubsPtr->tcl_UtfToExternalDString) /* 333 */ #define Tcl_UtfToLower \ @@ -3119,11 +3232,12 @@ (tclStubsPtr->tcl_UniCharIsSpace) /* 349 */ #define Tcl_UniCharIsUpper \ (tclStubsPtr->tcl_UniCharIsUpper) /* 350 */ #define Tcl_UniCharIsWordChar \ (tclStubsPtr->tcl_UniCharIsWordChar) /* 351 */ -/* Slot 352 is reserved */ +#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 */ @@ -3172,18 +3286,19 @@ (tclStubsPtr->tcl_RegExpGetInfo) /* 377 */ #define Tcl_NewUnicodeObj \ (tclStubsPtr->tcl_NewUnicodeObj) /* 378 */ #define Tcl_SetUnicodeObj \ (tclStubsPtr->tcl_SetUnicodeObj) /* 379 */ -#define Tcl_GetCharLength \ - (tclStubsPtr->tcl_GetCharLength) /* 380 */ -#define Tcl_GetUniChar \ - (tclStubsPtr->tcl_GetUniChar) /* 381 */ +#define TclGetCharLength \ + (tclStubsPtr->tclGetCharLength) /* 380 */ +#define TclGetUniChar \ + (tclStubsPtr->tclGetUniChar) /* 381 */ /* Slot 382 is reserved */ -#define Tcl_GetRange \ - (tclStubsPtr->tcl_GetRange) /* 383 */ -/* Slot 384 is reserved */ +#define TclGetRange \ + (tclStubsPtr->tclGetRange) /* 383 */ +#define Tcl_AppendUnicodeToObj \ + (tclStubsPtr->tcl_AppendUnicodeToObj) /* 384 */ #define Tcl_RegExpMatchObj \ (tclStubsPtr->tcl_RegExpMatchObj) /* 385 */ #define Tcl_SetNotifier \ (tclStubsPtr->tcl_SetNotifier) /* 386 */ #define Tcl_GetAllocMutex \ @@ -3272,12 +3387,12 @@ (tclStubsPtr->tcl_AttemptDbCkrealloc) /* 431 */ #define Tcl_AttemptSetObjLength \ (tclStubsPtr->tcl_AttemptSetObjLength) /* 432 */ #define Tcl_GetChannelThread \ (tclStubsPtr->tcl_GetChannelThread) /* 433 */ -#define Tcl_GetUnicodeFromObj \ - (tclStubsPtr->tcl_GetUnicodeFromObj) /* 434 */ +#define TclGetUnicodeFromObj \ + (tclStubsPtr->tclGetUnicodeFromObj) /* 434 */ /* Slot 435 is reserved */ /* Slot 436 is reserved */ #define Tcl_SubstObj \ (tclStubsPtr->tcl_SubstObj) /* 437 */ #define Tcl_DetachChannel \ @@ -3324,12 +3439,12 @@ (tclStubsPtr->tcl_FSChdir) /* 458 */ #define Tcl_FSConvertToPathType \ (tclStubsPtr->tcl_FSConvertToPathType) /* 459 */ #define Tcl_FSJoinPath \ (tclStubsPtr->tcl_FSJoinPath) /* 460 */ -#define Tcl_FSSplitPath \ - (tclStubsPtr->tcl_FSSplitPath) /* 461 */ +#define TclFSSplitPath \ + (tclStubsPtr->tclFSSplitPath) /* 461 */ #define Tcl_FSEqualPaths \ (tclStubsPtr->tcl_FSEqualPaths) /* 462 */ #define Tcl_FSGetNormalizedPath \ (tclStubsPtr->tcl_FSGetNormalizedPath) /* 463 */ #define Tcl_FSJoinToPath \ @@ -3396,12 +3511,12 @@ (tclStubsPtr->tcl_DictObjPut) /* 494 */ #define Tcl_DictObjGet \ (tclStubsPtr->tcl_DictObjGet) /* 495 */ #define Tcl_DictObjRemove \ (tclStubsPtr->tcl_DictObjRemove) /* 496 */ -#define Tcl_DictObjSize \ - (tclStubsPtr->tcl_DictObjSize) /* 497 */ +#define TclDictObjSize \ + (tclStubsPtr->tclDictObjSize) /* 497 */ #define Tcl_DictObjFirst \ (tclStubsPtr->tcl_DictObjFirst) /* 498 */ #define Tcl_DictObjNext \ (tclStubsPtr->tcl_DictObjNext) /* 499 */ #define Tcl_DictObjDone \ @@ -3609,12 +3724,12 @@ (tclStubsPtr->tcl_GetBlockSizeFromStat) /* 601 */ #define Tcl_SetEnsembleParameterList \ (tclStubsPtr->tcl_SetEnsembleParameterList) /* 602 */ #define Tcl_GetEnsembleParameterList \ (tclStubsPtr->tcl_GetEnsembleParameterList) /* 603 */ -#define Tcl_ParseArgsObjv \ - (tclStubsPtr->tcl_ParseArgsObjv) /* 604 */ +#define TclParseArgsObjv \ + (tclStubsPtr->tclParseArgsObjv) /* 604 */ #define Tcl_GetErrorLine \ (tclStubsPtr->tcl_GetErrorLine) /* 605 */ #define Tcl_SetErrorLine \ (tclStubsPtr->tcl_SetErrorLine) /* 606 */ #define Tcl_TransferResult \ @@ -3673,18 +3788,18 @@ (tclStubsPtr->tclZipfs_Unmount) /* 633 */ #define TclZipfs_TclLibrary \ (tclStubsPtr->tclZipfs_TclLibrary) /* 634 */ #define TclZipfs_MountBuffer \ (tclStubsPtr->tclZipfs_MountBuffer) /* 635 */ -#define Tcl_FreeIntRep \ - (tclStubsPtr->tcl_FreeIntRep) /* 636 */ +#define Tcl_FreeInternalRep \ + (tclStubsPtr->tcl_FreeInternalRep) /* 636 */ #define Tcl_InitStringRep \ (tclStubsPtr->tcl_InitStringRep) /* 637 */ -#define Tcl_FetchIntRep \ - (tclStubsPtr->tcl_FetchIntRep) /* 638 */ -#define Tcl_StoreIntRep \ - (tclStubsPtr->tcl_StoreIntRep) /* 639 */ +#define Tcl_FetchInternalRep \ + (tclStubsPtr->tcl_FetchInternalRep) /* 638 */ +#define Tcl_StoreInternalRep \ + (tclStubsPtr->tcl_StoreInternalRep) /* 639 */ #define Tcl_HasStringRep \ (tclStubsPtr->tcl_HasStringRep) /* 640 */ #define Tcl_IncrRefCount \ (tclStubsPtr->tcl_IncrRefCount) /* 641 */ #define Tcl_DecrRefCount \ @@ -3699,30 +3814,99 @@ (tclStubsPtr->tcl_UtfToUniChar) /* 646 */ #define Tcl_UniCharToUtfDString \ (tclStubsPtr->tcl_UniCharToUtfDString) /* 647 */ #define Tcl_UtfToUniCharDString \ (tclStubsPtr->tcl_UtfToUniCharDString) /* 648 */ +#define TclGetBytesFromObj \ + (tclStubsPtr->tclGetBytesFromObj) /* 649 */ +#define Tcl_GetBytesFromObj \ + (tclStubsPtr->tcl_GetBytesFromObj) /* 650 */ +#define Tcl_GetStringFromObj \ + (tclStubsPtr->tcl_GetStringFromObj) /* 651 */ +#define Tcl_GetUnicodeFromObj \ + (tclStubsPtr->tcl_GetUnicodeFromObj) /* 652 */ +#define Tcl_GetSizeIntFromObj \ + (tclStubsPtr->tcl_GetSizeIntFromObj) /* 653 */ +#define Tcl_UtfCharComplete \ + (tclStubsPtr->tcl_UtfCharComplete) /* 654 */ +#define Tcl_UtfNext \ + (tclStubsPtr->tcl_UtfNext) /* 655 */ +#define Tcl_UtfPrev \ + (tclStubsPtr->tcl_UtfPrev) /* 656 */ +#define Tcl_UniCharIsUnicode \ + (tclStubsPtr->tcl_UniCharIsUnicode) /* 657 */ +#define Tcl_ExternalToUtfDStringEx \ + (tclStubsPtr->tcl_ExternalToUtfDStringEx) /* 658 */ +#define Tcl_UtfToExternalDStringEx \ + (tclStubsPtr->tcl_UtfToExternalDStringEx) /* 659 */ +#define Tcl_AsyncMarkFromSignal \ + (tclStubsPtr->tcl_AsyncMarkFromSignal) /* 660 */ +#define Tcl_ListObjGetElements \ + (tclStubsPtr->tcl_ListObjGetElements) /* 661 */ +#define Tcl_ListObjLength \ + (tclStubsPtr->tcl_ListObjLength) /* 662 */ +#define Tcl_DictObjSize \ + (tclStubsPtr->tcl_DictObjSize) /* 663 */ +#define Tcl_SplitList \ + (tclStubsPtr->tcl_SplitList) /* 664 */ +#define Tcl_SplitPath \ + (tclStubsPtr->tcl_SplitPath) /* 665 */ +#define Tcl_FSSplitPath \ + (tclStubsPtr->tcl_FSSplitPath) /* 666 */ +#define Tcl_ParseArgsObjv \ + (tclStubsPtr->tcl_ParseArgsObjv) /* 667 */ +#define Tcl_UniCharLen \ + (tclStubsPtr->tcl_UniCharLen) /* 668 */ +#define Tcl_NumUtfChars \ + (tclStubsPtr->tcl_NumUtfChars) /* 669 */ +#define Tcl_GetCharLength \ + (tclStubsPtr->tcl_GetCharLength) /* 670 */ +#define Tcl_UtfAtIndex \ + (tclStubsPtr->tcl_UtfAtIndex) /* 671 */ +#define Tcl_GetRange \ + (tclStubsPtr->tcl_GetRange) /* 672 */ +#define Tcl_GetUniChar \ + (tclStubsPtr->tcl_GetUniChar) /* 673 */ +#define Tcl_GetBool \ + (tclStubsPtr->tcl_GetBool) /* 674 */ +#define Tcl_GetBoolFromObj \ + (tclStubsPtr->tcl_GetBoolFromObj) /* 675 */ +#define Tcl_CreateObjCommand2 \ + (tclStubsPtr->tcl_CreateObjCommand2) /* 676 */ +#define Tcl_CreateObjTrace2 \ + (tclStubsPtr->tcl_CreateObjTrace2) /* 677 */ +#define Tcl_NRCreateCommand2 \ + (tclStubsPtr->tcl_NRCreateCommand2) /* 678 */ +#define Tcl_NRCallObjProc2 \ + (tclStubsPtr->tcl_NRCallObjProc2) /* 679 */ +#define Tcl_GetNumberFromObj \ + (tclStubsPtr->tcl_GetNumberFromObj) /* 680 */ +#define Tcl_GetNumber \ + (tclStubsPtr->tcl_GetNumber) /* 681 */ +#define Tcl_RemoveChannelMode \ + (tclStubsPtr->tcl_RemoveChannelMode) /* 682 */ +#define Tcl_GetEncodingNulLength \ + (tclStubsPtr->tcl_GetEncodingNulLength) /* 683 */ +#define Tcl_GetWideUIntFromObj \ + (tclStubsPtr->tcl_GetWideUIntFromObj) /* 684 */ +#define Tcl_DStringToObj \ + (tclStubsPtr->tcl_DStringToObj) /* 685 */ +/* Slot 686 is reserved */ +/* Slot 687 is reserved */ +#define TclUnusedStubEntry \ + (tclStubsPtr->tclUnusedStubEntry) /* 688 */ #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); +#undef TclUnusedStubEntry + +#ifdef _WIN32 +# undef Tcl_CreateFileHandler +# undef Tcl_DeleteFileHandler +# undef Tcl_GetOpenFile #endif #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT @@ -3733,16 +3917,16 @@ #define Tcl_PkgRequire(interp, name, version, exact) \ Tcl_PkgRequireEx(interp, name, version, exact, NULL) #define Tcl_GetIndexFromObj(interp, objPtr, tablePtr, msg, flags, indexPtr) \ Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, \ sizeof(char *), msg, flags, indexPtr) -#define Tcl_NewBooleanObj(boolValue) \ - Tcl_NewWideIntObj((boolValue)!=0) -#define Tcl_DbNewBooleanObj(boolValue, file, line) \ - Tcl_DbNewWideIntObj((boolValue)!=0, file, line) -#define Tcl_SetBooleanObj(objPtr, boolValue) \ - Tcl_SetWideIntObj(objPtr, (boolValue)!=0) +#define Tcl_NewBooleanObj(intValue) \ + Tcl_NewWideIntObj((intValue)!=0) +#define Tcl_DbNewBooleanObj(intValue, file, line) \ + Tcl_DbNewWideIntObj((intValue)!=0, file, line) +#define Tcl_SetBooleanObj(objPtr, intValue) \ + Tcl_SetWideIntObj(objPtr, (intValue)!=0) #define Tcl_SetVar(interp, varName, newValue, flags) \ Tcl_SetVar2(interp, varName, NULL, newValue, flags) #define Tcl_UnsetVar(interp, varName, flags) \ Tcl_UnsetVar2(interp, varName, NULL, flags) #define Tcl_GetVar(interp, varName, flags) \ @@ -3758,28 +3942,14 @@ #define Tcl_AddErrorInfo(interp, message) \ Tcl_AppendObjToErrorInfo(interp, Tcl_NewStringObj(message, -1)) #define Tcl_AddObjErrorInfo(interp, message, length) \ Tcl_AppendObjToErrorInfo(interp, Tcl_NewStringObj(message, length)) #define Tcl_Eval(interp, objPtr) \ - Tcl_EvalEx(interp, objPtr, -1, 0) + Tcl_EvalEx(interp, objPtr, TCL_INDEX_NONE, 0) #define Tcl_GlobalEval(interp, objPtr) \ - Tcl_EvalEx(interp, objPtr, -1, TCL_EVAL_GLOBAL) + Tcl_EvalEx(interp, objPtr, TCL_INDEX_NONE, TCL_EVAL_GLOBAL) #define Tcl_GetStringResult(interp) Tcl_GetString(Tcl_GetObjResult(interp)) -#define Tcl_SaveResult(interp, statePtr) \ - do { \ - *(statePtr) = Tcl_GetObjResult(interp); \ - Tcl_IncrRefCount(*(statePtr)); \ - Tcl_SetObjResult(interp, Tcl_NewObj()); \ - } while(0) -#define Tcl_RestoreResult(interp, statePtr) \ - do { \ - Tcl_ResetResult(interp); \ - Tcl_SetObjResult(interp, *(statePtr)); \ - Tcl_DecrRefCount(*(statePtr)); \ - } while(0) -#define Tcl_DiscardResult(statePtr) \ - Tcl_DecrRefCount(*(statePtr)) #define Tcl_SetResult(interp, result, freeProc) \ do { \ const char *__result = result; \ Tcl_FreeProc *__freeProc = freeProc; \ Tcl_SetObjResult(interp, Tcl_NewStringObj(__result, -1)); \ @@ -3790,11 +3960,37 @@ (*__freeProc)((char *)__result); \ } \ } \ } while(0) -#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) +#undef Tcl_UtfToExternalDString +#define Tcl_UtfToExternalDString(encoding, src, len, ds) \ + (Tcl_UtfToExternalDStringEx(NULL, (encoding), (src), (len), \ + TCL_ENCODING_PROFILE_TCL8, (ds), NULL), Tcl_DStringValue(ds)) +#undef Tcl_ExternalToUtfDString +#define Tcl_ExternalToUtfDString(encoding, src, len, ds) \ + (Tcl_ExternalToUtfDStringEx(NULL, (encoding), (src), (len), \ + TCL_ENCODING_PROFILE_TCL8, (ds), NULL), Tcl_DStringValue(ds)) + +#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 @@ -3819,10 +4015,90 @@ 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) +#if TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED) +# undef Tcl_GetBytesFromObj +# undef Tcl_GetStringFromObj +# undef Tcl_GetUnicodeFromObj +#endif +#undef Tcl_GetIndexFromObjStruct +#undef Tcl_GetBooleanFromObj +#undef Tcl_GetBoolean +#if defined(USE_TCL_STUBS) +# if TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED) +# 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))) +# endif +#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \ + (tclStubsPtr->tcl_GetIndexFromObjStruct((interp), (objPtr), (tablePtr), (offset), (msg), \ + (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr))) +#define Tcl_GetBooleanFromObj(interp, objPtr, boolPtr) \ + ((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? tclStubsPtr->tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \ + Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr))) +#define Tcl_GetBoolean(interp, src, 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))) +#if TCL_MAJOR_VERSION > 8 +#undef Tcl_GetByteArrayFromObj +#define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \ + (sizeof(*(sizePtr)) <= sizeof(int) ? \ + tclStubsPtr->tclGetBytesFromObj(NULL, objPtr, (sizePtr)) : \ + tclStubsPtr->tcl_GetBytesFromObj(NULL, objPtr, (Tcl_Size *)(void *)(sizePtr))) + +#endif +#else +#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \ + ((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), (msg), \ + (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr))) +#define Tcl_GetBooleanFromObj(interp, objPtr, boolPtr) \ + ((sizeof(*(boolPtr)) == sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? Tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \ + Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr))) +#define Tcl_GetBoolean(interp, src, 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))) +#undef Tcl_GetByteArrayFromObj +#if defined(TCL_NO_DEPRECATED) +#define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \ + (Tcl_GetBytesFromObj)(NULL, objPtr, (sizePtr)) +#else +#define Tcl_GetByteArrayFromObj(objPtr, sizePtr) \ + (sizeof(*(sizePtr)) <= sizeof(int) ? \ + TclGetBytesFromObj(NULL, objPtr, (sizePtr)) : \ + (Tcl_GetBytesFromObj)(NULL, 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_GetStringFromObj(objPtr, sizePtr) \ + (sizeof(*(sizePtr)) <= sizeof(int) ? \ + TclGetStringFromObj(objPtr, (sizePtr)) : \ + (Tcl_GetStringFromObj)(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))) +#endif +#endif #ifdef TCL_MEM_DEBUG # undef Tcl_Alloc # define Tcl_Alloc(x) \ (Tcl_DbCkalloc((x), __FILE__, __LINE__)) @@ -3843,42 +4119,122 @@ #define Tcl_NewLongObj(value) Tcl_NewWideIntObj((long)(value)) #define Tcl_NewIntObj(value) Tcl_NewWideIntObj((int)(value)) #define Tcl_DbNewLongObj(value, file, line) Tcl_DbNewWideIntObj((long)(value), file, line) #define Tcl_SetIntObj(objPtr, value) Tcl_SetWideIntObj((objPtr), (int)(value)) #define Tcl_SetLongObj(objPtr, value) Tcl_SetWideIntObj((objPtr), (long)(value)) -#define Tcl_GetUnicode(objPtr) Tcl_GetUnicodeFromObj((objPtr), NULL) #define Tcl_BackgroundError(interp) Tcl_BackgroundException((interp), TCL_ERROR) #define Tcl_StringMatch(str, pattern) Tcl_StringCaseMatch((str), (pattern), 0) -#if TCL_UTF_MAX <= 3 +#if TCL_UTF_MAX < 4 # undef Tcl_UniCharToUtfDString # define Tcl_UniCharToUtfDString Tcl_Char16ToUtfDString # undef Tcl_UtfToUniCharDString # define Tcl_UtfToUniCharDString Tcl_UtfToChar16DString # undef Tcl_UtfToUniChar # define Tcl_UtfToUniChar Tcl_UtfToChar16 +# undef Tcl_UniCharLen +# define Tcl_UniCharLen Tcl_Char16Len +# undef Tcl_UniCharToUtf +# if defined(USE_TCL_STUBS) +# define Tcl_UniCharToUtf(c, p) \ + (tclStubsPtr->tcl_UniCharToUtf((c)|TCL_COMBINE, (p))) +# else +# define Tcl_UniCharToUtf(c, p) \ + ((Tcl_UniCharToUtf)((c)|TCL_COMBINE, (p))) +# endif +#if !defined(BUILD_tcl) +# 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 +#endif #endif #if defined(USE_TCL_STUBS) # define Tcl_WCharToUtfDString (sizeof(wchar_t) != sizeof(short) \ - ? (char *(*)(const wchar_t *, size_t, Tcl_DString *))tclStubsPtr->tcl_UniCharToUtfDString \ - : (char *(*)(const wchar_t *, size_t, Tcl_DString *))Tcl_Char16ToUtfDString) + ? (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))tclStubsPtr->tcl_UniCharToUtfDString \ + : (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))Tcl_Char16ToUtfDString) # define Tcl_UtfToWCharDString (sizeof(wchar_t) != sizeof(short) \ - ? (wchar_t *(*)(const char *, size_t, Tcl_DString *))tclStubsPtr->tcl_UtfToUniCharDString \ - : (wchar_t *(*)(const char *, size_t, Tcl_DString *))Tcl_UtfToChar16DString) + ? (wchar_t *(*)(const char *, Tcl_Size, Tcl_DString *))tclStubsPtr->tcl_UtfToUniCharDString \ + : (wchar_t *(*)(const char *, Tcl_Size, Tcl_DString *))Tcl_UtfToChar16DString) # define Tcl_UtfToWChar (sizeof(wchar_t) != sizeof(short) \ - ? (int (*)(const char *, wchar_t *))tclStubsPtr->tcl_UtfToChar16 \ - : (int (*)(const char *, wchar_t *))Tcl_UtfToUniChar) + ? (Tcl_Size (*)(const char *, wchar_t *))tclStubsPtr->tcl_UtfToUniChar \ + : (Tcl_Size (*)(const char *, wchar_t *))Tcl_UtfToChar16) +# define Tcl_WCharLen (sizeof(wchar_t) != sizeof(short) \ + ? (Tcl_Size (*)(wchar_t *))tclStubsPtr->tcl_UniCharLen \ + : (Tcl_Size (*)(wchar_t *))Tcl_Char16Len) +#if TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED) +# undef Tcl_ListObjGetElements +# 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))) +# undef Tcl_ListObjLength +# define Tcl_ListObjLength(interp, listPtr, lengthPtr) (sizeof(*(lengthPtr)) == sizeof(int) \ + ? tclStubsPtr->tclListObjLength((interp), (listPtr), (lengthPtr)) \ + : tclStubsPtr->tcl_ListObjLength((interp), (listPtr), (Tcl_Size *)(void *)(lengthPtr))) +# undef Tcl_DictObjSize +# define Tcl_DictObjSize(interp, dictPtr, sizePtr) (sizeof(*(sizePtr)) == sizeof(int) \ + ? tclStubsPtr->tclDictObjSize((interp), (dictPtr), (sizePtr)) \ + : tclStubsPtr->tcl_DictObjSize((interp), (dictPtr), (Tcl_Size *)(void *)(sizePtr))) +# undef Tcl_SplitList +# 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))) +# undef Tcl_SplitPath +# define Tcl_SplitPath(path, argcPtr, argvPtr) (sizeof(*(argcPtr)) == sizeof(int) \ + ? tclStubsPtr->tclSplitPath((path), (argcPtr), (argvPtr)) \ + : tclStubsPtr->tcl_SplitPath((path), (Tcl_Size *)(void *)(argcPtr), (argvPtr))) +# undef Tcl_FSSplitPath +# define Tcl_FSSplitPath(pathPtr, lenPtr) (sizeof(*(lenPtr)) == sizeof(int) \ + ? tclStubsPtr->tclFSSplitPath((pathPtr), (lenPtr)) \ + : tclStubsPtr->tcl_FSSplitPath((pathPtr), (Tcl_Size *)(void *)(lenPtr))) +# undef Tcl_ParseArgsObjv +# 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 /* TCL_MAJOR_VERSION < 9 || !defined(TCL_NO_DEPRECATED) */ #else # define Tcl_WCharToUtfDString (sizeof(wchar_t) != sizeof(short) \ - ? (char *(*)(const wchar_t *, size_t, Tcl_DString *))Tcl_UniCharToUtfDString \ - : (char *(*)(const wchar_t *, size_t, Tcl_DString *))Tcl_Char16ToUtfDString) + ? (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))Tcl_UniCharToUtfDString \ + : (char *(*)(const wchar_t *, Tcl_Size, Tcl_DString *))Tcl_Char16ToUtfDString) # define Tcl_UtfToWCharDString (sizeof(wchar_t) != sizeof(short) \ - ? (wchar_t *(*)(const char *, size_t, Tcl_DString *))Tcl_UtfToUniCharDString \ - : (wchar_t *(*)(const char *, size_t, Tcl_DString *))Tcl_UtfToChar16DString) + ? (wchar_t *(*)(const char *, Tcl_Size, Tcl_DString *))Tcl_UtfToUniCharDString \ + : (wchar_t *(*)(const char *, Tcl_Size, Tcl_DString *))Tcl_UtfToChar16DString) # define Tcl_UtfToWChar (sizeof(wchar_t) != sizeof(short) \ - ? (int (*)(const char *, wchar_t *))Tcl_UtfToChar16 \ - : (int (*)(const char *, wchar_t *))Tcl_UtfToUniChar) + ? (Tcl_Size (*)(const char *, wchar_t *))Tcl_UtfToUniChar \ + : (Tcl_Size (*)(const char *, wchar_t *))Tcl_UtfToChar16) +# define Tcl_WCharLen (sizeof(wchar_t) != sizeof(short) \ + ? (Tcl_Size (*)(wchar_t *))Tcl_UniCharLen \ + : (Tcl_Size (*)(wchar_t *))Tcl_Char16Len) +#if !defined(BUILD_tcl) && !defined(TCL_NO_DEPRECATED) +# 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))) +#endif /* !defined(BUILD_tcl) */ #endif /* * Deprecated Tcl procedures: */ @@ -3886,55 +4242,49 @@ #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 +#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 + +#ifdef TCL_USE_STUBS + /* Protect those 10 functions, being usable through the stub table */ +# undef TclGetStringFromObj +# undef TclGetBytesFromObj +# undef TclGetUnicodeFromObj +# undef TclListObjGetElements +# undef TclListObjLength +# undef TclDictObjSize +# undef TclSplitList +# undef TclSplitPath +# undef TclFSSplitPath +# undef TclParseArgsObjv +#endif + +#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 +#endif #endif /* _TCLDECLS */ Index: generic/tclDictObj.c ================================================================== --- generic/tclDictObj.c +++ generic/tclDictObj.c @@ -2,11 +2,11 @@ * tclDictObj.c -- * * This file contains functions that implement the Tcl dict object type * and its accessor command. * - * Copyright (c) 2002-2010 by Donal K. Fellows. + * Copyright © 2002-2010 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -59,10 +59,12 @@ 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. */ @@ -127,11 +129,11 @@ * 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 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; @@ -141,28 +143,40 @@ * functions that can be invoked by generic object code. */ const Tcl_ObjType tclDictType = { "dict", - FreeDictInternalRep, /* freeIntRepProc */ - DupDictInternalRep, /* dupIntRepProc */ - UpdateStringOfDict, /* updateStringProc */ - SetDictFromAny /* setFromAnyProc */ + FreeDictInternalRep, /* freeIntRepProc */ + DupDictInternalRep, /* dupIntRepProc */ + UpdateStringOfDict, /* updateStringProc */ + SetDictFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_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 DictSetIntRep(objPtr, dictRepPtr) \ +#define DictSetInternalRep(objPtr, dictRepPtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (dictRepPtr); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreIntRep((objPtr), &tclDictType, &ir); \ + Tcl_StoreInternalRep((objPtr), &tclDictType, &ir); \ } while (0) -#define DictGetIntRep(objPtr, dictRepPtr) \ +#define DictGetInternalRep(objPtr, dictRepPtr) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), &tclDictType); \ + 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 @@ -360,11 +374,11 @@ Tcl_Obj *copyPtr) { Dict *oldDict, *newDict = (Dict *)Tcl_Alloc(sizeof(Dict)); ChainEntry *cPtr; - DictGetIntRep(srcPtr, oldDict); + DictGetInternalRep(srcPtr, oldDict); /* * Copy values across from the old hash table. */ @@ -393,11 +407,11 @@ /* * Store in the object. */ - DictSetIntRep(copyPtr, newDict); + DictSetInternalRep(copyPtr, newDict); } /* *---------------------------------------------------------------------- * @@ -420,11 +434,11 @@ FreeDictInternalRep( Tcl_Obj *dictPtr) { Dict *dict; - DictGetIntRep(dictPtr, dict); + DictGetInternalRep(dictPtr, dict); if (dict->refCount-- <= 1) { DeleteDict(dict); } } @@ -486,22 +500,23 @@ #define LOCAL_SIZE 64 char localFlags[LOCAL_SIZE], *flagPtr = NULL; Dict *dict; ChainEntry *cPtr; Tcl_Obj *keyPtr, *valuePtr; - size_t i, length, bytesNeeded = 0; + 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... */ - size_t numElems; + Tcl_Size numElems; - DictGetIntRep(dictPtr, dict); + DictGetInternalRep(dictPtr, dict); assert (dict != NULL); numElems = dict->table.numEntries * 2; @@ -526,15 +541,15 @@ * elements already. */ flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 ); keyPtr = (Tcl_Obj *)Tcl_GetHashKey(&dict->table, &cPtr->entry); - elem = TclGetStringFromObj(keyPtr, &length); + elem = Tcl_GetStringFromObj(keyPtr, &length); bytesNeeded += TclScanElement(elem, length, flagPtr+i); flagPtr[i+1] = TCL_DONT_QUOTE_HASH; valuePtr = (Tcl_Obj *)Tcl_GetHashValue(&cPtr->entry); - elem = TclGetStringFromObj(valuePtr, &length); + elem = Tcl_GetStringFromObj(valuePtr, &length); bytesNeeded += TclScanElement(elem, length, flagPtr+i+1); } bytesNeeded += numElems; /* @@ -544,20 +559,21 @@ dst = Tcl_InitStringRep(dictPtr, NULL, bytesNeeded - 1); TclOOM(dst, bytesNeeded); for (i=0,cPtr=dict->entryChainHead; inextPtr) { flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 ); keyPtr = (Tcl_Obj *)Tcl_GetHashKey(&dict->table, &cPtr->entry); - elem = TclGetStringFromObj(keyPtr, &length); + elem = Tcl_GetStringFromObj(keyPtr, &length); dst += TclConvertElement(elem, length, dst, flagPtr[i]); *dst++ = ' '; flagPtr[i+1] |= TCL_DONT_QUOTE_HASH; valuePtr = (Tcl_Obj *)Tcl_GetHashValue(&cPtr->entry); - elem = TclGetStringFromObj(valuePtr, &length); + elem = Tcl_GetStringFromObj(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); } @@ -598,16 +614,16 @@ * Since lists and dictionaries have very closely-related string * representations (i.e. the same parsing code) we can safely special-case * the conversion from lists to dictionaries. */ - if (TclHasIntRep(objPtr, &tclListType)) { - int objc, i; + if (TclHasInternalRep(objPtr, &tclListType)) { + Tcl_Size objc, i; Tcl_Obj **objv; /* Cannot fail, we already know the Tcl_ObjType is "list". */ - TclListObjGetElements(NULL, objPtr, &objc, &objv); + TclListObjGetElementsM(NULL, objPtr, &objc, &objv); if (objc & 1) { goto missingValue; } for (i=0 ; iepoch = 1; dict->chain = NULL; dict->refCount = 1; - DictSetIntRep(objPtr, dict); + DictSetInternalRep(objPtr, dict); return TCL_OK; missingValue: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing value to go with key", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", (void *)NULL); } errorInFindDictElement: DeleteChainTable(dict); Tcl_Free(dict); return TCL_ERROR; @@ -728,16 +744,16 @@ Tcl_Interp *interp, Tcl_Obj *dictPtr) { Dict *dict; - DictGetIntRep(dictPtr, dict); + DictGetInternalRep(dictPtr, dict); if (dict == NULL) { if (SetDictFromAny(interp, dictPtr) != TCL_OK) { return NULL; } - DictGetIntRep(dictPtr, dict); + DictGetInternalRep(dictPtr, dict); } return dict; } /* @@ -764,33 +780,33 @@ * side effects occur. Shared dictionaries along the path are converted * into unshared objects, and a backward-pointing chain is built using * the chain fields of the dictionaries (for easy invalidation of string * representations using InvalidateDictChain). If the flags argument has * the DICT_PATH_CREATE bits set (and not the DICT_PATH_EXISTS bit), - * non-existant keys will be inserted with a value of an empty + * non-extant keys will be inserted with a value of an empty * dictionary, resulting in the path being built. * *---------------------------------------------------------------------- */ Tcl_Obj * TclTraceDictPath( Tcl_Interp *interp, Tcl_Obj *dictPtr, - int keyc, + Tcl_Size keyc, Tcl_Obj *const keyv[], int flags) { Dict *dict, *newDict; - int i; + Tcl_Size i; - DictGetIntRep(dictPtr, dict); + DictGetInternalRep(dictPtr, dict); if (dict == NULL) { if (SetDictFromAny(interp, dictPtr) != TCL_OK) { return NULL; } - DictGetIntRep(dictPtr, dict); + DictGetInternalRep(dictPtr, dict); } if (flags & DICT_PATH_UPDATE) { dict->chain = NULL; } @@ -808,11 +824,11 @@ if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "key \"%s\" not known in dictionary", TclGetString(keyv[i]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT", - TclGetString(keyv[i]), NULL); + TclGetString(keyv[i]), (void *)NULL); } return NULL; } /* @@ -824,28 +840,28 @@ Tcl_IncrRefCount(tmpObj); Tcl_SetHashValue(hPtr, tmpObj); } else { tmpObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr); - DictGetIntRep(tmpObj, newDict); + DictGetInternalRep(tmpObj, newDict); if (newDict == NULL) { if (SetDictFromAny(interp, tmpObj) != TCL_OK) { return NULL; } } } - DictGetIntRep(tmpObj, newDict); + DictGetInternalRep(tmpObj, newDict); if (flags & DICT_PATH_UPDATE) { if (Tcl_IsShared(tmpObj)) { TclDecrRefCount(tmpObj); tmpObj = Tcl_DuplicateObj(tmpObj); Tcl_IncrRefCount(tmpObj); Tcl_SetHashValue(hPtr, tmpObj); dict->epoch++; - DictGetIntRep(tmpObj, newDict); + DictGetInternalRep(tmpObj, newDict); } newDict->chain = dictPtr; } dict = newDict; @@ -857,11 +873,11 @@ /* *---------------------------------------------------------------------- * * InvalidateDictChain -- * - * Go through a dictionary chain (built by an updating invokation of + * Go through a dictionary chain (built by an updating invocation of * TclTraceDictPath) and invalidate the string representations of all the * dictionaries on the chain. * * Results: * None @@ -878,26 +894,26 @@ InvalidateDictChain( Tcl_Obj *dictObj) { Dict *dict; - DictGetIntRep(dictObj, dict); + DictGetInternalRep(dictObj, dict); assert( dict != NULL); do { dict->refCount++; TclInvalidateStringRep(dictObj); - TclFreeIntRep(dictObj); - DictSetIntRep(dictObj, dict); + TclFreeInternalRep(dictObj); + DictSetInternalRep(dictObj, dict); dict->epoch++; dictObj = dict->chain; if (dictObj == NULL) { break; } dict->chain = NULL; - DictGetIntRep(dictObj, dict); + DictGetInternalRep(dictObj, dict); } while (dict != NULL); } /* *---------------------------------------------------------------------- @@ -939,12 +955,12 @@ } TclInvalidateStringRep(dictPtr); hPtr = CreateChainEntry(dict, keyPtr, &isNew); dict->refCount++; - TclFreeIntRep(dictPtr) - DictSetIntRep(dictPtr, dict); + TclFreeInternalRep(dictPtr) + DictSetInternalRep(dictPtr, dict); Tcl_IncrRefCount(valuePtr); if (!isNew) { Tcl_Obj *oldValuePtr = (Tcl_Obj *)Tcl_GetHashValue(hPtr); TclDecrRefCount(oldValuePtr); @@ -1043,10 +1059,30 @@ } /* *---------------------------------------------------------------------- * + * 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: @@ -1058,15 +1094,16 @@ * dictionary already. * *---------------------------------------------------------------------- */ +#undef Tcl_DictObjSize int Tcl_DictObjSize( Tcl_Interp *interp, Tcl_Obj *dictPtr, - int *sizePtr) + Tcl_Size *sizePtr) { Dict *dict; dict = GetDictFromObj(interp, dictPtr); if (dict == NULL) { @@ -1182,11 +1219,11 @@ * otherwise. */ { ChainEntry *cPtr; /* - * If the searh is done; we do no work. + * If the search is done; we do no work. */ if (!searchPtr->epoch) { *donePtr = 1; return; @@ -1275,11 +1312,11 @@ int Tcl_DictObjPutKeyList( Tcl_Interp *interp, Tcl_Obj *dictPtr, - int keyc, + Tcl_Size keyc, Tcl_Obj *const keyv[], Tcl_Obj *valuePtr) { Dict *dict; Tcl_HashEntry *hPtr; @@ -1295,11 +1332,11 @@ dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_CREATE); if (dictPtr == NULL) { return TCL_ERROR; } - DictGetIntRep(dictPtr, dict); + DictGetInternalRep(dictPtr, dict); assert(dict != NULL); hPtr = CreateChainEntry(dict, keyv[keyc-1], &isNew); Tcl_IncrRefCount(valuePtr); if (!isNew) { Tcl_Obj *oldValuePtr = (Tcl_Obj *)Tcl_GetHashValue(hPtr); @@ -1336,11 +1373,11 @@ int Tcl_DictObjRemoveKeyList( Tcl_Interp *interp, Tcl_Obj *dictPtr, - int keyc, + Tcl_Size keyc, Tcl_Obj *const keyv[]) { Dict *dict; if (Tcl_IsShared(dictPtr)) { @@ -1353,11 +1390,11 @@ dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_UPDATE); if (dictPtr == NULL) { return TCL_ERROR; } - DictGetIntRep(dictPtr, dict); + DictGetInternalRep(dictPtr, dict); assert(dict != NULL); DeleteChainEntry(dict, keyv[keyc-1]); InvalidateDictChain(dictPtr); return TCL_OK; } @@ -1400,11 +1437,11 @@ dict = (Dict *)Tcl_Alloc(sizeof(Dict)); InitChainTable(dict); dict->epoch = 1; dict->chain = NULL; dict->refCount = 1; - DictSetIntRep(dictPtr, dict); + DictSetInternalRep(dictPtr, dict); return dictPtr; #endif } /* @@ -1448,11 +1485,11 @@ dict = (Dict *)Tcl_Alloc(sizeof(Dict)); InitChainTable(dict); dict->epoch = 1; dict->chain = NULL; dict->refCount = 1; - DictSetIntRep(dictPtr, dict); + DictSetInternalRep(dictPtr, dict); return dictPtr; } #else /* !TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewDictObj( @@ -1483,11 +1520,11 @@ *---------------------------------------------------------------------- */ static int DictCreateCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictObj; @@ -1533,11 +1570,11 @@ *---------------------------------------------------------------------- */ static int DictGetCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *valuePtr = NULL; @@ -1599,11 +1636,11 @@ if (valuePtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "key \"%s\" not known in dictionary", TclGetString(objv[objc-1]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT", - TclGetString(objv[objc-1]), NULL); + TclGetString(objv[objc-1]), (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, valuePtr); return TCL_OK; } @@ -1626,11 +1663,11 @@ *---------------------------------------------------------------------- */ static int DictGetDefCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *keyPtr, *valuePtr, *defaultPtr; @@ -1691,11 +1728,11 @@ *---------------------------------------------------------------------- */ static int DictReplaceCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr; @@ -1739,11 +1776,11 @@ *---------------------------------------------------------------------- */ static int DictRemoveCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr; @@ -1787,11 +1824,11 @@ *---------------------------------------------------------------------- */ static int DictMergeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *targetObj, *keyObj = NULL, *valueObj = NULL; @@ -1874,11 +1911,11 @@ *---------------------------------------------------------------------- */ static int DictKeysCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *listPtr; @@ -1953,11 +1990,11 @@ *---------------------------------------------------------------------- */ static int DictValuesCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *valuePtr = NULL, *listPtr; @@ -2013,16 +2050,17 @@ *---------------------------------------------------------------------- */ static int DictSizeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { - int result, size; + int result; + Tcl_Size size; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "dictionary"); return TCL_ERROR; } @@ -2051,11 +2089,11 @@ *---------------------------------------------------------------------- */ static int DictExistsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *valuePtr; @@ -2093,11 +2131,11 @@ *---------------------------------------------------------------------- */ static int DictInfoCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Dict *dict; @@ -2137,11 +2175,11 @@ *---------------------------------------------------------------------- */ static int DictIncrCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int code = TCL_OK; @@ -2258,11 +2296,11 @@ *---------------------------------------------------------------------- */ static int DictLappendCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *valuePtr, *resultPtr; @@ -2345,11 +2383,11 @@ *---------------------------------------------------------------------- */ static int DictAppendCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *valuePtr, *resultPtr; @@ -2447,20 +2485,21 @@ *---------------------------------------------------------------------- */ static int DictForNRCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj; Tcl_Obj **varv, *keyObj, *valueObj; Tcl_DictSearch *searchPtr; - int varc, done; + Tcl_Size varc; + int done; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "{keyVarName valueVarName} dictionary script"); return TCL_ERROR; @@ -2468,17 +2507,17 @@ /* * Parse arguments. */ - if (TclListObjGetElements(interp, objv[1], &varc, &varv) != TCL_OK) { + if (TclListObjGetElementsM(interp, objv[1], &varc, &varv) != TCL_OK) { return TCL_ERROR; } if (varc != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have exactly two variable names", -1)); - Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "for", NULL); + Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "for", (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) { @@ -2487,11 +2526,11 @@ } if (done) { TclStackFree(interp, searchPtr); return TCL_OK; } - TclListObjGetElements(NULL, objv[1], &varc, &varv); + TclListObjGetElementsM(NULL, objv[1], &varc, &varv); keyVarObj = varv[0]; valueVarObj = varv[1]; scriptObj = objv[3]; /* @@ -2542,11 +2581,11 @@ return TCL_ERROR; } static int DictForLoopCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_DictSearch *searchPtr = (Tcl_DictSearch *)data[0]; @@ -2642,19 +2681,20 @@ *---------------------------------------------------------------------- */ static int DictMapNRCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; Tcl_Obj **varv, *keyObj, *valueObj; DictMapStorage *storagePtr; - int varc, done; + Tcl_Size varc; + int done; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "{keyVarName valueVarName} dictionary script"); return TCL_ERROR; @@ -2662,17 +2702,17 @@ /* * Parse arguments. */ - if (TclListObjGetElements(interp, objv[1], &varc, &varv) != TCL_OK) { + if (TclListObjGetElementsM(interp, objv[1], &varc, &varv) != TCL_OK) { return TCL_ERROR; } if (varc != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have exactly two variable names", -1)); - Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "map", NULL); + Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "map", (void *)NULL); return TCL_ERROR; } storagePtr = (DictMapStorage *)TclStackAlloc(interp, sizeof(DictMapStorage)); if (Tcl_DictObjFirst(interp, objv[2], &storagePtr->search, &keyObj, &valueObj, &done) != TCL_OK) { @@ -2688,11 +2728,11 @@ TclStackFree(interp, storagePtr); return TCL_OK; } TclNewObj(storagePtr->accumulatorObj); - TclListObjGetElements(NULL, objv[1], &varc, &varv); + TclListObjGetElementsM(NULL, objv[1], &varc, &varv); storagePtr->keyVarObj = varv[0]; storagePtr->valueVarObj = varv[1]; storagePtr->scriptObj = objv[3]; /* @@ -2746,11 +2786,11 @@ return TCL_ERROR; } static int DictMapLoopCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; DictMapStorage *storagePtr = (DictMapStorage *)data[0]; @@ -2854,11 +2894,11 @@ *---------------------------------------------------------------------- */ static int DictSetCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *resultPtr; @@ -2914,11 +2954,11 @@ *---------------------------------------------------------------------- */ static int DictUnsetCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *resultPtr; @@ -2973,11 +3013,11 @@ *---------------------------------------------------------------------- */ static int DictFilterCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; @@ -2984,15 +3024,16 @@ static const char *const filters[] = { "key", "script", "value", NULL }; enum FilterTypes { FILTER_KEYS, FILTER_SCRIPT, FILTER_VALUES - }; + } index; Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj; Tcl_Obj **varv, *keyObj = NULL, *valueObj = NULL, *resultObj, *boolObj; Tcl_DictSearch search; - int index, varc, done, result, satisfied; + int done, result, satisfied; + Tcl_Size varc; const char *pattern; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "dictionary filterType ?arg ...?"); return TCL_ERROR; @@ -3000,11 +3041,11 @@ if (Tcl_GetIndexFromObj(interp, objv[2], filters, "filterType", 0, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum FilterTypes) index) { + switch (index) { case FILTER_KEYS: /* * Create a dictionary whose keys all match a certain pattern. */ @@ -3101,17 +3142,17 @@ * Create a dictionary whose key,value pairs all satisfy a script * (i.e. get a true boolean result from its evaluation). Massive * copying from the "dict for" implementation has occurred! */ - if (TclListObjGetElements(interp, objv[3], &varc, &varv) != TCL_OK) { + if (TclListObjGetElementsM(interp, objv[3], &varc, &varv) != TCL_OK) { return TCL_ERROR; } if (varc != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have exactly two variable names", -1)); - Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "filter", NULL); + Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "filter", (void *)NULL); return TCL_ERROR; } keyVarObj = varv[0]; valueVarObj = varv[1]; scriptObj = objv[4]; @@ -3258,18 +3299,19 @@ *---------------------------------------------------------------------- */ static int DictUpdateCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; Tcl_Obj *dictPtr, *objPtr; - int i, dummy; + int i; + Tcl_Size dummy; if (objc < 5 || !(objc & 1)) { Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key varName ?key varName ...? script"); return TCL_ERROR; @@ -3312,17 +3354,17 @@ return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1); } static int FinalizeDictUpdate( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Obj *dictPtr, *objPtr, **objv; Tcl_InterpState state; - int i, objc; + Tcl_Size i, objc; Tcl_Obj *varName = (Tcl_Obj *)data[0]; Tcl_Obj *argsObj = (Tcl_Obj *)data[1]; /* * ErrorInfo handling. @@ -3362,11 +3404,11 @@ /* * Write back the values from the variables, treating failure to read as * an instruction to remove the key. */ - Tcl_ListObjGetElements(NULL, argsObj, &objc, &objv); + TclListObjGetElementsM(NULL, argsObj, &objc, &objv); for (i=0 ; icmdFramePtr, objc-1); } static int FinalizeDictWith( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Obj **pathv; - int pathc; + Tcl_Size pathc; Tcl_InterpState state; Tcl_Obj *varName = (Tcl_Obj *)data[0]; Tcl_Obj *keysPtr = (Tcl_Obj *)data[1]; Tcl_Obj *pathPtr = (Tcl_Obj *)data[2]; Var *varPtr, *arrayPtr; @@ -3486,11 +3528,11 @@ * TCL_OK result. */ state = Tcl_SaveInterpState(interp, result); if (pathPtr != NULL) { - Tcl_ListObjGetElements(NULL, pathPtr, &pathc, &pathv); + TclListObjGetElementsM(NULL, pathPtr, &pathc, &pathv); } else { pathc = 0; pathv = NULL; } @@ -3545,11 +3587,11 @@ Tcl_Obj * TclDictWithInit( Tcl_Interp *interp, Tcl_Obj *dictPtr, - int pathc, + Tcl_Size pathc, Tcl_Obj *const pathv[]) { Tcl_DictSearch s; Tcl_Obj *keyPtr, *valPtr, *keysPtr; int done; @@ -3632,11 +3674,11 @@ Tcl_Obj *const pathv[], /* The elements of the path to the subdict. */ Tcl_Obj *keysPtr) /* List of keys to be synchronized. This is * the result value from TclDictWithInit. */ { Tcl_Obj *dictPtr, *leafPtr, *valPtr; - int i, allocdict, keyc; + Tcl_Size i, allocdict, keyc; Tcl_Obj **keyv; /* * If the dictionary variable doesn't exist, drop everything silently. */ @@ -3663,13 +3705,13 @@ } if (pathc > 0) { /* * Want to get to the dictionary which we will update; need to do - * prepare-for-update de-sharing along the path *but* avoid generating - * an error on a non-existant path (we'll treat that the same as a - * non-existant variable. Luckily, the de-sharing operation isn't + * prepare-for-update unsharing along the path *but* avoid generating + * an error on a non-extant path (we'll treat that the same as a + * non-extant variable. Luckily, the unsharing operation isn't * deeply damaging if we don't go on to update; it's just less than * perfectly efficient (but no memory should be leaked). */ leafPtr = TclTraceDictPath(interp, dictPtr, pathc, pathv, @@ -3692,11 +3734,11 @@ /* * Now process our updates on the leaf dictionary. */ - TclListObjGetElements(NULL, keysPtr, &keyc, &keyv); + TclListObjGetElementsM(NULL, keysPtr, &keyc, &keyv); for (i=0 ; iwideValue; \ + (inst) = irPtr->wideValue; \ } while (0) /* *---------------------------------------------------------------------- @@ -191,16 +192,16 @@ void TclPrintObject( FILE *outFile, /* The file to print the source to. */ Tcl_Obj *objPtr, /* Points to the Tcl object whose string * representation should be printed. */ - size_t maxChars) /* Maximum number of chars to print. */ + Tcl_Size maxChars) /* Maximum number of chars to print. */ { char *bytes; - size_t length; + Tcl_Size length; - bytes = TclGetStringFromObj(objPtr, &length); + bytes = Tcl_GetStringFromObj(objPtr, &length); TclPrintSource(outFile, bytes, TclMin(length, maxChars)); } /* *---------------------------------------------------------------------- @@ -222,11 +223,11 @@ void TclPrintSource( FILE *outFile, /* The file to print the source to. */ const char *stringPtr, /* The string to print. */ - size_t maxChars) /* Maximum number of chars to print. */ + Tcl_Size maxChars) /* Maximum number of chars to print. */ { Tcl_Obj *bufferObj; TclNewObj(bufferObj); PrintSourceToObj(bufferObj, stringPtr, maxChars); @@ -253,15 +254,16 @@ { ByteCode *codePtr; unsigned char *codeStart, *codeLimit, *pc; unsigned char *codeDeltaNext, *codeLengthNext; unsigned char *srcDeltaNext, *srcLengthNext; - int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, i, line; + int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, line; + Tcl_Size i; Interp *iPtr; Tcl_Obj *bufferObj, *fileObj; - ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr); iPtr = (Interp *) *codePtr->interpHandle; TclNewObj(bufferObj); if (!codePtr->refCount) { @@ -275,11 +277,11 @@ /* * Print header lines describing the ByteCode. */ Tcl_AppendPrintfToObj(bufferObj, - "ByteCode %p, refCt %" TCL_Z_MODIFIER "u, epoch %" TCL_Z_MODIFIER "u, interp %p (epoch %" TCL_Z_MODIFIER "u)\n", + "ByteCode %p, refCt %" TCL_SIZE_MODIFIER "u, epoch %" TCL_SIZE_MODIFIER "u, interp %p (epoch %" TCL_SIZE_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); @@ -286,29 +288,30 @@ if (line >= 0 && fileObj != NULL) { Tcl_AppendPrintfToObj(bufferObj, "\n File \"%s\" Line %d", TclGetString(fileObj), line); } Tcl_AppendPrintfToObj(bufferObj, - "\n Cmds %d, src %d, inst %d, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n", + "\n Cmds %d, src %" TCL_SIZE_MODIFIER "u, inst %" TCL_SIZE_MODIFIER "u, litObjs %" TCL_SIZE_MODIFIER "u, aux %" TCL_SIZE_MODIFIER "u, stkDepth %" TCL_SIZE_MODIFIER "u, code/src %.2f\n", numCmds, codePtr->numSrcBytes, codePtr->numCodeBytes, - codePtr->numLitObjects, codePtr->numAuxDataItems, + codePtr->numLitObjects, BA_AuxData_Size(codePtr->auxData), codePtr->maxStackDepth, #ifdef TCL_COMPILE_STATS codePtr->numSrcBytes? codePtr->structureSize/(float)codePtr->numSrcBytes : #endif 0.0); #ifdef TCL_COMPILE_STATS Tcl_AppendPrintfToObj(bufferObj, - " Code %lu = header %lu+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n", - (unsigned long) codePtr->structureSize, - (unsigned long) (sizeof(ByteCode) - sizeof(size_t) - sizeof(Tcl_Time)), + " Code %" TCL_Z_MODIFIER "u = header %" TCL_Z_MODIFIER "u+inst %" TCL_SIZE_MODIFIER "u+litObj %" + TCL_Z_MODIFIER "u+exc %" TCL_Z_MODIFIER "u+aux %" TCL_Z_MODIFIER "u+cmdMap %" TCL_SIZE_MODIFIER "u\n", + codePtr->structureSize, + offsetof(ByteCode, localCachePtr), codePtr->numCodeBytes, - (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)), - (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)), - (unsigned long) (codePtr->numAuxDataItems * sizeof(AuxData)), + codePtr->numLitObjects * sizeof(Tcl_Obj *), + codePtr->numExceptRanges*sizeof(ExceptionRange), + BA_AuxData_Size(codePtr->auxData) * sizeof(AuxData), codePtr->numCmdLocBytes); #endif /* TCL_COMPILE_STATS */ /* * If the ByteCode is the compiled body of a Tcl procedure, print @@ -316,22 +319,22 @@ * procedure's name since ByteCode's can be shared among procedures. */ if (codePtr->procPtr != NULL) { Proc *procPtr = codePtr->procPtr; - int numCompiledLocals = procPtr->numCompiledLocals; + Tcl_Size numCompiledLocals = procPtr->numCompiledLocals; Tcl_AppendPrintfToObj(bufferObj, - " Proc %p, refCt %" TCL_Z_MODIFIER "u, args %d, compiled locals %d\n", + " Proc %p, refCt %" TCL_SIZE_MODIFIER "u, args %" TCL_SIZE_MODIFIER "u, compiled locals %" TCL_SIZE_MODIFIER "u\n", procPtr, procPtr->refCount, procPtr->numArgs, numCompiledLocals); if (numCompiledLocals > 0) { CompiledLocal *localPtr = procPtr->firstLocalPtr; for (i = 0; i < numCompiledLocals; i++) { Tcl_AppendPrintfToObj(bufferObj, - " slot %d%s%s%s%s%s%s", i, + " slot %" TCL_SIZE_MODIFIER "u%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" : "", @@ -349,29 +352,29 @@ /* * Print the ExceptionRange array. */ - if (codePtr->numExceptRanges > 0) { - Tcl_AppendPrintfToObj(bufferObj, " Exception ranges %d, depth %d:\n", + if ((int)codePtr->numExceptRanges > 0) { + Tcl_AppendPrintfToObj(bufferObj, " Exception ranges %" TCL_SIZE_MODIFIER "u, depth %" TCL_SIZE_MODIFIER "u:\n", codePtr->numExceptRanges, codePtr->maxExceptDepth); - for (i = 0; i < codePtr->numExceptRanges; i++) { + for (i = 0; i < (int)codePtr->numExceptRanges; i++) { ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i]; Tcl_AppendPrintfToObj(bufferObj, - " %d: level %d, %s, pc %d-%d, ", + " %" TCL_SIZE_MODIFIER "u: level %" TCL_SIZE_MODIFIER "u, %s, pc %" TCL_SIZE_MODIFIER "u-%" TCL_SIZE_MODIFIER "u, ", i, rangePtr->nestingLevel, (rangePtr->type==LOOP_EXCEPTION_RANGE ? "loop" : "catch"), rangePtr->codeOffset, (rangePtr->codeOffset + rangePtr->numCodeBytes - 1)); switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: - Tcl_AppendPrintfToObj(bufferObj, "continue %d, break %d\n", + Tcl_AppendPrintfToObj(bufferObj, "continue %" TCL_SIZE_MODIFIER "u, break %" TCL_SIZE_MODIFIER "u\n", rangePtr->continueOffset, rangePtr->breakOffset); break; case CATCH_EXCEPTION_RANGE: - Tcl_AppendPrintfToObj(bufferObj, "catch %d\n", + Tcl_AppendPrintfToObj(bufferObj, "catch %" TCL_SIZE_MODIFIER "u\n", rangePtr->catchOffset); break; default: Tcl_Panic("DisassembleByteCodeObj: bad ExceptionRange type %d", rangePtr->type); @@ -441,11 +444,11 @@ } else { srcLen = TclGetInt1AtPtr(srcLengthNext); srcLengthNext++; } - Tcl_AppendPrintfToObj(bufferObj, "%s%4d: pc %d-%d, src %d-%d", + Tcl_AppendPrintfToObj(bufferObj, "%s%4" TCL_SIZE_MODIFIER "u: pc %d-%d, src %d-%d", ((i % 2)? " " : "\n "), (i+1), codeOffset, (codeOffset + codeLen - 1), srcOffset, (srcOffset + srcLen - 1)); } if (numCmds > 0) { @@ -500,11 +503,11 @@ while ((pc-codeStart) < codeOffset) { Tcl_AppendToObj(bufferObj, " ", -1); pc += FormatInstruction(codePtr, pc, bufferObj); } - Tcl_AppendPrintfToObj(bufferObj, " Command %d: ", i+1); + Tcl_AppendPrintfToObj(bufferObj, " Command %" TCL_SIZE_MODIFIER "u: ", i+1); PrintSourceToObj(bufferObj, (codePtr->source + srcOffset), TclMin(srcLen, 55)); Tcl_AppendToObj(bufferObj, "\n", -1); } if (pc < codeLimit) { @@ -540,11 +543,11 @@ unsigned char opCode = *pc; const InstructionDesc *instDesc = &tclInstructionTable[opCode]; unsigned char *codeStart = codePtr->codeStart; unsigned pcOffset = pc - codeStart; int opnd = 0, i, j, numBytes = 1; - int localCt = procPtr ? procPtr->numCompiledLocals : 0; + Tcl_Size localCt = procPtr ? procPtr->numCompiledLocals : 0; CompiledLocal *localPtr = procPtr ? procPtr->firstLocalPtr : NULL; char suffixBuffer[128]; /* Additional info to print after main opcode * and immediates. */ char *suffixSrc = NULL; Tcl_Obj *suffixObj = NULL; @@ -567,26 +570,26 @@ Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd); break; case OPERAND_UINT4: opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; if (opCode == INST_START_CMD) { - sprintf(suffixBuffer+strlen(suffixBuffer), + snprintf(suffixBuffer+strlen(suffixBuffer), sizeof(suffixBuffer) - strlen(suffixBuffer), ", %u cmds start here", opnd); } Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd); break; case OPERAND_OFFSET1: opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++; - sprintf(suffixBuffer, "pc %u", pcOffset+opnd); + snprintf(suffixBuffer, sizeof(suffixBuffer), "pc %u", pcOffset+opnd); Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_OFFSET4: opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4; if (opCode == INST_START_CMD) { - sprintf(suffixBuffer, "next cmd at pc %u", pcOffset+opnd); + snprintf(suffixBuffer, sizeof(suffixBuffer), "next cmd at pc %u", pcOffset+opnd); } else { - sprintf(suffixBuffer, "pc %u", pcOffset+opnd); + snprintf(suffixBuffer, sizeof(suffixBuffer), "pc %u", pcOffset+opnd); } Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_LIT1: opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; @@ -599,11 +602,11 @@ Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd); break; case OPERAND_AUX4: opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd); - auxPtr = &codePtr->auxDataArrayPtr[opnd]; + auxPtr = BA_AuxData_At(codePtr->auxData,opnd); break; case OPERAND_IDX4: opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4; if (opnd >= -1) { Tcl_AppendPrintfToObj(bufferObj, "%d ", opnd); @@ -621,20 +624,20 @@ opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; printLVTindex: if (localPtr != NULL) { if (opnd >= localCt) { - Tcl_Panic("FormatInstruction: bad local var index %u (%u locals)", + Tcl_Panic("FormatInstruction: bad local var index %u (%" TCL_SIZE_MODIFIER "u locals)", opnd, localCt); } for (j = 0; j < opnd; j++) { localPtr = localPtr->nextPtr; } if (TclIsVarTemporary(localPtr)) { - sprintf(suffixBuffer, "temp var %u", opnd); + snprintf(suffixBuffer, sizeof(suffixBuffer), "temp var %u", opnd); } else { - sprintf(suffixBuffer, "var "); + snprintf(suffixBuffer, sizeof(suffixBuffer), "var "); suffixSrc = localPtr->name; } } Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", opnd); break; @@ -648,14 +651,14 @@ break; } } if (suffixObj) { const char *bytes; - size_t length; + Tcl_Size length; Tcl_AppendToObj(bufferObj, "\t# ", -1); - bytes = TclGetStringFromObj(codePtr->objArrayPtr[opnd], &length); + bytes = Tcl_GetStringFromObj(codePtr->objArrayPtr[opnd], &length); PrintSourceToObj(bufferObj, bytes, TclMin(length, 40)); } else if (suffixBuffer[0]) { Tcl_AppendPrintfToObj(bufferObj, "\t# %s", suffixBuffer); if (suffixSrc) { PrintSourceToObj(bufferObj, suffixSrc, 40); @@ -686,11 +689,11 @@ TclGetInnerContext( Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj **tosPtr) { - int objc = 0, off = 0; + Tcl_Size objc = 0; Tcl_Obj *result; Interp *iPtr = (Interp *) interp; switch (*pc) { case INST_STR_LEN: @@ -755,25 +758,25 @@ if (Tcl_IsShared(result)) { Tcl_DecrRefCount(result); iPtr->innerContext = result = Tcl_NewListObj(objc + 1, NULL); Tcl_IncrRefCount(result); } else { - int len; + Tcl_Size len; /* - * Reset while keeping the list intrep as much as possible. + * Reset while keeping the list internalrep as much as possible. */ - Tcl_ListObjLength(interp, result, &len); + TclListObjLengthM(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]; + objPtr = tosPtr[1 - objc]; if (!objPtr) { Tcl_Panic("InnerContext: bad tos -- appending null object"); } if ((objPtr->refCount<=0) #ifdef TCL_MEM_DEBUG @@ -805,11 +808,11 @@ { Tcl_Obj *objPtr; TclNewObj(objPtr); TclInvalidateStringRep(objPtr); - InstNameSetIntRep(objPtr, (long) inst); + InstNameSetInternalRep(objPtr, inst); return objPtr; } /* @@ -827,16 +830,16 @@ Tcl_Obj *objPtr) { size_t inst; /* NOTE: We know this is really an unsigned char */ char *dst; - InstNameGetIntRep(objPtr, inst); + InstNameGetInternalRep(objPtr, inst); - if (inst > LAST_INST_OPCODE) { + if (inst >= LAST_INST_OPCODE) { dst = Tcl_InitStringRep(objPtr, NULL, TCL_INTEGER_SPACE + 5); - TclOOM(dst, (size_t)TCL_INTEGER_SPACE + 5); - sprintf(dst, "inst_%" TCL_Z_MODIFIER "u", inst); + TclOOM(dst, TCL_INTEGER_SPACE + 5); + snprintf(dst, TCL_INTEGER_SPACE + 5, "inst_%" TCL_Z_MODIFIER "u", inst); (void) Tcl_InitStringRep(objPtr, NULL, strlen(dst)); } else { const char *s = tclInstructionTable[inst].name; size_t len = strlen(s); dst = Tcl_InitStringRep(objPtr, s, len); @@ -856,14 +859,14 @@ static void PrintSourceToObj( Tcl_Obj *appendObj, /* The object to print the source to. */ const char *stringPtr, /* The string to print. */ - int maxChars) /* Maximum number of chars to print. */ + Tcl_Size maxChars) /* Maximum number of chars to print. */ { const char *p; - int i = 0, len; + Tcl_Size i = 0, len; if (stringPtr == NULL) { Tcl_AppendToObj(appendObj, "\"\"", -1); return; } @@ -871,11 +874,11 @@ Tcl_AppendToObj(appendObj, "\"", -1); p = stringPtr; for (; (*p != '\0') && (i < maxChars); p+=len) { int ucs4; - len = TclUtfToUCS4(p, &ucs4); + len = Tcl_UtfToUniChar(p, &ucs4); switch (ucs4) { case '"': Tcl_AppendToObj(appendObj, "\\\"", -1); i += 2; continue; @@ -939,14 +942,14 @@ { ByteCode *codePtr; Tcl_Obj *description, *literals, *variables, *instructions, *inst; Tcl_Obj *aux, *exn, *commands, *file; unsigned char *pc, *opnd, *codeOffPtr, *codeLenPtr, *srcOffPtr, *srcLenPtr; - int codeOffset, codeLength, sourceOffset, sourceLength; - int i, val, line; + int codeOffset, codeLength, sourceOffset, sourceLength, val, line; + Tcl_Size i; - ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr); /* * Get the literals from the bytecode. */ @@ -959,11 +962,11 @@ * Get the variables from the bytecode. */ TclNewObj(variables); if (codePtr->procPtr) { - int localCount = codePtr->procPtr->numCompiledLocals; + Tcl_Size localCount = codePtr->procPtr->numCompiledLocals; CompiledLocal *localPtr = codePtr->procPtr->firstLocalPtr; for (i=0 ; inextPtr) { Tcl_Obj *descriptor[2]; @@ -1109,51 +1112,57 @@ /* * Get the auxiliary data from the bytecode. */ TclNewObj(aux); - for (i=0 ; inumAuxDataItems ; i++) { - AuxData *auxData = &codePtr->auxDataArrayPtr[i]; - Tcl_Obj *auxDesc = Tcl_NewStringObj(auxData->type->name, -1); - - if (auxData->type->disassembleProc) { - Tcl_Obj *desc; - - TclNewObj(desc); - Tcl_DictObjPut(NULL, desc, Tcl_NewStringObj("name", -1), auxDesc); - auxDesc = desc; - auxData->type->disassembleProc(auxData->clientData, auxDesc, - codePtr, 0); - } else if (auxData->type->printProc) { - Tcl_Obj *desc; - - TclNewObj(desc); - auxData->type->printProc(auxData->clientData, desc, codePtr, 0); - Tcl_ListObjAppendElement(NULL, auxDesc, desc); - } - Tcl_ListObjAppendElement(NULL, aux, auxDesc); + if (codePtr->auxData) { + BP_AuxData ptr; + AuxData *auxData = BA_AuxData_First(codePtr->auxData, &ptr); + + while (auxData) { + Tcl_Obj *auxDesc = Tcl_NewStringObj(auxData->type->name, -1); + + if (auxData->type->disassembleProc) { + Tcl_Obj *desc; + + TclNewObj(desc); + Tcl_DictObjPut(NULL, desc, + Tcl_NewStringObj("name", -1), auxDesc); + auxDesc = desc; + auxData->type->disassembleProc(auxData->clientData, auxDesc, + codePtr, 0); + } else if (auxData->type->printProc) { + Tcl_Obj *desc; + + TclNewObj(desc); + auxData->type->printProc(auxData->clientData, desc, codePtr, 0); + Tcl_ListObjAppendElement(NULL, auxDesc, desc); + } + Tcl_ListObjAppendElement(NULL, aux, auxDesc); + auxData = BP_AuxData_Next(&ptr); + } } /* * Get the exception ranges from the bytecode. */ TclNewObj(exn); - for (i=0 ; inumExceptRanges ; i++) { + for (i=0 ; i<(int)codePtr->numExceptRanges ; i++) { ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i]; switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf( - "type %s level %d from %d to %d break %d continue %d", + "type %s level %" TCL_SIZE_MODIFIER "u from %" TCL_SIZE_MODIFIER "u to %" TCL_SIZE_MODIFIER "u break %" TCL_SIZE_MODIFIER "u continue %" TCL_SIZE_MODIFIER "u", "loop", rangePtr->nestingLevel, rangePtr->codeOffset, rangePtr->codeOffset + rangePtr->numCodeBytes - 1, rangePtr->breakOffset, rangePtr->continueOffset)); break; case CATCH_EXCEPTION_RANGE: Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf( - "type %s level %d from %d to %d catch %d", + "type %s level %" TCL_SIZE_MODIFIER "u from %" TCL_SIZE_MODIFIER "u to %" TCL_SIZE_MODIFIER "u catch %" TCL_SIZE_MODIFIER "u", "catch", rangePtr->nestingLevel, rangePtr->codeOffset, rangePtr->codeOffset + rangePtr->numCodeBytes - 1, rangePtr->catchOffset)); break; } @@ -1176,11 +1185,11 @@ codeOffPtr = codePtr->codeDeltaStart; codeLenPtr = codePtr->codeLengthStart; srcOffPtr = codePtr->srcDeltaStart; srcLenPtr = codePtr->srcLengthStart; codeOffset = sourceOffset = 0; - for (i=0 ; inumCommands ; i++) { + for (i=0 ; i<(int)codePtr->numCommands ; i++) { Tcl_Obj *cmd; codeOffset += Decode(codeOffPtr); codeLength = Decode(codeLenPtr); sourceOffset += Decode(srcOffPtr); @@ -1264,11 +1273,11 @@ *---------------------------------------------------------------------- */ int Tcl_DisassembleObjCmd( - ClientData clientData, /* What type of operation. */ + void *clientData, /* What type of operation. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const types[] = { @@ -1277,12 +1286,12 @@ }; enum Types { DISAS_CLASS_CONSTRUCTOR, DISAS_CLASS_DESTRUCTOR, DISAS_LAMBDA, DISAS_CLASS_METHOD, DISAS_OBJECT_METHOD, DISAS_PROC, DISAS_SCRIPT - }; - int idx, result; + } idx; + int result; Tcl_Obj *codeObjPtr = NULL; Proc *procPtr = NULL; Tcl_HashEntry *hPtr; Object *oPtr; ByteCode *codePtr; @@ -1294,11 +1303,11 @@ } if (Tcl_GetIndexFromObj(interp, objv[1], types, "type", 0, &idx)!=TCL_OK){ return TCL_ERROR; } - switch ((enum Types) idx) { + switch (idx) { case DISAS_LAMBDA: { Command cmd; Tcl_Obj *nsObjPtr; Tcl_Namespace *nsPtr; @@ -1340,11 +1349,11 @@ procPtr = TclFindProc((Interp *) interp, TclGetString(objv[2])); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't a procedure", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROC", - TclGetString(objv[2]), NULL); + TclGetString(objv[2]), (void *)NULL); return TCL_ERROR; } /* * Compile (if uncompiled) and disassemble a procedure. @@ -1365,11 +1374,11 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "script"); return TCL_ERROR; } - if (!TclHasIntRep(objv[2], &tclByteCodeType) && (TCL_OK + if (!TclHasInternalRep(objv[2], &tclByteCodeType) && (TCL_OK != TclSetByteCodeFromAny(interp, objv[2], NULL, NULL))) { return TCL_ERROR; } codeObjPtr = objv[2]; break; @@ -1390,37 +1399,37 @@ } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", - TclGetString(objv[2]), NULL); + TclGetString(objv[2]), (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", NULL); + "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", NULL); + "METHODTYPE", (void *)NULL); return TCL_ERROR; } /* * Compile if necessary. */ - if (!TclHasIntRep(procPtr->bodyPtr, &tclByteCodeType)) { + if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) { Command cmd; /* * Yes, this is ugly, but we need to pass the namespace in to the * compiler in two places. @@ -1455,37 +1464,37 @@ } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", - TclGetString(objv[2]), NULL); + TclGetString(objv[2]), (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", NULL); + "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", NULL); + "METHODTYPE", (void *)NULL); return TCL_ERROR; } /* * Compile if necessary. */ - if (!TclHasIntRep(procPtr->bodyPtr, &tclByteCodeType)) { + if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) { Command cmd; /* * Yes, this is ugly, but we need to pass the namespace in to the * compiler in two places. @@ -1520,15 +1529,15 @@ } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", - TclGetString(objv[2]), NULL); + TclGetString(objv[2]), (void *)NULL); return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods, - (char *) objv[3]); + objv[3]); goto methodBody; case DISAS_OBJECT_METHOD: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "objectName methodName"); return TCL_ERROR; @@ -1543,11 +1552,11 @@ return TCL_ERROR; } if (oPtr->methodsPtr == NULL) { goto unknownMethod; } - hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[3]); + hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[3]); /* * Compile (if necessary) and disassemble a method body. */ @@ -1555,22 +1564,22 @@ if (hPtr == NULL) { unknownMethod: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[3]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", - TclGetString(objv[3]), NULL); + TclGetString(objv[3]), (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", NULL); + "METHODTYPE", (void *)NULL); return TCL_ERROR; } - if (!TclHasIntRep(procPtr->bodyPtr, &tclByteCodeType)) { + if (!TclHasInternalRep(procPtr->bodyPtr, &tclByteCodeType)) { Command cmd; /* * Yes, this is ugly, but we need to pass the namespace in to the * compiler in two places. @@ -1594,17 +1603,17 @@ /* * Do the actual disassembly. */ - ByteCodeGetIntRep(codeObjPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(codeObjPtr, &tclByteCodeType, codePtr); if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may not disassemble prebuilt bytecode", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE", - "BYTECODE", NULL); + "BYTECODE", (void *)NULL); return TCL_ERROR; } if (clientData) { Tcl_SetObjResult(interp, DisassembleByteCodeAsDicts(codeObjPtr)); Index: generic/tclEncoding.c ================================================================== --- generic/tclEncoding.c +++ generic/tclEncoding.c @@ -1,17 +1,18 @@ /* * tclEncoding.c -- * * Contains the implementation of the encoding conversion package. * - * Copyright (c) 1996-1998 Sun Microsystems, Inc. + * Copyright © 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" +#include typedef size_t (LengthProc)(const char *src); /* * The following data structure represents an encoding, which describes how to @@ -31,23 +32,25 @@ /* 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 + 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 or 2. */ - ClientData clientData; /* Arbitrary value associated with encoding - * type. Passed to conversion functions. */ + * 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. */ + * 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; /* @@ -181,10 +184,41 @@ */ 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 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) \ + || (ENCODING_PROFILE_GET(flags_) == 0 \ + && TCL_ENCODING_PROFILE_DEFAULT == TCL_ENCODING_PROFILE_TCL8)) +#define PROFILE_STRICT(flags_) \ + ((ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_STRICT) \ + || (ENCODING_PROFILE_GET(flags_) == 0 \ + && TCL_ENCODING_PROFILE_DEFAULT == TCL_ENCODING_PROFILE_STRICT)) +#define PROFILE_REPLACE(flags_) \ + ((ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_REPLACE) \ + || (ENCODING_PROFILE_GET(flags_) == 0 \ + && TCL_ENCODING_PROFILE_DEFAULT == TCL_ENCODING_PROFILE_REPLACE)) + +#define UNICODE_REPLACE_CHAR ((Tcl_UniChar)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. */ @@ -194,17 +228,17 @@ /* * Functions used only in this module. */ static Tcl_EncodingConvertProc BinaryProc; -static Tcl_DupInternalRepProc DupEncodingIntRep; +static Tcl_DupInternalRepProc DupEncodingInternalRep; static Tcl_EncodingFreeProc EscapeFreeProc; static Tcl_EncodingConvertProc EscapeFromUtfProc; static Tcl_EncodingConvertProc EscapeToUtfProc; static void FillEncodingFileMap(void); static void FreeEncoding(Tcl_Encoding encoding); -static Tcl_FreeInternalRepProc FreeEncodingIntRep; +static Tcl_FreeInternalRepProc FreeEncodingInternalRep; static Encoding * GetTableEncoding(EscapeEncodingData *dataPtr, int state); static Tcl_Encoding LoadEncodingFile(Tcl_Interp *interp, const char *name); static Tcl_Encoding LoadTableEncoding(const char *name, int type, @@ -214,46 +248,49 @@ static Tcl_Channel OpenEncodingFileChannel(Tcl_Interp *interp, const char *name); static Tcl_EncodingFreeProc TableFreeProc; static Tcl_EncodingConvertProc TableFromUtfProc; static Tcl_EncodingConvertProc TableToUtfProc; -static size_t unilen(const char *src); +static size_t unilen(const char *src); +static size_t unilen4(const char *src); +static Tcl_EncodingConvertProc Utf32ToUtfProc; +static Tcl_EncodingConvertProc UtfToUtf32Proc; static Tcl_EncodingConvertProc Utf16ToUtfProc; static Tcl_EncodingConvertProc UtfToUtf16Proc; static Tcl_EncodingConvertProc UtfToUcs2Proc; -static int UtfToUtfProc(ClientData clientData, - const char *src, int srcLen, int flags, - Tcl_EncodingState *statePtr, char *dst, - int dstLen, int *srcReadPtr, - int *dstWrotePtr, int *dstCharsPtr, - int pureNullMode); -static Tcl_EncodingConvertProc UtfIntToUtfExtProc; -static Tcl_EncodingConvertProc UtfExtToUtfIntProc; +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 intrep. This should help the lifetime of encodings be more useful. + * of the internalrep. This should help the lifetime of encodings be more useful. * See concerns raised in [Bug 1077262]. */ static const Tcl_ObjType encodingType = { - "encoding", FreeEncodingIntRep, DupEncodingIntRep, NULL, NULL + "encoding", + FreeEncodingInternalRep, + DupEncodingInternalRep, + NULL, + NULL, + TCL_OBJTYPE_V0 }; -#define EncodingSetIntRep(objPtr, encoding) \ + +#define EncodingSetInternalRep(objPtr, encoding) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (encoding); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreIntRep((objPtr), &encodingType, &ir); \ + Tcl_StoreInternalRep((objPtr), &encodingType, &ir); \ } while (0) -#define EncodingGetIntRep(objPtr, encoding) \ +#define EncodingGetInternalRep(objPtr, encoding) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep ((objPtr), &encodingType); \ + const Tcl_ObjInternalRep *irPtr; \ + irPtr = TclFetchInternalRep ((objPtr), &encodingType); \ (encoding) = irPtr ? (Tcl_Encoding)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* @@ -282,59 +319,59 @@ Tcl_Encoding *encodingPtr) { Tcl_Encoding encoding; const char *name = TclGetString(objPtr); - EncodingGetIntRep(objPtr, encoding); + EncodingGetInternalRep(objPtr, encoding); if (encoding == NULL) { encoding = Tcl_GetEncoding(interp, name); if (encoding == NULL) { return TCL_ERROR; } - EncodingSetIntRep(objPtr, encoding); + EncodingSetInternalRep(objPtr, encoding); } *encodingPtr = Tcl_GetEncoding(NULL, name); return TCL_OK; } /* *---------------------------------------------------------------------- * - * FreeEncodingIntRep -- + * FreeEncodingInternalRep -- * * The Tcl_FreeInternalRepProc for the "encoding" Tcl_ObjType. * *---------------------------------------------------------------------- */ static void -FreeEncodingIntRep( +FreeEncodingInternalRep( Tcl_Obj *objPtr) { Tcl_Encoding encoding; - EncodingGetIntRep(objPtr, encoding); + EncodingGetInternalRep(objPtr, encoding); Tcl_FreeEncoding(encoding); } /* *---------------------------------------------------------------------- * - * DupEncodingIntRep -- + * DupEncodingInternalRep -- * * The Tcl_DupInternalRepProc for the "encoding" Tcl_ObjType. * *---------------------------------------------------------------------- */ static void -DupEncodingIntRep( +DupEncodingInternalRep( Tcl_Obj *srcPtr, Tcl_Obj *dupPtr) { Tcl_Encoding encoding = Tcl_GetEncoding(NULL, TclGetString(srcPtr)); - EncodingSetIntRep(dupPtr, encoding); + EncodingSetInternalRep(dupPtr, encoding); } /* *---------------------------------------------------------------------- * @@ -368,13 +405,13 @@ int Tcl_SetEncodingSearchPath( Tcl_Obj *searchPath) { - int dummy; + Tcl_Size dummy; - if (TCL_ERROR == Tcl_ListObjLength(NULL, searchPath, &dummy)) { + if (TCL_ERROR == TclListObjLengthM(NULL, searchPath, &dummy)) { return TCL_ERROR; } TclSetProcessGlobalValue(&encodingSearchPath, searchPath, NULL); return TCL_OK; } @@ -415,13 +452,13 @@ void TclSetLibraryPath( Tcl_Obj *path) { - int dummy; + Tcl_Size dummy; - if (TCL_ERROR == Tcl_ListObjLength(NULL, path, &dummy)) { + if (TCL_ERROR == TclListObjLengthM(NULL, path, &dummy)) { return; } TclSetProcessGlobalValue(&libraryPath, path, NULL); } @@ -451,26 +488,26 @@ */ static void FillEncodingFileMap(void) { - int i, numDirs = 0; + Tcl_Size i, numDirs = 0; Tcl_Obj *map, *searchPath; searchPath = Tcl_GetEncodingSearchPath(); Tcl_IncrRefCount(searchPath); - Tcl_ListObjLength(NULL, searchPath, &numDirs); + TclListObjLengthM(NULL, searchPath, &numDirs); map = Tcl_NewDictObj(); Tcl_IncrRefCount(map); - for (i = numDirs-1; i >= 0; i--) { + for (i = numDirs-1; i != TCL_INDEX_NONE; i--) { /* * Iterate backwards through the search path so as we overwrite * entries found, we favor files earlier on the search path. */ - int j, numFiles; + Tcl_Size j, numFiles; Tcl_Obj *directory, *matchFileList; Tcl_Obj **filev; Tcl_GlobTypeData readableFiles = { TCL_GLOB_TYPE_FILE, TCL_GLOB_PERM_R, NULL, NULL }; @@ -480,11 +517,11 @@ Tcl_IncrRefCount(directory); Tcl_IncrRefCount(matchFileList); Tcl_FSMatchInDirectory(NULL, matchFileList, directory, "*.enc", &readableFiles); - Tcl_ListObjGetElements(NULL, matchFileList, &numFiles, &filev); + TclListObjGetElementsM(NULL, matchFileList, &numFiles, &filev); for (j=0; j internal */ + void TclInitEncodingSubsystem(void) { Tcl_EncodingType type; TableEncodingData *dataPtr; unsigned size; unsigned short i; union { - char c; - short s; + char c; + short s; } isLe; + int leFlags; if (encodingsInitialized) { return; } + /* Note: This DEPENDS on TCL_ENCODING_LE being defined in least sig byte */ isLe.s = 1; + leFlags = isLe.c ? TCL_ENCODING_LE : 0; + Tcl_MutexLock(&encodingMutex); Tcl_InitHashTable(&encodingTable, TCL_STRING_KEYS); Tcl_MutexUnlock(&encodingMutex); /* @@ -551,43 +603,60 @@ type.nullSize = 1; type.clientData = NULL; tclIdentityEncoding = Tcl_CreateEncoding(&type); type.encodingName = "utf-8"; - type.toUtfProc = UtfExtToUtfIntProc; - type.fromUtfProc = UtfIntToUtfExtProc; + type.toUtfProc = UtfToUtfProc; + type.fromUtfProc = UtfToUtfProc; type.freeProc = NULL; type.nullSize = 1; + type.clientData = INT2PTR(ENCODING_UTF); + tclUtf8Encoding = Tcl_CreateEncoding(&type); type.clientData = NULL; + type.encodingName = "cesu-8"; Tcl_CreateEncoding(&type); type.toUtfProc = Utf16ToUtfProc; type.fromUtfProc = UtfToUcs2Proc; type.freeProc = NULL; type.nullSize = 2; type.encodingName = "ucs-2le"; - type.clientData = INT2PTR(1); + type.clientData = INT2PTR(TCL_ENCODING_LE); Tcl_CreateEncoding(&type); type.encodingName = "ucs-2be"; - type.clientData = INT2PTR(0); + type.clientData = NULL; Tcl_CreateEncoding(&type); type.encodingName = "ucs-2"; - type.clientData = INT2PTR(isLe.c); + 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(1); + type.clientData = INT2PTR(TCL_ENCODING_LE); Tcl_CreateEncoding(&type); type.encodingName = "utf-16be"; - type.clientData = INT2PTR(0); + type.clientData = NULL; Tcl_CreateEncoding(&type); type.encodingName = "utf-16"; - type.clientData = INT2PTR(isLe.c); + type.clientData = INT2PTR(leFlags); Tcl_CreateEncoding(&type); #ifndef TCL_NO_DEPRECATED type.encodingName = "unicode"; Tcl_CreateEncoding(&type); @@ -661,10 +730,12 @@ 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 @@ -802,11 +873,11 @@ /* *------------------------------------------------------------------------- * * Tcl_GetEncodingName -- * - * Given an encoding, return the name that was used to constuct the + * Given an encoding, return the name that was used to construct the * encoding. * * Results: * The name of the encoding. * @@ -867,11 +938,11 @@ for (hPtr = Tcl_FirstHashEntry(&encodingTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Encoding *encodingPtr = (Encoding *)Tcl_GetHashValue(hPtr); Tcl_CreateHashEntry(&table, - Tcl_NewStringObj(encodingPtr->name, -1), &dummy); + Tcl_NewStringObj(encodingPtr->name, TCL_INDEX_NONE), &dummy); } Tcl_MutexUnlock(&encodingMutex); FillEncodingFileMap(); map = TclGetProcessGlobalValue(&encodingFileMap); @@ -895,10 +966,37 @@ (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 -- @@ -988,14 +1086,16 @@ encodingPtr->toUtfProc = typePtr->toUtfProc; encodingPtr->fromUtfProc = typePtr->fromUtfProc; encodingPtr->freeProc = typePtr->freeProc; encodingPtr->nullSize = typePtr->nullSize; encodingPtr->clientData = typePtr->clientData; - if (typePtr->nullSize == 1) { - encodingPtr->lengthProc = (LengthProc *) strlen; + if (typePtr->nullSize == 2) { + encodingPtr->lengthProc = (LengthProc *) unilen; + } else if (typePtr->nullSize == 4) { + encodingPtr->lengthProc = (LengthProc *) unilen4; } else { - encodingPtr->lengthProc = (LengthProc *) unilen; + encodingPtr->lengthProc = (LengthProc *) strlen; } encodingPtr->refCount = 1; encodingPtr->hPtr = NULL; if (typePtr->encodingName) { @@ -1044,56 +1144,187 @@ * None. * *------------------------------------------------------------------------- */ +#undef Tcl_ExternalToUtfDString char * Tcl_ExternalToUtfDString( Tcl_Encoding encoding, /* The encoding for the source string, or NULL * for the default system encoding. */ const char *src, /* Source string in specified encoding. */ - size_t srcLen, /* Source string length in bytes, or -1 for + Tcl_Size srcLen, /* Source string length in bytes, or < 0 for * encoding-specific string length. */ Tcl_DString *dstPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { + Tcl_ExternalToUtfDStringEx( + NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_TCL8, dstPtr, NULL); + return Tcl_DStringValue(dstPtr); +} + + +/* + *------------------------------------------------------------------------- + * + * Tcl_ExternalToUtfDStringEx -- + * + * Convert a source buffer from the specified encoding into UTF-8. + * "flags" controls the behavior if any of the bytes in + * the source buffer are invalid or cannot be represented in utf-8. + * Possible flags values: + * target encoding. It should be composed by OR-ing the following: + * - *At most one* of TCL_ENCODING_PROFILE{DEFAULT,TCL8,STRICT} + * - TCL_ENCODING_STOPONERROR: Backward compatibility. Sets the profile + * to TCL_ENCODING_PROFILE_STRICT overriding any specified profile flags + * Any other flag bits will cause an error to be returned (for future + * compatibility) + * + * Results: + * The return value is one of + * TCL_OK: success. Converted string in *dstPtr + * TCL_ERROR: error in passed parameters. Error message in interp + * TCL_CONVERT_MULTIBYTE: source ends in truncated multibyte sequence + * TCL_CONVERT_SYNTAX: source is not conformant to encoding definition + * TCL_CONVERT_UNKNOWN: source contained a character that could not + * be represented in target encoding. + * + * Side effects: + * + * TCL_OK: The converted bytes are stored in the DString and NUL + * terminated in an encoding-specific manner. + * TCL_ERROR: an error, message is stored in the interp if not NULL. + * TCL_CONVERT_*: if errorLocPtr is NULL, an error message is stored + * in the interpreter (if not NULL). If errorLocPtr is not NULL, + * no error message is stored as it is expected the caller is + * interested in whatever is decoded so far and not treating this + * as an error condition. + * + * In addition, *dstPtr is always initialized and must be cleared + * by the caller irrespective of the return code. + * + *------------------------------------------------------------------------- + */ + +int +Tcl_ExternalToUtfDStringEx( + Tcl_Interp *interp, /* For error messages. May be NULL. */ + Tcl_Encoding encoding, /* The encoding for the source string, or NULL + * for the default system encoding. */ + const char *src, /* Source string in specified encoding. */ + Tcl_Size srcLen, /* Source string length in bytes, or < 0 for + * encoding-specific string length. */ + int flags, /* Conversion control flags. */ + Tcl_DString *dstPtr, /* Uninitialized or free DString in which the + * converted string is stored. */ + Tcl_Size *errorLocPtr) /* Where to store the error location + (or TCL_INDEX_NONE if no error). May + be NULL. */ +{ char *dst; Tcl_EncodingState state; const Encoding *encodingPtr; - int flags, result, soFar, srcRead, dstWrote, dstChars; - size_t dstLen; + int result; + Tcl_Size dstLen, soFar; + const char *srcStart = src; + /* DO FIRST - Must always be initialized before returning */ Tcl_DStringInit(dstPtr); + + if (flags & (TCL_ENCODING_START|TCL_ENCODING_END)) { + /* TODO - what other flags are illegal? - See TIP 656 */ + Tcl_SetObjResult( + interp, + Tcl_NewStringObj( + "Parameter error: TCL_ENCODING_{START,STOP} bits set in flags.", + TCL_INDEX_NONE)); + Tcl_SetErrorCode(interp, "TCL", "ENCODING", "ILLEGALFLAGS", (void *)NULL); + errno = EINVAL; + return TCL_ERROR; + } + dst = Tcl_DStringValue(dstPtr); dstLen = dstPtr->spaceAvl - 1; if (encoding == NULL) { encoding = systemEncoding; } - encodingPtr = (Encoding *) encoding; + encodingPtr = (Encoding *)encoding; if (src == NULL) { srcLen = 0; } else if (srcLen == TCL_INDEX_NONE) { srcLen = encodingPtr->lengthProc(src); } - flags = TCL_ENCODING_START | TCL_ENCODING_END; + flags |= TCL_ENCODING_START; + if (encodingPtr->toUtfProc == UtfToUtfProc) { + flags |= ENCODING_INPUT; + } while (1) { - result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen, - flags, &state, dst, dstLen, &srcRead, &dstWrote, &dstChars); - soFar = dst + dstWrote - Tcl_DStringValue(dstPtr); + int srcChunkLen, srcChunkRead; + int dstChunkLen, dstChunkWrote, dstChunkChars; - if (result != TCL_CONVERT_NOSPACE) { + 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); - return Tcl_DStringValue(dstPtr); + 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 "u", nBytesProcessed); + Tcl_SetObjResult( + interp, + Tcl_ObjPrintf("unexpected byte sequence starting at index %" + TCL_SIZE_MODIFIER "u: '\\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; } flags &= ~TCL_ENCODING_START; - src += srcRead; - srcLen -= srcRead; + srcLen -= srcChunkRead; + if (Tcl_DStringLength(dstPtr) == 0) { Tcl_DStringSetLength(dstPtr, dstLen); } Tcl_DStringSetLength(dstPtr, 2 * Tcl_DStringLength(dstPtr) + 1); dst = Tcl_DStringValue(dstPtr) + soFar; @@ -1123,21 +1354,21 @@ Tcl_ExternalToUtf( TCL_UNUSED(Tcl_Interp *), /* TODO: Re-examine this. */ Tcl_Encoding encoding, /* The encoding for the source string, or NULL * for the default system encoding. */ const char *src, /* Source string in specified encoding. */ - size_t srcLen, /* Source string length in bytes, or -1 - * for encoding-specific string length. */ + Tcl_Size srcLen, /* Source string length in bytes, or TCL_INDEX_NONE for + * encoding-specific string length. */ int flags, /* Conversion control flags. */ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state * information used during a piecewise * conversion. Contents of statePtr are * initialized and/or reset by conversion * routine under control of flags argument. */ char *dst, /* Output buffer in which converted string is * stored. */ - size_t dstLen, /* The maximum length of output buffer in + Tcl_Size dstLen, /* The maximum length of output buffer in * bytes. */ int *srcReadPtr, /* Filled with the number of bytes from the * source string that were converted. This may * be less than the original source length if * there was a problem converting some source @@ -1167,10 +1398,17 @@ 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) { @@ -1182,31 +1420,39 @@ } else if (charLimited) { maxChars = *dstCharsPtr; } if (!noTerminate) { + if (dstLen < 1) { + return TCL_CONVERT_NOSPACE; + } /* * If there are any null characters in the middle of the buffer, - * they will converted to the UTF-8 null character (\xC080). To get + * they will converted to the UTF-8 null character (\xC0\x80). To get * the actual \0 at the end of the destination buffer, we need to * append it manually. First make room for it... */ dstLen--; + } else { + if (dstLen <= 0 && srcLen > 0) { + return TCL_CONVERT_NOSPACE; + } + } + if (encodingPtr->toUtfProc == UtfToUtfProc) { + flags |= ENCODING_INPUT; } do { - int savedFlags = flags; Tcl_EncodingState savedState = *statePtr; result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr); if (*dstCharsPtr <= maxChars) { break; } dstLen = Tcl_UtfAtIndex(dst, maxChars) - dst + (TCL_UTF_MAX - 1); - flags = savedFlags; *statePtr = savedState; } while (1); if (!noTerminate) { /* ...and then append it */ @@ -1233,28 +1479,103 @@ * Side effects: * None. * *------------------------------------------------------------------------- */ - +#undef Tcl_UtfToExternalDString char * Tcl_UtfToExternalDString( Tcl_Encoding encoding, /* The encoding for the converted string, or * NULL for the default system encoding. */ const char *src, /* Source string in UTF-8. */ - size_t srcLen, /* Source string length in bytes, or -1 for + Tcl_Size srcLen, /* Source string length in bytes, or < 0 for * strlen(). */ Tcl_DString *dstPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { + Tcl_UtfToExternalDStringEx( + NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_TCL8, dstPtr, NULL); + return Tcl_DStringValue(dstPtr); +} + + +/* + *------------------------------------------------------------------------- + * + * Tcl_UtfToExternalDStringEx -- + * + * Convert a source buffer from UTF-8 to the specified encoding. + * The parameter flags controls the behavior, if any of the bytes in + * the source buffer are invalid or cannot be represented in the + * target encoding. It should be composed by OR-ing the following: + * - *At most one* of TCL_ENCODING_PROFILE_* + * - TCL_ENCODING_STOPONERROR: Backward compatibility. Sets the profile + * to TCL_ENCODING_PROFILE_STRICT overriding any specified profile flags + * + * Results: + * The return value is one of + * TCL_OK: success. Converted string in *dstPtr + * TCL_ERROR: error in passed parameters. Error message in interp + * TCL_CONVERT_MULTIBYTE: source ends in truncated multibyte sequence + * TCL_CONVERT_SYNTAX: source is not conformant to encoding definition + * TCL_CONVERT_UNKNOWN: source contained a character that could not + * be represented in target encoding. + * + * Side effects: + * + * TCL_OK: The converted bytes are stored in the DString and NUL + * terminated in an encoding-specific manner + * TCL_ERROR: an error, message is stored in the interp if not NULL. + * TCL_CONVERT_*: if errorLocPtr is NULL, an error message is stored + * in the interpreter (if not NULL). If errorLocPtr is not NULL, + * no error message is stored as it is expected the caller is + * interested in whatever is decoded so far and not treating this + * as an error condition. + * + * In addition, *dstPtr is always initialized and must be cleared + * by the caller irrespective of the return code. + * + *------------------------------------------------------------------------- + */ + +int +Tcl_UtfToExternalDStringEx( + Tcl_Interp *interp, /* For error messages. May be NULL. */ + Tcl_Encoding encoding, /* The encoding for the converted string, or + * NULL for the default system encoding. */ + const char *src, /* Source string in UTF-8. */ + Tcl_Size srcLen, /* Source string length in bytes, or < 0 for + * strlen(). */ + int flags, /* Conversion control flags. */ + Tcl_DString *dstPtr, /* Uninitialized or free DString in which the + * converted string is stored. */ + Tcl_Size *errorLocPtr) /* Where to store the error location + (or TCL_INDEX_NONE if no error). May + be NULL. */ +{ char *dst; Tcl_EncodingState state; const Encoding *encodingPtr; - int flags, result, soFar, srcRead, dstWrote, dstChars; - size_t dstLen; + int result; + const char *srcStart = src; + Tcl_Size dstLen, soFar; + /* DO FIRST - must always be initialized on return */ Tcl_DStringInit(dstPtr); + + if (flags & (TCL_ENCODING_START|TCL_ENCODING_END)) { + /* TODO - what other flags are illegal? - See TIP 656 */ + Tcl_SetObjResult( + interp, + Tcl_NewStringObj( + "Parameter error: TCL_ENCODING_{START,STOP} bits set in flags.", + TCL_INDEX_NONE)); + Tcl_SetErrorCode(interp, "TCL", "ENCODING", "ILLEGALFLAGS", (void *)NULL); + errno = EINVAL; + return TCL_ERROR; + } + dst = Tcl_DStringValue(dstPtr); dstLen = dstPtr->spaceAvl - 1; if (encoding == NULL) { encoding = systemEncoding; @@ -1264,28 +1585,82 @@ if (src == NULL) { srcLen = 0; } else if (srcLen == TCL_INDEX_NONE) { srcLen = strlen(src); } - flags = TCL_ENCODING_START | TCL_ENCODING_END; + + flags |= TCL_ENCODING_START; while (1) { + int srcChunkLen, srcChunkRead; + int dstChunkLen, dstChunkWrote, dstChunkChars; + + if (srcLen > INT_MAX) { + srcChunkLen = INT_MAX; + } else { + srcChunkLen = srcLen; + flags |= TCL_ENCODING_END; /* Last chunk */ + } + dstChunkLen = dstLen > INT_MAX ? INT_MAX : dstLen; + result = encodingPtr->fromUtfProc(encodingPtr->clientData, src, - srcLen, flags, &state, dst, dstLen, &srcRead, &dstWrote, - &dstChars); - soFar = dst + dstWrote - Tcl_DStringValue(dstPtr); - - if (result != TCL_CONVERT_NOSPACE) { - if (encodingPtr->nullSize == 2) { - Tcl_DStringSetLength(dstPtr, soFar + 1); - } - Tcl_DStringSetLength(dstPtr, soFar); - return Tcl_DStringValue(dstPtr); + srcChunkLen, flags, &state, dst, dstChunkLen, + &srcChunkRead, &dstChunkWrote, &dstChunkChars); + soFar = dst + dstChunkWrote - Tcl_DStringValue(dstPtr); + + /* Move past the part processed in this go around */ + src += srcChunkRead; + + /* + * Keep looping in two case - + * - our destination buffer did not have enough room + * - we had not passed in all the data and error indicated fragment + * of a multibyte character + * In both cases we have to grow buffer, move the input source pointer + * and loop. Otherwise, return the result we got. + */ + if ((result != TCL_CONVERT_NOSPACE) && + !(result == TCL_CONVERT_MULTIBYTE && (flags & TCL_ENCODING_END))) { + Tcl_Size nBytesProcessed = (src - srcStart); + Tcl_Size i = soFar + encodingPtr->nullSize - 1; + /* Loop as DStringSetLength only stores one nul byte at a time */ + while (i >= soFar) { + Tcl_DStringSetLength(dstPtr, i--); + } + if (errorLocPtr) { + /* + * Do not write error message into interpreter if caller + * wants to know error location. + */ + *errorLocPtr = result == TCL_OK ? TCL_INDEX_NONE : nBytesProcessed; + } else { + /* Caller wants error message on failure */ + if (result != TCL_OK && interp != NULL) { + Tcl_Size pos = Tcl_NumUtfChars(srcStart, nBytesProcessed); + int ucs4; + char buf[TCL_INTEGER_SPACE]; + Tcl_UtfToUniChar(&srcStart[nBytesProcessed], &ucs4); + snprintf(buf, sizeof(buf), "%" TCL_SIZE_MODIFIER "u", 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; - src += srcRead; - srcLen -= srcRead; + srcLen -= srcChunkRead; + if (Tcl_DStringLength(dstPtr) == 0) { Tcl_DStringSetLength(dstPtr, dstLen); } Tcl_DStringSetLength(dstPtr, 2 * Tcl_DStringLength(dstPtr) + 1); dst = Tcl_DStringValue(dstPtr) + soFar; @@ -1315,21 +1690,21 @@ Tcl_UtfToExternal( TCL_UNUSED(Tcl_Interp *), /* TODO: Re-examine this. */ Tcl_Encoding encoding, /* The encoding for the converted string, or * NULL for the default system encoding. */ const char *src, /* Source string in UTF-8. */ - size_t srcLen, /* Source string length in bytes, or -1 - * for strlen(). */ + Tcl_Size srcLen, /* Source string length in bytes, or TCL_INDEX_NONE for + * strlen(). */ int flags, /* Conversion control flags. */ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state * information used during a piecewise * conversion. Contents of statePtr are * initialized and/or reset by conversion * routine under control of flags argument. */ char *dst, /* Output buffer in which converted string * is stored. */ - size_t dstLen, /* The maximum length of output buffer in + Tcl_Size dstLen, /* The maximum length of output buffer in * bytes. */ int *srcReadPtr, /* Filled with the number of bytes from the * source string that were converted. This may * be less than the original source length if * there was a problem converting some source @@ -1356,10 +1731,17 @@ 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) { @@ -1367,18 +1749,22 @@ } if (dstCharsPtr == NULL) { dstCharsPtr = &dstChars; } + if (dstLen < encodingPtr->nullSize) { + return TCL_CONVERT_NOSPACE; + } dstLen -= encodingPtr->nullSize; result = encodingPtr->fromUtfProc(encodingPtr->clientData, src, srcLen, - flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, - dstCharsPtr); - if (encodingPtr->nullSize == 2) { - dst[*dstWrotePtr + 1] = '\0'; - } - dst[*dstWrotePtr] = '\0'; + 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; } /* @@ -1397,18 +1783,19 @@ * returned later by [info nameofexecutable]. * *--------------------------------------------------------------------------- */ #undef Tcl_FindExecutable -void +const char * Tcl_FindExecutable( const char *argv0) /* The value of the application's argv[0] * (native). */ { - Tcl_InitSubsystems(); + const char *version = Tcl_InitSubsystems(); TclpSetInitialEncodings(); TclpFindExecutable(argv0); + return version; } /* *--------------------------------------------------------------------------- * @@ -1432,21 +1819,21 @@ 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 *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; - int i, numDirs; + Tcl_Size i, numDirs; - Tcl_ListObjGetElements(NULL, searchPath, &numDirs, &dir); + TclListObjGetElementsM(NULL, searchPath, &numDirs, &dir); Tcl_IncrRefCount(nameObj); - Tcl_AppendToObj(fileNameObj, ".enc", -1); + 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. @@ -1515,11 +1902,11 @@ } if ((NULL == chan) && (interp != NULL)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown encoding \"%s\"", name)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, (void *)NULL); } Tcl_DecrRefCount(fileNameObj); Tcl_DecrRefCount(nameObj); Tcl_DecrRefCount(searchPath); @@ -1590,11 +1977,11 @@ break; } if ((encoding == NULL) && (interp != NULL)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid encoding file \"%s\"", name)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, (void *)NULL); } Tcl_CloseEx(NULL, chan, 0); return encoding; } @@ -1703,11 +2090,11 @@ TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); for (i = 0; i < numPages; i++) { int ch; const char *p; - size_t expected = 3 + 16 * (16 * 4 + 1); + Tcl_Size expected = 3 + 16 * (16 * 4 + 1); if (Tcl_ReadChars(chan, objPtr, expected, 0) != expected) { return NULL; } p = TclGetString(objPtr); @@ -1939,11 +2326,11 @@ init[0] = '\0'; final[0] = '\0'; Tcl_DStringInit(&escapeData); while (1) { - int argc; + Tcl_Size argc; const char **argv; char *line; Tcl_DString lineString; Tcl_DStringInit(&lineString); @@ -1987,11 +2374,11 @@ } est.encodingPtr = e; Tcl_DStringAppend(&escapeData, (char *) &est, sizeof(est)); } } - Tcl_Free((void *)argv); + Tcl_Free(argv); Tcl_DStringFree(&lineString); } size = offsetof(EscapeEncodingData, subTables) + Tcl_DStringLength(&escapeData); @@ -2049,11 +2436,11 @@ *------------------------------------------------------------------------- */ static int BinaryProc( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), const char *src, /* Source string (unknown encoding). */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ TCL_UNUSED(Tcl_EncodingState *), char *dst, /* Output buffer in which converted string is @@ -2074,10 +2461,11 @@ result = TCL_OK; dstLen -= TCL_UTF_MAX - 1; if (dstLen < 0) { dstLen = 0; } + flags = TclEncodingSetProfileFlags(flags); if ((flags & TCL_ENCODING_CHAR_LIMIT) && srcLen > *dstCharsPtr) { srcLen = *dstCharsPtr; } if (srcLen > dstLen) { srcLen = dstLen; @@ -2092,113 +2480,15 @@ } /* *------------------------------------------------------------------------- * - * 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. + * 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: @@ -2207,19 +2497,15 @@ *------------------------------------------------------------------------- */ static int UtfToUtfProc( - TCL_UNUSED(ClientData), + void *clientData, /* additional flags */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ - int flags, /* Conversion control flags. */ - 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. */ + 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 @@ -2228,42 +2514,354 @@ * 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 + int *dstCharsPtr) /* Filled with the number of characters that * correspond to the bytes stored in the * output buffer. */ - int pureNullMode) /* Convert embedded nulls from internal - * representation to real null-bytes or vice - * versa. Also combine or separate surrogate pairs */ { const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd; int result, numChars, charLimit = INT_MAX; - int *chPtr = (int *) statePtr; + int ch; + int profile; - if (flags & TCL_ENCODING_START) { - *statePtr = 0; - } result = TCL_OK; srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; + flags = TclEncodingSetProfileFlags(flags); 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_STRICT(profile) || + PROFILE_REPLACE(profile))) { + /* Special sequence \xC0\x80 */ + if ((PROFILE_STRICT(profile) || PROFILE_REPLACE(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 { + /* + * For output convert 0xC080 to a real null. + */ + *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 + * 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; + Tcl_UtfToUniChar(chbuf, &ch); + } + dst += Tcl_UniCharToUtf(ch, dst); + } else { + int isInvalid = 0; + size_t len = Tcl_UtfToUniChar(src, &ch); + if (flags & ENCODING_INPUT) { + if ((len < 2) && (ch != 0)) { + isInvalid = 1; + } else if ((ch > 0xFFFF) && !(flags & ENCODING_UTF)) { + isInvalid = 1; + } + if (isInvalid) { + 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 (PROFILE_STRICT(profile) && + (!(flags & ENCODING_INPUT)) && + SURROGATE(ch)) { + result = TCL_CONVERT_UNKNOWN; + src = saveSrc; + break; + } else if (PROFILE_STRICT(profile) && + (flags & ENCODING_INPUT) && + SURROGATE(ch)) { + result = TCL_CONVERT_SYNTAX; + src = saveSrc; + break; + } + 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 = TclEncodingSetProfileFlags(flags); + 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 ((src > srcClose) && (!TclUCS4Complete(src, srcEnd - src))) { + 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) { + ch = UNICODE_REPLACE_CHAR; + if (PROFILE_STRICT(flags)) { + result = TCL_CONVERT_SYNTAX; + break; + } + } else if (PROFILE_STRICT(flags) && SURROGATE(ch)) { + result = TCL_CONVERT_SYNTAX; + break; + } else if (PROFILE_REPLACE(flags) && SURROGATE(ch)) { + 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 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 += 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; + flags = TclEncodingSetProfileFlags(flags); + 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. */ @@ -2272,52 +2870,31 @@ } 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); + len = Tcl_UtfToUniChar(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 { - 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); + *dst++ = ((ch >> 24) & 0xFF); + *dst++ = ((ch >> 16) & 0xFF); + *dst++ = ((ch >> 8) & 0xFF); + *dst++ = (ch & 0xFF); } } *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; @@ -2341,11 +2918,11 @@ *------------------------------------------------------------------------- */ static int Utf16ToUtfProc( - ClientData clientData, /* != NULL means LE, == NUL means BE */ + void *clientData, /* additional flags, e.g. TCL_ENCODING_LE */ const char *src, /* Source string in Unicode. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ TCL_UNUSED(Tcl_EncodingState *), char *dst, /* Output buffer in which converted string is @@ -2365,24 +2942,35 @@ * output buffer. */ { const char *srcStart, *srcEnd; const char *dstEnd, *dstStart; int result, numChars, charLimit = INT_MAX; - unsigned short ch; + unsigned short ch = 0; + flags = TclEncodingSetProfileFlags(flags); + flags |= PTR2INT(clientData); if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } result = TCL_OK; - /* check alignment with utf-16 (2 == sizeof(UTF-16)) */ + /* + * Check alignment with utf-16 (2 == sizeof(UTF-16)) + */ + if ((srcLen % 2) != 0) { result = TCL_CONVERT_MULTIBYTE; srcLen--; } - /* If last code point is a high surrogate, we cannot handle that yet */ - if ((srcLen >= 2) && ((src[srcLen - (clientData?1:2)] & 0xFC) == 0xD8)) { + + /* + * If last code point is a high surrogate, we cannot handle that yet, + * unless we are at the end. + */ + + if (!(flags & TCL_ENCODING_END) && (srcLen >= 2) && + ((src[srcLen - ((flags & TCL_ENCODING_LE)?1:2)] & 0xFC) == 0xD8)) { result = TCL_CONVERT_MULTIBYTE; srcLen-= 2; } srcStart = src; @@ -2389,31 +2977,104 @@ srcEnd = src + srcLen; dstStart = dst; dstEnd = dst + dstLen - TCL_UTF_MAX; - for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) { + for (numChars = 0; src < srcEnd && numChars <= charLimit; src += 2, numChars++) { if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } - if (clientData) { + 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 (ch && ch < 0x80) { + + 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_UNKNOWN; + break; + } else { + /* PROFILE_REPLACE */ + dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst); + } } else { dst += Tcl_UniCharToUtf(ch, dst); } - src += sizeof(unsigned short); + } + + 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; @@ -2436,19 +3097,15 @@ *------------------------------------------------------------------------- */ static int UtfToUtf16Proc( - ClientData clientData, /* != NULL means LE, == NUL means BE */ + void *clientData, /* additional flags, e.g. TCL_ENCODING_LE */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ - Tcl_EncodingState *statePtr,/* Place for conversion routine to store state - * information used during a piecewise - * conversion. Contents of statePtr are - * initialized and/or reset by conversion - * routine under control of flags argument. */ + 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 @@ -2463,24 +3120,23 @@ * correspond to the bytes stored in the * output buffer. */ { const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd; int result, numChars; - Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr; + int ch, len; - if (flags & TCL_ENCODING_START) { - *statePtr = 0; - } srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; + flags = TclEncodingSetProfileFlags(flags); if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } dstStart = dst; - dstEnd = dst + dstLen - sizeof(Tcl_UniChar); + dstEnd = dst + dstLen - 2; /* 2 -> sizeof a UTF-16 code unit */ + flags |= PTR2INT(clientData); result = TCL_OK; for (numChars = 0; src < srcEnd; numChars++) { if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) { /* @@ -2493,42 +3149,41 @@ } 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 + len = Tcl_UtfToUniChar(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; @@ -2551,11 +3206,11 @@ *------------------------------------------------------------------------- */ static int UtfToUcs2Proc( - ClientData clientData, /* != NULL means LE, == NUL means BE */ + void *clientData, /* additional flags, e.g. TCL_ENCODING_LE */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ TCL_UNUSED(Tcl_EncodingState *), char *dst, /* Output buffer in which converted string is @@ -2573,25 +3228,24 @@ 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 + int result, numChars, len; Tcl_UniChar ch = 0; + flags = TclEncodingSetProfileFlags(flags); + flags |= PTR2INT(clientData); srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } dstStart = dst; - dstEnd = dst + dstLen - sizeof(Tcl_UniChar); + dstEnd = dst + dstLen - 2; /* 2 - size of UCS code unit */ result = TCL_OK; for (numChars = 0; src < srcEnd; numChars++) { if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) { /* @@ -2604,29 +3258,31 @@ } 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); + len = TclUtfToUniChar(src, &ch); if (ch > 0xFFFF) { - ch = 0xFFFD; + if (PROFILE_STRICT(flags)) { + result = TCL_CONVERT_UNKNOWN; + break; + } + ch = UNICODE_REPLACE_CHAR; + } + if (PROFILE_STRICT(flags) && SURROGATE(ch)) { + result = TCL_CONVERT_SYNTAX; + break; } -#endif + + src += len; /* * Need to handle this in a way that won't cause misalignment by * casting dst to a Tcl_UniChar. [Bug 1122671] */ - if (clientData) { + if (flags & TCL_ENCODING_LE) { *dst++ = (ch & 0xFF); *dst++ = (ch >> 8); } else { *dst++ = (ch >> 8); *dst++ = (ch & 0xFF); @@ -2635,11 +3291,11 @@ *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } - + /* *------------------------------------------------------------------------- * * TableToUtfProc -- * @@ -2655,11 +3311,11 @@ *------------------------------------------------------------------------- */ static int TableToUtfProc( - ClientData clientData, /* TableEncodingData that specifies + void *clientData, /* TableEncodingData that specifies * encoding. */ const char *src, /* Source string in specified encoding. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ TCL_UNUSED(Tcl_EncodingState *), @@ -2685,10 +3341,11 @@ Tcl_UniChar ch = 0; const unsigned short *const *toUnicode; const unsigned short *pageZero; TableEncodingData *dataPtr = (TableEncodingData *)clientData; + flags = TclEncodingSetProfileFlags(flags); if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } srcStart = src; srcEnd = src + srcLen; @@ -2706,43 +3363,59 @@ result = TCL_CONVERT_NOSPACE; break; } byte = *((unsigned char *) src); if (prefixBytes[byte]) { - src++; - if (src >= srcEnd) { - src--; - result = TCL_CONVERT_MULTIBYTE; - break; + 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 { + ch = (Tcl_UniChar)byte; + } + } else { + ch = toUnicode[byte][*((unsigned char *)++src)]; } - ch = toUnicode[byte][*((unsigned char *) src)]; } else { ch = pageZero[byte]; } if ((ch == 0) && (byte != 0)) { - if (flags & TCL_ENCODING_STOPONERROR) { + /* Prefix+suffix pair is invalid */ + if (PROFILE_STRICT(flags)) { result = TCL_CONVERT_SYNTAX; break; } if (prefixBytes[byte]) { src--; } - ch = (Tcl_UniChar) byte; + if (PROFILE_REPLACE(flags)) { + ch = UNICODE_REPLACE_CHAR; + } else { + ch = (Tcl_UniChar)byte; + } } /* - * Special case for 1-byte utf chars for speed. + * Special case for 1-byte Utf chars for speed. */ - if (ch && ch < 0x80) { + if ((unsigned)ch - 1 < 0x7F) { *dst++ = (char) ch; } else { dst += Tcl_UniCharToUtf(ch, dst); } src++; } + assert(src <= srcEnd); *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } @@ -2764,11 +3437,11 @@ *------------------------------------------------------------------------- */ static int TableFromUtfProc( - ClientData clientData, /* TableEncodingData that specifies + void *clientData, /* TableEncodingData that specifies * encoding. */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ TCL_UNUSED(Tcl_EncodingState *), @@ -2801,10 +3474,11 @@ fromUnicode = (const unsigned short *const *) dataPtr->fromUnicode; srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; + flags = TclEncodingSetProfileFlags(flags); if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } dstStart = dst; @@ -2820,32 +3494,23 @@ result = TCL_CONVERT_MULTIBYTE; break; } len = TclUtfToUniChar(src, &ch); -#if TCL_UTF_MAX > 3 - /* - * This prevents a crash condition. More evaluation is required for - * full support of int Tcl_UniChar. [Bug 1004065] - */ - + /* Unicode chars > +U0FFFF cannot be represented in any table encoding */ if (ch & 0xFFFF0000) { word = 0; - } else -#else - if (!len) { - word = 0; - } else -#endif + } else { word = fromUnicode[(ch >> 8)][ch & 0xFF]; + } if ((word == 0) && (ch != 0)) { - if (flags & TCL_ENCODING_STOPONERROR) { + if (PROFILE_STRICT(flags)) { result = TCL_CONVERT_UNKNOWN; break; } - word = dataPtr->fallback; + word = dataPtr->fallback; /* Both profiles REPLACE and TCL8 */ } if (prefixBytes[(word >> 8)] != 0) { if (dst + 1 > dstEnd) { result = TCL_CONVERT_NOSPACE; break; @@ -2886,11 +3551,11 @@ *------------------------------------------------------------------------- */ static int Iso88591ToUtfProc( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), const char *src, /* Source string in specified encoding. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ TCL_UNUSED(Tcl_EncodingState *), char *dst, /* Output buffer in which converted string is @@ -2911,10 +3576,11 @@ { const char *srcStart, *srcEnd; const char *dstEnd, *dstStart; int result, numChars, charLimit = INT_MAX; + flags = TclEncodingSetProfileFlags(flags); if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } srcStart = src; srcEnd = src + srcLen; @@ -2934,11 +3600,11 @@ /* * Special case for 1-byte utf chars for speed. */ - if (ch && ch < 0x80) { + if ((unsigned)ch - 1 < 0x7F) { *dst++ = (char) ch; } else { dst += Tcl_UniCharToUtf(ch, dst); } src++; @@ -2966,11 +3632,11 @@ *------------------------------------------------------------------------- */ static int Iso88591FromUtfProc( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ TCL_UNUSED(Tcl_EncodingState *), char *dst, /* Output buffer in which converted string is @@ -2995,10 +3661,11 @@ Tcl_UniChar ch = 0; srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; + flags = TclEncodingSetProfileFlags(flags); if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } dstStart = dst; @@ -3020,27 +3687,20 @@ /* * Check for illegal characters. */ - if (ch > 0xFF -#if TCL_UTF_MAX <= 3 - || ((ch >= 0xD800) && (len < 3)) -#endif - ) { - if (flags & TCL_ENCODING_STOPONERROR) { + if (ch > 0xFF) { + if (PROFILE_STRICT(flags)) { result = TCL_CONVERT_UNKNOWN; break; } -#if TCL_UTF_MAX <= 3 - if ((ch >= 0xD800) && (len < 3)) len = 4; -#endif /* * Plunge on, using '?' as a fallback character. */ - ch = (Tcl_UniChar) '?'; + ch = (Tcl_UniChar) '?'; /* Profiles TCL8 and REPLACE */ } if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; @@ -3072,11 +3732,11 @@ *--------------------------------------------------------------------------- */ static void TableFreeProc( - ClientData clientData) /* TableEncodingData that specifies + void *clientData) /* TableEncodingData that specifies * encoding. */ { TableEncodingData *dataPtr = (TableEncodingData *)clientData; /* @@ -3107,11 +3767,11 @@ *------------------------------------------------------------------------- */ static int EscapeToUtfProc( - ClientData clientData, /* EscapeEncodingData that specifies + void *clientData, /* EscapeEncodingData that specifies * encoding. */ const char *src, /* Source string in specified encoding. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state @@ -3140,10 +3800,11 @@ const unsigned short *const *tableToUnicode; const Encoding *encodingPtr; int state, result, numChars, charLimit = INT_MAX; const char *dstStart, *dstEnd; + flags = TclEncodingSetProfileFlags(flags); if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } result = TCL_OK; tablePrefixBytes = NULL; @@ -3250,16 +3911,15 @@ * 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; + 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; @@ -3321,11 +3981,11 @@ *------------------------------------------------------------------------- */ static int EscapeFromUtfProc( - ClientData clientData, /* EscapeEncodingData that specifies + void *clientData, /* EscapeEncodingData that specifies * encoding. */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ Tcl_EncodingState *statePtr,/* Place for conversion routine to store state @@ -3362,10 +4022,11 @@ result = TCL_OK; srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; + flags = TclEncodingSetProfileFlags(flags); if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } dstStart = dst; @@ -3425,11 +4086,11 @@ } } if (word == 0) { state = oldState; - if (flags & TCL_ENCODING_STOPONERROR) { + if (PROFILE_STRICT(flags)) { result = TCL_CONVERT_UNKNOWN; break; } encodingPtr = GetTableEncoding(dataPtr, state); tableDataPtr = (const TableEncodingData *)encodingPtr->clientData; @@ -3532,11 +4193,11 @@ *--------------------------------------------------------------------------- */ static void EscapeFreeProc( - ClientData clientData) /* EscapeEncodingData that specifies + void *clientData) /* EscapeEncodingData that specifies * encoding. */ { EscapeEncodingData *dataPtr = (EscapeEncodingData *)clientData; EscapeSubTable *subTablePtr; int i; @@ -3609,11 +4270,11 @@ } /* *--------------------------------------------------------------------------- * - * unilen -- + * unilen, unilen4 -- * * A helper function for the Tcl_ExternalToUtf functions. This function * is similar to strlen for double-byte characters: it returns the number * of bytes in a 0x0000 terminated string. * @@ -3633,10 +4294,23 @@ 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; } /* @@ -3667,20 +4341,20 @@ char **valuePtr, size_t *lengthPtr, Tcl_Encoding *encodingPtr) { const char *bytes; - int i, numDirs; + Tcl_Size i, numDirs, numBytes; Tcl_Obj *libPathObj, *encodingObj, *searchPathObj; TclNewLiteralStringObj(encodingObj, "encoding"); TclNewObj(searchPathObj); Tcl_IncrRefCount(encodingObj); Tcl_IncrRefCount(searchPathObj); libPathObj = TclGetLibraryPath(); Tcl_IncrRefCount(libPathObj); - Tcl_ListObjLength(NULL, libPathObj, &numDirs); + TclListObjLengthM(NULL, libPathObj, &numDirs); for (i = 0; i < numDirs; i++) { Tcl_Obj *directoryObj, *pathObj; Tcl_StatBuf stat; @@ -3697,18 +4371,180 @@ Tcl_DecrRefCount(encodingObj); *encodingPtr = libraryPath.encoding; if (*encodingPtr) { ((Encoding *)(*encodingPtr))->refCount++; } - bytes = TclGetStringFromObj(searchPathObj, lengthPtr); - *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1); - memcpy(*valuePtr, bytes, *lengthPtr + 1); + bytes = Tcl_GetStringFromObj(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) { + Tcl_Obj *errorObj; + /* This code assumes at least two profiles :-) */ + 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; +} + +/* + *------------------------------------------------------------------------ + * + * TclEncodingSetProfileFlags -- + * + * Maps the flags supported in the encoding C API's to internal flags. + * + * For backward compatibility reasons, TCL_ENCODING_STOPONERROR is + * is mapped to the TCL_ENCODING_PROFILE_STRICT overwriting any profile + * specified. + * + * If no profile or an invalid profile is specified, it is set to + * the default. + * + * Results: + * Internal encoding flag mask. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ +int TclEncodingSetProfileFlags(int flags) +{ + if (flags & TCL_ENCODING_STOPONERROR) { + ENCODING_PROFILE_SET(flags, TCL_ENCODING_PROFILE_STRICT); + } else { + int profile = ENCODING_PROFILE_GET(flags); + switch (profile) { + case TCL_ENCODING_PROFILE_TCL8: + case TCL_ENCODING_PROFILE_STRICT: + case TCL_ENCODING_PROFILE_REPLACE: + break; + case 0: /* Unspecified by caller */ + default: + ENCODING_PROFILE_SET(flags, TCL_ENCODING_PROFILE_DEFAULT); + break; + } + } + return flags; +} + +/* + *------------------------------------------------------------------------ + * + * 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: */ Index: generic/tclEnsemble.c ================================================================== --- generic/tclEnsemble.c +++ generic/tclEnsemble.c @@ -2,11 +2,11 @@ * tclEnsemble.c -- * * Contains support for ensembles (see TIP#112), which provide simple * mechanism for creating composite commands on top of namespaces. * - * Copyright (c) 2005-2013 Donal K. Fellows. + * Copyright © 2005-2013 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -19,16 +19,16 @@ 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, +static int NsEnsembleImplementationCmdNR(void *clientData, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static void BuildEnsembleConfig(EnsembleConfig *ensemblePtr); static int NsEnsembleStringOrder(const void *strPtr1, const void *strPtr2); -static void DeleteEnsembleConfig(ClientData clientData); +static void DeleteEnsembleConfig(void *clientData); static void MakeCachedEnsembleCommand(Tcl_Obj *objPtr, EnsembleConfig *ensemblePtr, Tcl_HashEntry *hPtr, Tcl_Obj *fix); static void FreeEnsembleCmdRep(Tcl_Obj *objPtr); static void DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); @@ -68,46 +68,47 @@ CONF_MAP, CONF_NAMESPACE, CONF_PARAM, CONF_PREFIX, CONF_SUBCMDS, CONF_UNKNOWN }; /* - * This structure defines a Tcl object type that contains a reference to an - * ensemble subcommand (e.g. the "length" in [string length ab]). It is used + * ensembleCmdType is a Tcl object type that contains a reference to an + * ensemble subcommand, e.g. the "length" in [string length ab]. It is used * to cache the mapping between the subcommand itself and the real command * that implements it. */ static const Tcl_ObjType ensembleCmdType = { "ensembleCommand", /* the type's name */ FreeEnsembleCmdRep, /* freeIntRepProc */ DupEnsembleCmdRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - NULL /* setFromAnyProc */ + NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; -#define ECRSetIntRep(objPtr, ecRepPtr) \ +#define ECRSetInternalRep(objPtr, ecRepPtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (ecRepPtr); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreIntRep((objPtr), &ensembleCmdType, &ir); \ + Tcl_StoreInternalRep((objPtr), &ensembleCmdType, &ir); \ } while (0) -#define ECRGetIntRep(objPtr, ecRepPtr) \ +#define ECRGetInternalRep(objPtr, ecRepPtr) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), &ensembleCmdType); \ + const Tcl_ObjInternalRep *irPtr; \ + irPtr = TclFetchInternalRep((objPtr), &ensembleCmdType); \ (ecRepPtr) = irPtr ? (EnsembleCmdRep *)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* * The internal rep for caching ensemble subcommand lookups and spelling * corrections. */ typedef struct { - size_t epoch; /* Used to confirm when the data in this + 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. */ @@ -149,11 +150,11 @@ *---------------------------------------------------------------------- */ int TclNamespaceEnsembleCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Namespace *namespacePtr; @@ -161,18 +162,19 @@ *foundNsPtr, *altFoundNsPtr, *actualCxtPtr; Tcl_Command token; Tcl_DictSearch search; Tcl_Obj *listObj; const char *simpleName; - int index, done; + enum EnsSubcmds index; + int done; - if (nsPtr == NULL || nsPtr->flags & NS_DYING) { + if (nsPtr == NULL || nsPtr->flags & NS_DEAD) { if (!Tcl_InterpDeleted(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "tried to manipulate ensemble of deleted namespace", -1)); - Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", NULL); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", (void *)NULL); } return TCL_ERROR; } if (objc < 2) { @@ -182,14 +184,15 @@ if (Tcl_GetIndexFromObj(interp, objv[1], ensembleSubcommands, "subcommand", 0, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum EnsSubcmds) index) { + switch (index) { case ENS_CREATE: { const char *name; - int len, allocatedMapFlag = 0; + Tcl_Size len; + int allocatedMapFlag = 0; /* * Defaults */ Tcl_Obj *subcmdObj = NULL; Tcl_Obj *mapObj = NULL; @@ -217,33 +220,34 @@ * 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, &index) != TCL_OK) { + "option", 0, &idx) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } - switch ((enum EnsCreateOpts) index) { + switch (idx) { case CRT_CMD: name = TclGetString(objv[1]); cxtPtr = nsPtr; continue; case CRT_SUBCMDS: - if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { + if (TclListObjLengthM(interp, objv[1], &len) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } subcmdObj = (len > 0 ? objv[1] : NULL); continue; case CRT_PARAM: - if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { + if (TclListObjLengthM(interp, objv[1], &len) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } @@ -269,11 +273,11 @@ } do { Tcl_Obj **listv; const char *cmd; - if (TclListObjGetElements(interp, listObj, &len, + if (TclListObjGetElementsM(interp, listObj, &len, &listv) != TCL_OK) { Tcl_DictObjDone(&search); if (patchedDict) { Tcl_DecrRefCount(patchedDict); } @@ -285,11 +289,11 @@ 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); + "EMPTY_TARGET", (void *)NULL); Tcl_DictObjDone(&search); if (patchedDict) { Tcl_DecrRefCount(patchedDict); } if (allocatedMapFlag) { @@ -301,11 +305,11 @@ 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_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]); @@ -334,11 +338,11 @@ } return TCL_ERROR; } continue; case CRT_UNKNOWN: - if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { + if (TclListObjLengthM(interp, objv[1], &len) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } @@ -396,17 +400,18 @@ 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, &index) != TCL_OK) { + "option", 0, &idx) != TCL_OK) { return TCL_ERROR; } - switch ((enum EnsConfigOpts) index) { + switch (idx) { case CONF_SUBCMDS: Tcl_GetEnsembleSubcommandList(NULL, token, &resultObj); if (resultObj != NULL) { Tcl_SetObjResult(interp, resultObj); } @@ -496,11 +501,12 @@ Tcl_ListObjAppendElement(NULL, resultObj, (tmpObj != NULL) ? tmpObj : Tcl_NewObj()); Tcl_SetObjResult(interp, resultObj); } else { - int len, allocatedMapFlag = 0; + 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); @@ -519,27 +525,28 @@ * 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, &index) != TCL_OK) { + "option", 0, &idx) != TCL_OK) { freeMapAndError: if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } - switch ((enum EnsConfigOpts) index) { + switch (idx) { case CONF_SUBCMDS: - if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { + if (TclListObjLengthM(interp, objv[1], &len) != TCL_OK) { goto freeMapAndError; } subcmdObj = (len > 0 ? objv[1] : NULL); continue; case CONF_PARAM: - if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { + if (TclListObjLengthM(interp, objv[1], &len) != TCL_OK) { goto freeMapAndError; } paramObj = (len > 0 ? objv[1] : NULL); continue; case CONF_MAP: { @@ -557,12 +564,12 @@ if (done) { mapObj = NULL; continue; } do { - if (TclListObjGetElements(interp, listObj, &len, - &listv) != TCL_OK) { + if (TclListObjLengthM(interp, listObj, &len + ) != TCL_OK) { Tcl_DictObjDone(&search); if (patchedDict) { Tcl_DecrRefCount(patchedDict); } goto freeMapAndError; @@ -570,11 +577,19 @@ 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); + "EMPTY_TARGET", (void *)NULL); + Tcl_DictObjDone(&search); + if (patchedDict) { + Tcl_DecrRefCount(patchedDict); + } + goto freeMapAndError; + } + if (TclListObjGetElementsM(interp, listObj, &len, + &listv) != TCL_OK) { Tcl_DictObjDone(&search); if (patchedDict) { Tcl_DecrRefCount(patchedDict); } goto freeMapAndError; @@ -583,11 +598,11 @@ 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_AppendStringsToObj(newCmd, "::", (void *)NULL); } Tcl_AppendObjToObj(newCmd, listv[0]); Tcl_ListObjReplace(NULL, newList, 0, 1, 1, &newCmd); if (patchedDict == NULL) { @@ -610,20 +625,20 @@ } case CONF_NAMESPACE: Tcl_SetObjResult(interp, Tcl_NewStringObj( "option -namespace is read-only", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "READ_ONLY", - NULL); + (void *)NULL); goto freeMapAndError; case CONF_PREFIX: if (Tcl_GetBooleanFromObj(interp, objv[1], &permitPrefix) != TCL_OK) { goto freeMapAndError; } continue; case CONF_UNKNOWN: - if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { + if (TclListObjLengthM(interp, objv[1], &len) != TCL_OK) { goto freeMapAndError; } unknownObj = (len > 0 ? objv[1] : NULL); continue; } @@ -782,17 +797,17 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); return TCL_ERROR; } if (subcmdList != NULL) { - int length; + Tcl_Size length; - if (TclListObjLength(interp, subcmdList, &length) != TCL_OK) { + if (TclListObjLengthM(interp, subcmdList, &length) != TCL_OK) { return TCL_ERROR; } if (length < 1) { subcmdList = NULL; } @@ -853,22 +868,22 @@ Tcl_Obj *paramList) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; Tcl_Obj *oldList; - int length; + 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", NULL); + 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) { + if (TclListObjLengthM(interp, paramList, &length) != TCL_OK) { return TCL_ERROR; } if (length < 1) { paramList = NULL; } @@ -934,15 +949,16 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); return TCL_ERROR; } if (mapDict != NULL) { - int size, done; + Tcl_Size size; + int done; Tcl_DictSearch search; Tcl_Obj *valuePtr; if (Tcl_DictObjSize(interp, mapDict, &size) != TCL_OK) { return TCL_ERROR; @@ -961,11 +977,11 @@ 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); + "UNQUALIFIED_TARGET", (void *)NULL); Tcl_DictObjDone(&search); return TCL_ERROR; } } @@ -1033,17 +1049,17 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); return TCL_ERROR; } if (unknownList != NULL) { - int length; + Tcl_Size length; - if (TclListObjLength(interp, unknownList, &length) != TCL_OK) { + if (TclListObjLengthM(interp, unknownList, &length) != TCL_OK) { return TCL_ERROR; } if (length < 1) { unknownList = NULL; } @@ -1099,11 +1115,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); return TCL_ERROR; } ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData; wasCompiled = ensemblePtr->flags & ENSEMBLE_COMPILE; @@ -1176,11 +1192,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); } return TCL_ERROR; } ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData; @@ -1218,11 +1234,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); } return TCL_ERROR; } ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData; @@ -1260,11 +1276,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); } return TCL_ERROR; } ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData; @@ -1301,11 +1317,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); } return TCL_ERROR; } ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData; @@ -1342,11 +1358,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); } return TCL_ERROR; } ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData; @@ -1383,11 +1399,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL); } return TCL_ERROR; } ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData; @@ -1444,11 +1460,11 @@ if (flags & TCL_LEAVE_ERR_MSG) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not an ensemble command", TclGetString(cmdNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENSEMBLE", - TclGetString(cmdNameObj), NULL); + TclGetString(cmdNameObj), (void *)NULL); } return NULL; } } @@ -1521,11 +1537,12 @@ 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; + Tcl_Size i, nameCount = 0; + int ensembleFlags = 0, hiddenLen; /* * Construct the path for the ensemble namespace and create it. */ @@ -1672,11 +1689,11 @@ *---------------------------------------------------------------------- */ int TclEnsembleImplementationCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { return Tcl_NRCallObjProc(interp, NsEnsembleImplementationCmdNR, @@ -1683,11 +1700,11 @@ clientData, objc, objv); } static int NsEnsembleImplementationCmdNR( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { EnsembleConfig *ensemblePtr = (EnsembleConfig *)clientData; @@ -1699,22 +1716,22 @@ * specified but not yet cached command * names. */ int reparseCount = 0; /* Number of reparses. */ Tcl_Obj *errorObj; /* Used for building error messages. */ Tcl_Obj *subObj; - size_t subIdx; + Tcl_Size subIdx; /* - * Must recheck objc, since numParameters might have changed. Cf. test + * Must recheck objc since numParameters might have changed. See test * namespace-53.9. */ restartEnsembleParse: subIdx = 1 + ensemblePtr->numParameters; - if ((size_t)objc < subIdx + 1) { + if (objc < subIdx + 1) { /* - * We don't have a subcommand argument. Make error message. + * No subcommand argument. Make error message. */ Tcl_DString buf; /* Message being built */ Tcl_DStringInit(&buf); @@ -1728,40 +1745,38 @@ Tcl_DStringFree(&buf); return TCL_ERROR; } - if (ensemblePtr->nsPtr->flags & NS_DYING) { + if (ensemblePtr->nsPtr->flags & NS_DEAD) { /* * Don't know how we got here, but make things give up quickly. */ if (!Tcl_InterpDeleted(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "ensemble activated for deleted namespace", -1)); - Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", NULL); + Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", (void *)NULL); } return TCL_ERROR; } /* - * Determine if the table of subcommands is right. If so, we can just look - * up in there and go straight to dispatch. + * If the table of subcommands is valid just lookup up the command there + * and go to dispatch. */ subObj = objv[subIdx]; if (ensemblePtr->epoch == ensemblePtr->nsPtr->exportLookupEpoch) { /* - * Table of subcommands is still valid; therefore there might be a - * valid cache of discovered information which we can reuse. Do the - * check here, and if we're still valid, we can jump straight to the - * part where we do the invocation of the subcommand. + * Table of subcommands is still valid so if the internal representtion + * is an ensembleCmd, just call it. */ EnsembleCmdRep *ensembleCmd; - ECRGetIntRep(subObj, ensembleCmd); + ECRGetInternalRep(subObj, ensembleCmd); if (ensembleCmd) { if (ensembleCmd->epoch == ensemblePtr->epoch && ensembleCmd->token == (Command *)ensemblePtr->token) { prefixObj = (Tcl_Obj *)Tcl_GetHashValue(ensembleCmd->hPtr); Tcl_IncrRefCount(prefixObj); @@ -1775,75 +1790,73 @@ BuildEnsembleConfig(ensemblePtr); ensemblePtr->epoch = ensemblePtr->nsPtr->exportLookupEpoch; } /* - * Look in the hashtable for the subcommand name; this is the fastest way - * of all if there is no cache in operation. + * Look in the hashtable for the named subcommand. This is the fastest + * path if there is no cache in operation. */ hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, TclGetString(subObj)); if (hPtr != NULL) { /* - * Cache for later in the subcommand object. + * Cache ensemble in the subcommand object for later. */ MakeCachedEnsembleCommand(subObj, ensemblePtr, hPtr, NULL); } else if (!(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX)) { /* - * Could not map, no prefixing, go to unknown/error handling. + * Could not map. No prefixing. Go to unknown/error handling. */ goto unknownOrAmbiguousSubcommand; } else { /* - * If we've not already confirmed the command with the hash as part of - * building our export table, we need to scan the sorted array for - * matches. + * 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 (will be an error for a non-unique - * prefix). */ + 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. */ - size_t stringLength, i; - size_t tableLength = ensemblePtr->subcommandTable.numEntries; + Tcl_Size stringLength, i; + Tcl_Size tableLength = ensemblePtr->subcommandTable.numEntries; Tcl_Obj *fix; - subcmdName = TclGetStringFromObj(subObj, &stringLength); + subcmdName = Tcl_GetStringFromObj(subObj, &stringLength); for (i=0 ; isubcommandArrayPtr[i], stringLength); if (cmp == 0) { if (fullName != NULL) { /* - * Since there's never the exact-match case to worry about - * (hash search filters this), getting here indicates that - * our subcommand is an ambiguous prefix of (at least) two - * exported subcommands, which is an error case. + * Hash search filters out the exact-match case, so getting + * here indicates that the subcommand is an ambiguous + * prefix of at least two exported subcommands, which is an + * error case. */ goto unknownOrAmbiguousSubcommand; } fullName = ensemblePtr->subcommandArrayPtr[i]; } else if (cmp < 0) { /* - * Because we are searching a sorted table, we can now stop - * searching because we have gone past anything that could - * possibly match. + * The table is sorted so stop searching because a match would + * have been found already. */ break; } } if (fullName == NULL) { /* - * The subcommand is not a prefix of anything, so bail out! + * The subcommand is not a prefix of anything. Bail out! */ goto unknownOrAmbiguousSubcommand; } hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, fullName); @@ -1869,30 +1882,28 @@ 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, + * 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 we don't do that (the cacheing of the command object used should - * help with that.) + * but don't do that because caching of the command object should help. */ { - Tcl_Obj *copyPtr; /* The actual list of words to dispatch to. + Tcl_Obj *copyPtr; /* The list of words to dispatch on. * Will be freed by the dispatch engine. */ Tcl_Obj **copyObjv; - int copyObjc, prefixObjc; + Tcl_Size copyObjc, prefixObjc; - Tcl_ListObjLength(NULL, prefixObj, &prefixObjc); + TclListObjLengthM(NULL, prefixObj, &prefixObjc); if (objc == 2) { copyPtr = TclListObjCopy(NULL, prefixObj); } else { copyPtr = Tcl_NewListObj(objc - 2 + prefixObjc, NULL); @@ -1906,12 +1917,12 @@ Tcl_IncrRefCount(copyPtr); TclNRAddCallback(interp, TclNRReleaseValues, copyPtr, NULL, NULL, NULL); TclDecrRefCount(prefixObj); /* - * Record what arguments the script sent in so that things like - * Tcl_WrongNumArgs can give the correct error message. Parameters + * Record the words of the command as given so that routines like + * Tcl_WrongNumArgs can produce the correct error message. Parameters * count both as inserted and removed arguments. */ if (TclInitRewriteEnsemble(interp, 2 + ensemblePtr->numParameters, prefixObjc + ensemblePtr->numParameters, objv)) { @@ -1922,21 +1933,20 @@ /* * Hand off to the target command. */ TclSkipTailcall(interp); - Tcl_ListObjGetElements(NULL, copyPtr, ©Objc, ©Objv); + TclListObjGetElementsM(NULL, copyPtr, ©Objc, ©Objv); ((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. + * 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)) { @@ -1948,19 +1958,19 @@ goto restartEnsembleParse; } } /* - * We cannot determine what subcommand to hand off to, so generate a - * (standard) failure message. Note the one odd case compared with - * standard ensemble-like command, which is where a namespace has no - * exported commands at all... + * Could not find a routine for the named subcommand so generate a standard + * failure message. The one odd case compared with a standard + * ensemble-like command is where a namespace has no exported commands at + * all... */ Tcl_ResetResult(interp); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND", - TclGetString(subObj), NULL); + TclGetString(subObj), (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)); @@ -1970,11 +1980,11 @@ (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; + Tcl_Size i; for (i=0 ; isubcommandTable.numEntries-1 ; i++) { Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[i], -1); Tcl_AppendToObj(errorObj, ", ", 2); } @@ -1985,11 +1995,11 @@ return TCL_ERROR; } int TclClearRootEnsemble( - TCL_UNUSED(ClientData *), + TCL_UNUSED(void **), Tcl_Interp *interp, int result) { TclResetRewriteEnsemble(interp, 1); return result; @@ -1998,12 +2008,12 @@ /* *---------------------------------------------------------------------- * * TclInitRewriteEnsemble -- * - * Applies a rewrite of arguments so that an ensemble subcommand will - * report error messages correctly for the overall command. + * Applies a rewrite of arguments so that an ensemble subcommand + * correctly reports any error messages for the overall command. * * Results: * Whether this is the first rewrite applied, a value which must be * passed to TclResetRewriteEnsemble when undoing this command's * behaviour. @@ -2015,12 +2025,12 @@ */ int TclInitRewriteEnsemble( Tcl_Interp *interp, - size_t numRemoved, - size_t numInserted, + Tcl_Size numRemoved, + Tcl_Size numInserted, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL); @@ -2028,11 +2038,11 @@ if (isRootEnsemble) { iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = numRemoved; iPtr->ensembleRewrite.numInsertedObjs = numInserted; } else { - size_t numIns = iPtr->ensembleRewrite.numInsertedObjs; + Tcl_Size numIns = iPtr->ensembleRewrite.numInsertedObjs; if (numIns < numRemoved) { iPtr->ensembleRewrite.numRemovedObjs += numRemoved - numIns; iPtr->ensembleRewrite.numInsertedObjs = numInserted; } else { @@ -2077,11 +2087,11 @@ /* *---------------------------------------------------------------------- * * TclSpellFix -- * - * Record a spelling correction that needs making in the generation of + * Records a spelling correction that needs making in the generation of * the WrongNumArgs usage message. * * Results: * None. * @@ -2091,11 +2101,11 @@ *---------------------------------------------------------------------- */ static int FreeER( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { Tcl_Obj **tmp = (Tcl_Obj **) data[0]; Tcl_Obj **store = (Tcl_Obj **) data[1]; @@ -2107,20 +2117,20 @@ void TclSpellFix( Tcl_Interp *interp, Tcl_Obj *const *objv, - int objc, - size_t badIdx, + Tcl_Size objc, + Tcl_Size badIdx, Tcl_Obj *bad, Tcl_Obj *fix) { Interp *iPtr = (Interp *) interp; Tcl_Obj *const *search; Tcl_Obj **store; - size_t idx; - size_t size; + Tcl_Size idx; + Tcl_Size size; if (iPtr->ensembleRewrite.sourceObjs == NULL) { iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = 0; iPtr->ensembleRewrite.numInsertedObjs = 0; @@ -2142,12 +2152,12 @@ search = (Tcl_Obj *const *) search[1]; } if (badIdx < iPtr->ensembleRewrite.numInsertedObjs) { /* - * Misspelled value was inserted. We cannot directly jump to the bad - * value, but have to search. + * Misspelled value was inserted. Cannot directly jump to the bad + * value. Must search. */ idx = 1; while (idx < size) { if (search[idx] == bad) { @@ -2198,10 +2208,22 @@ 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 -- @@ -2220,43 +2242,49 @@ Tcl_Obj *const * TclFetchEnsembleRoot( Tcl_Interp *interp, Tcl_Obj *const *objv, - int objc, - int *objcPtr) + Tcl_Size objc, + Tcl_Size *objcPtr) { + Tcl_Obj *const *sourceObjs; Interp *iPtr = (Interp *) interp; if (iPtr->ensembleRewrite.sourceObjs) { *objcPtr = objc + iPtr->ensembleRewrite.numRemovedObjs - iPtr->ensembleRewrite.numInsertedObjs; - return iPtr->ensembleRewrite.sourceObjs; + 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; } /* * ---------------------------------------------------------------------- * - * EnsmebleUnknownCallback -- + * EnsembleUnknownCallback -- * - * Helper for the ensemble engine that handles the procesing of unknown - * callbacks. See the user documentation of the ensemble unknown handler - * for details; this function is only ever called when such a function is - * defined, and is only ever called once per ensemble dispatch (i.e. if a - * reparse still fails, this isn't called again). + * Helper for the ensemble engine. Calls the routine registered for + * "ensemble unknown" case. See the user documentation of the + * ensemble unknown handler for details. Only called when such a + * function is defined, and is only called once per ensemble dispatch. + * I.e. even if a reparse still fails, this isn't called again. * * Results: * TCL_OK - *prefixObjPtr contains the command words to dispatch * to. - * TCL_CONTINUE - Need to reparse (*prefixObjPtr is invalid). - * TCL_ERROR - Something went wrong! Error message in interpreter. + * TCL_CONTINUE - Need to reparse, i.e. *prefixObjPtr is invalid + * TCL_ERROR - Something went wrong. Error message in interpreter. * * Side effects: - * Calls the Tcl interpreter, so arbitrary. + * Arbitrary, due to evaluation of script provided by client. * * ---------------------------------------------------------------------- */ static inline int @@ -2265,32 +2293,33 @@ EnsembleConfig *ensemblePtr, int objc, Tcl_Obj *const objv[], Tcl_Obj **prefixObjPtr) { - int paramc, i, result, prefixObjc; + Tcl_Size paramc; + int result; + Tcl_Size i, prefixObjc; Tcl_Obj **paramv, *unknownCmd, *ensObj; /* - * Create the unknown command callback to determine what to do. + * Create the "unknown" command callback to determine what to do. */ unknownCmd = Tcl_DuplicateObj(ensemblePtr->unknownHandler); TclNewObj(ensObj); Tcl_GetCommandFullName(interp, ensemblePtr->token, ensObj); Tcl_ListObjAppendElement(NULL, unknownCmd, ensObj); - for (i=1 ; iflags & 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); + (void *)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. + * 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); - /* - * Namespace is still there. Check if the result is a valid list. If - * it is, and it is non-empty, that list is what we are using as our - * replacement. - */ + /* A non-empty list is the replacement command. */ - if (TclListObjLength(interp, *prefixObjPtr, &prefixObjc) != TCL_OK) { + if (TclListObjLengthM(interp, *prefixObjPtr, &prefixObjc) != TCL_OK) { TclDecrRefCount(*prefixObjPtr); Tcl_AddErrorInfo(interp, "\n while parsing result of " "ensemble unknown subcommand handler"); return TCL_ERROR; } @@ -2333,19 +2357,19 @@ if (prefixObjc > 0) { return TCL_OK; } /* - * Namespace alive & empty result => reparse. + * Empty result => reparse. */ TclDecrRefCount(*prefixObjPtr); return TCL_CONTINUE; } /* - * Oh no! An exceptional result. Convert to an error. + * Convert exceptional result to an error. */ if (!Tcl_InterpDeleted(interp)) { if (result != TCL_ERROR) { Tcl_ResetResult(interp); @@ -2366,11 +2390,11 @@ } Tcl_AddErrorInfo(interp, "\n result of " "ensemble unknown subcommand handler: "); Tcl_AppendObjToErrorInfo(interp, unknownCmd); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_RESULT", - NULL); + (void *)NULL); } else { Tcl_AddErrorInfo(interp, "\n (ensemble unknown subcommand handler)"); } } @@ -2381,20 +2405,20 @@ /* *---------------------------------------------------------------------- * * 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.) + * 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 + * None. * * Side effects: - * Alters the internal representation of the first object parameter. + * Converts the internal representation of the given object to an + * ensembleCmd. * *---------------------------------------------------------------------- */ static void @@ -2404,24 +2428,23 @@ Tcl_HashEntry *hPtr, Tcl_Obj *fix) { EnsembleCmdRep *ensembleCmd; - ECRGetIntRep(objPtr, ensembleCmd); + ECRGetInternalRep(objPtr, ensembleCmd); if (ensembleCmd) { TclCleanupCommandMacro(ensembleCmd->token); if (ensembleCmd->fix) { Tcl_DecrRefCount(ensembleCmd->fix); } } else { /* - * Kill the old internal rep, and replace it with a brand new one of - * our own. + * Replace any old internal representation with a new one. */ ensembleCmd = (EnsembleCmdRep *)Tcl_Alloc(sizeof(EnsembleCmdRep)); - ECRSetIntRep(objPtr, ensembleCmd); + ECRSetInternalRep(objPtr, ensembleCmd); } /* * Populate the internal rep. */ @@ -2439,21 +2462,20 @@ /* *---------------------------------------------------------------------- * * 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. + * 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. + * Memory is eventually deallocated. * *---------------------------------------------------------------------- */ static void @@ -2476,19 +2498,16 @@ Tcl_DeleteHashTable(hash); } static void DeleteEnsembleConfig( - ClientData clientData) + void *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. - */ + /* Unlink from the ensemble chain if it not already marked as unlinked. */ if (ensemblePtr->next != ensemblePtr) { EnsembleConfig *ensPtr = (EnsembleConfig *) nsPtr->ensembles; if (ensPtr == ensemblePtr) { @@ -2510,11 +2529,11 @@ */ ensemblePtr->flags |= ENSEMBLE_DEAD; /* - * Kill the pointer-containing fields. + * Release the fields that contain pointers. */ ClearTable(ensemblePtr); if (ensemblePtr->subcmdList != NULL) { Tcl_DecrRefCount(ensemblePtr->subcmdList); @@ -2528,14 +2547,13 @@ 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.) + * 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); } @@ -2542,35 +2560,34 @@ /* *---------------------------------------------------------------------- * * BuildEnsembleConfig -- * - * Create the internal data structures that describe how an ensemble - * looks, being a hash mapping from the full command name to the Tcl list - * that describes the implementation prefix words, and a sorted array of - * all the full command names to allow for reasonably efficient - * unambiguous prefix handling. + * Creates the internal data structures that describe how an ensemble + * looks. The structures are a hash map from the full command name to the + * Tcl list that describes the implementation prefix words, and a sorted + * array of all the full command names to allow for reasonably efficient + * handling of an unambiguous prefix. * * Results: * None. * * Side effects: * Reallocates and rebuilds the hash table and array stored at the * ensemblePtr argument. For large ensembles or large namespaces, this is - * a potentially expensive operation. + * may be an expensive operation. * *---------------------------------------------------------------------- */ static void BuildEnsembleConfig( EnsembleConfig *ensemblePtr) { - Tcl_HashSearch search; /* Used for scanning the set of commands in - * the namespace that backs up this - * ensemble. */ - size_t i, j; + 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; @@ -2577,27 +2594,27 @@ ClearTable(ensemblePtr); Tcl_InitHashTable(hash, TCL_STRING_KEYS); if (subList) { - int subc; + Tcl_Size subc; Tcl_Obj **subv, *target, *cmdObj, *cmdPrefixObj; const char *name; /* * There is a list of exactly what subcommands go in the table. - * Must determine the target for each. + * Determine the target for each. */ - Tcl_ListObjGetElements(NULL, subList, &subc, &subv); + TclListObjGetElementsM(NULL, subList, &subc, &subv); if (subList == mapDict) { /* - * Strange case where explicit list of subcommands is same value + * Unusual case where explicit list of subcommands is same value * as the dict mapping to targets. */ - for (i = 0; i < (size_t)subc; i += 2) { + 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); @@ -2617,11 +2634,11 @@ } else { /* * Usual case where we can freely act on the list and dict. */ - for (i = 0; i < (size_t)subc; i++) { + for (i = 0; i < subc; i++) { name = TclGetString(subv[i]); hPtr = Tcl_CreateHashEntry(hash, name, &isNew); if (!isNew) { continue; } @@ -2638,14 +2655,14 @@ continue; } } /* - * target was not in the dictionary so map onto the namespace. - * Note in this case that we do not guarantee that the command - * is actually there; that is the programmer's responsibility - * (or [::unknown] of course). + * Target was not in the dictionary. Map onto the namespace. + * In this case there is no guarantee that the command + * is actually there. It is the responsibility of the + * programmer (or [::unknown] of course) to provide the procedure. */ cmdObj = Tcl_NewStringObj(name, -1); cmdPrefixObj = Tcl_NewListObj(1, &cmdObj); Tcl_SetHashValue(hPtr, cmdPrefixObj); @@ -2652,13 +2669,13 @@ Tcl_IncrRefCount(cmdPrefixObj); } } } else if (mapDict) { /* - * No subcmd list, but we do have a mapping dictionary so we should - * use the keys of that. Convert the dictionary's contents into the - * form required for the ensemble's internal hashtable. + * No subcmd list, but there is a mapping dictionary, so + * use the keys of that. Convert the contents of the dictionary into the + * form required for the internal hashtable of the ensemble. */ Tcl_DictSearch dictSearch; Tcl_Obj *keyObj, *valueObj; int done; @@ -2672,95 +2689,49 @@ 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); - - for (i=0 ; insPtr->numExportPatterns ; i++) { - if (Tcl_StringMatch(nsCmdName, - ensemblePtr->nsPtr->exportArrayPtr[i])) { - hPtr = Tcl_CreateHashEntry(hash, nsCmdName, &isNew); - - /* - * Remember, hash entries have a full reference to the - * substituted part of the command (as a list) as their - * content! - */ - - if (isNew) { - Tcl_Obj *cmdObj, *cmdPrefixObj; - - TclNewObj(cmdObj); - Tcl_AppendStringsToObj(cmdObj, - ensemblePtr->nsPtr->fullName, - (ensemblePtr->nsPtr->parentPtr ? "::" : ""), - nsCmdName, NULL); - cmdPrefixObj = Tcl_NewListObj(1, &cmdObj); - Tcl_SetHashValue(hPtr, cmdPrefixObj); - Tcl_IncrRefCount(cmdPrefixObj); - } - break; - } - } - } + TclFillTableWithExports(ensemblePtr->nsPtr, hash); } 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. + * 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 array from both ends as this makes us less likely to end up with - * performance problems in qsort(), which is good. Note that doing this - * makes this code much more opaque, but the naive alternatve: + * Fill the array from both ends as this reduces the likelihood of + * performance problems in qsort(). This makes this code much more opaque, + * but the naive alternatve: * * for (hPtr=Tcl_FirstHashEntry(hash,&search),i=0 ; * hPtr!=NULL ; hPtr=Tcl_NextHashEntry(&search),i++) { * ensemblePtr->subcommandArrayPtr[i] = Tcl_GetHashKey(hash, &hPtr); * } * * can produce long runs of precisely ordered table entries when the - * commands in the namespace are declared in a sorted fashion (an ordering - * some people like) and the hashing functions (or the command names - * themselves) are fairly unfortunate. By filling from both ends, it - * requires active malice (and probably a debugger) to get qsort() to have - * awful runtime behaviour. + * commands in the namespace are declared in a sorted fashion, which is an + * ordering some people like, and the hashing functions or the command + * names themselves are fairly unfortunate. Filling from both ends means + * that it requires active malice, and probably a debugger, to get qsort() + * to have awful runtime behaviour. */ i = 0; j = hash->numEntries; hPtr = Tcl_FirstHashEntry(hash, &search); @@ -2782,12 +2753,11 @@ /* *---------------------------------------------------------------------- * * NsEnsembleStringOrder -- * - * Helper function to compare two pointers to two strings for use with - * qsort(). + * 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. * @@ -2828,11 +2798,11 @@ FreeEnsembleCmdRep( Tcl_Obj *objPtr) { EnsembleCmdRep *ensembleCmd; - ECRGetIntRep(objPtr, ensembleCmd); + ECRGetInternalRep(objPtr, ensembleCmd); TclCleanupCommandMacro(ensembleCmd->token); if (ensembleCmd->fix) { Tcl_DecrRefCount(ensembleCmd->fix); } Tcl_Free(ensembleCmd); @@ -2862,12 +2832,12 @@ Tcl_Obj *copyPtr) { EnsembleCmdRep *ensembleCmd; EnsembleCmdRep *ensembleCopy = (EnsembleCmdRep *)Tcl_Alloc(sizeof(EnsembleCmdRep)); - ECRGetIntRep(objPtr, ensembleCmd); - ECRSetIntRep(copyPtr, ensembleCopy); + ECRGetInternalRep(objPtr, ensembleCmd); + ECRSetInternalRep(copyPtr, ensembleCopy); ensembleCopy->epoch = ensembleCmd->epoch; ensembleCopy->token = ensembleCmd->token; ensembleCopy->token->refCount++; ensembleCopy->fix = ensembleCmd->fix; @@ -2901,28 +2871,28 @@ int TclCompileEnsemble( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); Tcl_Obj *mapObj, *subcmdObj, *targetCmdObj, *listObj, **elems; Tcl_Obj *replaced, *replacement; Tcl_Command ensemble = (Tcl_Command) cmdPtr; Command *oldCmdPtr = cmdPtr, *newCmdPtr; - int len, result, flags = 0, i, depth = 1, invokeAnyway = 0; + int result, flags = 0, depth = 1, invokeAnyway = 0; int ourResult = TCL_ERROR; - size_t numBytes; + Tcl_Size i, len, numBytes; const char *word; TclNewObj(replaced); Tcl_IncrRefCount(replaced); - if (parsePtr->numWords < depth + 1) { + if (parsePtr->numWords <= depth) { goto failed; } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { /* * Too hard. @@ -2983,19 +2953,19 @@ * list filters the entries in the map. */ (void) Tcl_GetEnsembleSubcommandList(NULL, ensemble, &listObj); if (listObj != NULL) { - size_t sclen; + Tcl_Size sclen; const char *str; Tcl_Obj *matchObj = NULL; - if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) { + if (TclListObjGetElementsM(NULL, listObj, &len, &elems) != TCL_OK) { goto failed; } for (i=0 ; icompileProc == TclCompileEnsemble) { tokenPtr = TokenAfter(tokenPtr); - if (parsePtr->numWords < depth + 1 + if ((int)parsePtr->numWords < depth + 1 || tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { /* * Too hard because the user has done something unpleasant like * omitting the sub-ensemble's command name or used a non-constant * name for a sub-ensemble's command name; we respond by bailing @@ -3178,11 +3148,11 @@ /* * Throw out any line information generated by the failed compile attempt. */ - while (mapPtr->nuloc - 1 > eclIndex) { + while (mapPtr->nuloc > eclIndex + 1) { mapPtr->nuloc--; Tcl_Free(mapPtr->loc[mapPtr->nuloc].line); mapPtr->loc[mapPtr->nuloc].line = NULL; } @@ -3240,23 +3210,24 @@ int TclAttemptCompileProc( Tcl_Interp *interp, Tcl_Parse *parsePtr, - int depth, + Tcl_Size depth, Command *cmdPtr, CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; - int result, i; + int result; + Tcl_Size i; Tcl_Token *saveTokenPtr = parsePtr->tokenPtr; - int savedStackDepth = envPtr->currStackDepth; - unsigned savedCodeNext = envPtr->codeNext - envPtr->codeStart; - int savedAuxDataArrayNext = envPtr->auxDataArrayNext; - int savedExceptArrayNext = envPtr->exceptArrayNext; + Tcl_Size savedStackDepth = envPtr->currStackDepth; + Tcl_Size savedCodeNext = envPtr->codeNext - envPtr->codeStart; + Tcl_Size savedAuxDataSize = BA_AuxData_Size(envPtr->auxData); + Tcl_Size savedExceptArrayNext = envPtr->exceptArrayNext; #ifdef TCL_COMPILE_DEBUG - int savedExceptDepth = envPtr->exceptDepth; + Tcl_Size savedExceptDepth = envPtr->exceptDepth; #endif if (cmdPtr->compileProc == NULL) { return TCL_ERROR; } @@ -3312,38 +3283,30 @@ if (result != TCL_OK) { ExceptionAux *auxPtr = envPtr->exceptAuxArrayPtr; for (i = 0; i < savedExceptArrayNext; i++) { while (auxPtr->numBreakTargets > 0 - && auxPtr->breakTargets[auxPtr->numBreakTargets - 1] + && (Tcl_Size) auxPtr->breakTargets[auxPtr->numBreakTargets - 1] >= savedCodeNext) { auxPtr->numBreakTargets--; } while (auxPtr->numContinueTargets > 0 - && auxPtr->continueTargets[auxPtr->numContinueTargets - 1] + && (Tcl_Size) auxPtr->continueTargets[auxPtr->numContinueTargets - 1] >= savedCodeNext) { auxPtr->numContinueTargets--; } auxPtr++; } envPtr->exceptArrayNext = savedExceptArrayNext; - if (savedAuxDataArrayNext != envPtr->auxDataArrayNext) { - AuxData *auxDataPtr = envPtr->auxDataArrayPtr; - AuxData *auxDataEnd = auxDataPtr; - - auxDataPtr += savedAuxDataArrayNext; - auxDataEnd += envPtr->auxDataArrayNext; - - while (auxDataPtr < auxDataEnd) { - if (auxDataPtr->type->freeProc != NULL) { - auxDataPtr->type->freeProc(auxDataPtr->clientData); - } - auxDataPtr++; - } - envPtr->auxDataArrayNext = savedAuxDataArrayNext; - } + while (savedAuxDataSize < BA_AuxData_Size(envPtr->auxData)) { + AuxData *auxDataPtr = BA_AuxData_Detach(envPtr->auxData); + if (auxDataPtr->type->freeProc != NULL) { + auxDataPtr->type->freeProc(auxDataPtr->clientData); + } + } + envPtr->currStackDepth = savedStackDepth; envPtr->codeNext = envPtr->codeStart + savedCodeNext; #ifdef TCL_COMPILE_DEBUG } else { /* @@ -3381,24 +3344,24 @@ { DefineLineInformation; Tcl_Token *tokPtr; Tcl_Obj *objPtr, **words; const char *bytes; - int i, numWords, cmdLit, extraLiteralFlags = LITERAL_CMD_NAME; - size_t length; + int cmdLit, extraLiteralFlags = LITERAL_CMD_NAME; + Tcl_Size i, numWords, length; /* * Push the words of the command. Take care; the command words may be * scripts that have backslashes in them, and [info frame 0] can see the * difference. Hence the call to TclContinuationsEnterDerived... */ - Tcl_ListObjGetElements(NULL, replacements, &numWords, &words); + TclListObjGetElementsM(NULL, replacements, &numWords, &words); for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords; i++, tokPtr = TokenAfter(tokPtr)) { - if (i > 0 && i < numWords+1) { - bytes = TclGetStringFromObj(words[i-1], &length); + if (i > 0 && i <= numWords) { + bytes = Tcl_GetStringFromObj(words[i-1], &length); PushLiteral(envPtr, bytes, length); continue; } SetLineInformation(i); @@ -3423,11 +3386,11 @@ * the implementation. */ TclNewObj(objPtr); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr); - bytes = TclGetStringFromObj(objPtr, &length); + bytes = Tcl_GetStringFromObj(objPtr, &length); if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) { extraLiteralFlags |= LITERAL_UNSHARED; } cmdLit = TclRegisterLiteral(envPtr, bytes, length, extraLiteralFlags); TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr); @@ -3456,20 +3419,20 @@ static int CompileBasicNArgCommand( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Obj *objPtr; TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr); - TclCompileInvocation(interp, parsePtr->tokenPtr, objPtr, + (void) TclCompileInvocation(interp, parsePtr->tokenPtr, objPtr, parsePtr->numWords, envPtr); Tcl_DecrRefCount(objPtr); return TCL_OK; } @@ -3476,11 +3439,11 @@ int TclCompileBasic0ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case @@ -3498,11 +3461,11 @@ int TclCompileBasic1ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case @@ -3520,11 +3483,11 @@ int TclCompileBasic2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case @@ -3542,11 +3505,11 @@ int TclCompileBasic3ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case @@ -3564,11 +3527,11 @@ int TclCompileBasic0Or1ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case @@ -3586,11 +3549,11 @@ int TclCompileBasic1Or2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case @@ -3608,11 +3571,11 @@ int TclCompileBasic2Or3ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case @@ -3630,11 +3593,11 @@ int TclCompileBasic0To2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case @@ -3652,11 +3615,11 @@ int TclCompileBasic1To3ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case @@ -3674,21 +3637,21 @@ int TclCompileBasicMin0ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ - if (parsePtr->numWords < 1) { + if ((int)parsePtr->numWords < 1) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } @@ -3696,21 +3659,21 @@ int TclCompileBasicMin1ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ - if (parsePtr->numWords < 2) { + if ((int)parsePtr->numWords < 2) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } @@ -3718,21 +3681,21 @@ int TclCompileBasicMin2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ - Command *cmdPtr, /* Points to defintion of command being + Command *cmdPtr, /* Points to definition of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ - if (parsePtr->numWords < 3) { + if ((int)parsePtr->numWords < 3) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } Index: generic/tclEnv.c ================================================================== --- generic/tclEnv.c +++ generic/tclEnv.c @@ -4,50 +4,57 @@ * Tcl support for environment variables, including a setenv function. * This file contains the generic portion of the environment module. It * is primarily responsible for keeping the "env" arrays in sync with the * system environment variables. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" +#include "tclBrodnik.h" + +typedef char * pchar; +TclBrodnikArray(pchar); TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ. */ #if defined(_WIN32) # define tenviron _wenviron -# define tenviron2utfdstr(string, len, dsPtr) (Tcl_DStringInit(dsPtr), \ - (char *)Tcl_Char16ToUtfDString((const unsigned short *)(string), ((((len) + 2) >> 1) - 1), (dsPtr))) -# define utf2tenvirondstr(string, len, dsPtr) (Tcl_DStringInit(dsPtr), \ - (const WCHAR *)Tcl_UtfToChar16DString((string), (len), (dsPtr))) +# define tenviron2utfdstr(str, dsPtr) (Tcl_DStringInit(dsPtr), \ + (char *)Tcl_Char16ToUtfDString((const unsigned short *)(str), -1, (dsPtr))) +# define utf2tenvirondstr(str, dsPtr) (Tcl_DStringInit(dsPtr), \ + (const WCHAR *)Tcl_UtfToChar16DString((str), -1, (dsPtr))) # define techar WCHAR # ifdef USE_PUTENV # define putenv(env) _wputenv((const wchar_t *)env) # endif #else # define tenviron environ -# define tenviron2utfdstr(tenvstr, len, dstr) \ - Tcl_ExternalToUtfDString(NULL, tenvstr, len, dstr) -# define utf2tenvirondstr(str, len, dstr) \ - Tcl_UtfToExternalDString(NULL, str, len, dstr) +# define tenviron2utfdstr(str, dsPtr) \ + Tcl_ExternalToUtfDString(NULL, str, -1, dsPtr) +# define utf2tenvirondstr(str, dsPtr) \ + Tcl_UtfToExternalDString(NULL, str, -1, dsPtr) # define techar char #endif + +/* MODULE_SCOPE */ +size_t TclEnvEpoch = 0; /* Epoch of the tcl environment + * (if changed with tcl-env). */ + static struct { - size_t cacheSize; /* Number of env strings in cache. */ - char **cache; /* Array containing all of the environment - * strings that Tcl has allocated. */ + BA_pchar *cachePtr; /* Cache of the env strings we alloc'd */ #ifndef USE_PUTENV techar **ourEnviron; /* Cache of the array that we allocate. We * need to track this in case another * subsystem swaps around the environ array * like we do. */ - size_t ourEnvironSize; /* Non-zero means that the environ array was + Tcl_Size ourEnvironSize; /* Non-zero means that the environ array was * malloced and has this many total entries * allocated to it (not all may be in use at * once). Zero means that the environment * array is in its original static state. */ #endif @@ -57,11 +64,11 @@ /* * Declarations for local functions defined in this file: */ -static char * EnvTraceProc(ClientData clientData, Tcl_Interp *interp, +static char * EnvTraceProc(void *clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); static void ReplaceString(const char *oldStr, char *newStr); MODULE_SCOPE void TclSetEnv(const char *name, const char *value); MODULE_SCOPE void TclUnsetEnv(const char *name); @@ -152,11 +159,15 @@ for (i = 0; tenviron[i] != NULL; i++) { Tcl_Obj *obj1, *obj2; const char *p1; char *p2; - p1 = tenviron2utfdstr(tenviron[i], -1, &envString); + p1 = tenviron2utfdstr(tenviron[i], &envString); + if (p1 == NULL) { + /* Ignore what cannot be decoded (should not happen) */ + continue; + } p2 = (char *)strchr(p1, '='); if (p2 == NULL) { /* * This condition seem to happen occasionally under some * versions of Solaris, or when encoding accidents swallow the @@ -246,12 +257,12 @@ const char *name, /* Name of variable whose value is to be set * (UTF-8). */ const char *value) /* New value for variable (UTF-8). */ { Tcl_DString envString; - size_t nameLength, valueLength; - size_t index, length; + Tcl_Size nameLength, valueLength; + Tcl_Size index, length; char *p, *oldValue; const techar *p2; /* * Figure out where the entry is going to go. If the name doesn't already @@ -294,13 +305,13 @@ * to other interpreters). Otherwise, when there are N interpreters * there will be N! propagations of the same value among the * interpreters. */ - oldEnv = tenviron2utfdstr(tenviron[index], -1, &envString); - if (strcmp(value, oldEnv + (length + 1)) == 0) { - Tcl_DStringFree(&envString); + oldEnv = tenviron2utfdstr(tenviron[index], &envString); + if (oldEnv == NULL || strcmp(value, oldEnv + (length + 1)) == 0) { + Tcl_DStringFree(&envString); /* OK even if oldEnv is NULL */ Tcl_MutexUnlock(&envMutex); return; } Tcl_DStringFree(&envString); @@ -317,11 +328,17 @@ valueLength = strlen(value); p = (char *)Tcl_Alloc(nameLength + valueLength + 2); memcpy(p, name, nameLength); p[nameLength] = '='; memcpy(p+nameLength+1, value, valueLength+1); - p2 = utf2tenvirondstr(p, -1, &envString); + p2 = utf2tenvirondstr(p, &envString); + if (p2 == NULL) { + /* No way to signal error from here :-( but should not happen */ + Tcl_Free(p); + Tcl_MutexUnlock(&envMutex); + return; + } /* * Copy the native string to heap memory. */ @@ -357,19 +374,10 @@ 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); - } } /* *---------------------------------------------------------------------- * @@ -404,21 +412,32 @@ if (assignment == NULL) { return 0; } /* - * First convert the native string to UTF. Then separate the string into + * First convert the native string to Utf. Then separate the string into * name and value parts, and call TclSetEnv to do all of the real work. */ - name = Tcl_ExternalToUtfDString(NULL, assignment, -1, &nameString); + name = Tcl_ExternalToUtfDString(NULL, assignment, TCL_INDEX_NONE, &nameString); value = (char *)strchr(name, '='); if ((value != NULL) && (value != name)) { value[0] = '\0'; +#if defined(_WIN32) + if (tenviron == NULL) { + /* + * When we are started from main(), the _wenviron array could + * be NULL and will be initialized by the first _wgetenv() call. + */ + + (void) _wgetenv(L"WINDIR"); + } +#endif TclSetEnv(name, value+1); } + TclEnvEpoch++; Tcl_DStringFree(&nameString); return 0; } @@ -444,11 +463,11 @@ void TclUnsetEnv( const char *name) /* Name of variable to remove (UTF-8). */ { char *oldValue; - size_t length, index; + Tcl_Size length, index; #ifdef USE_PUTENV_FOR_UNSET Tcl_DString envString; char *string; #else char **envPtr; @@ -460,11 +479,11 @@ /* * First make sure that the environment variable exists to avoid doing * needless work and to avoid recursion on the unset. */ - if (index == TCL_INDEX_NONE) { + if (index == -1) { Tcl_MutexUnlock(&envMutex); return; } /* @@ -493,11 +512,15 @@ string = (char *)Tcl_Alloc(length + 1); memcpy(string, name, length); string[length] = '\0'; #endif /* _WIN32 */ - utf2tenvirondstr(string, -1, &envString); + if (utf2tenvirondstr(string, &envString) == NULL) { + /* Should not happen except memory alloc fail. */ + Tcl_MutexUnlock(&envMutex); + return; + } string = (char *)Tcl_Realloc(string, Tcl_DStringLength(&envString) + tNTL); memcpy(string, Tcl_DStringValue(&envString), Tcl_DStringLength(&envString) + tNTL); Tcl_DStringFree(&envString); @@ -559,30 +582,32 @@ * (UTF-8). */ Tcl_DString *valuePtr) /* Uninitialized or free DString in which the * value of the environment variable is * stored. */ { - size_t length, index; + Tcl_Size length, index; const char *result; Tcl_MutexLock(&envMutex); index = TclpFindVariable(name, &length); result = NULL; - if (index != TCL_INDEX_NONE) { + if (index != -1) { Tcl_DString envStr; - result = tenviron2utfdstr(tenviron[index], -1, &envStr); - result += length; - if (*result == '=') { - result++; - Tcl_DStringInit(valuePtr); - Tcl_DStringAppend(valuePtr, result, -1); - result = Tcl_DStringValue(valuePtr); - } else { - result = NULL; - } - Tcl_DStringFree(&envStr); + result = tenviron2utfdstr(tenviron[index], &envStr); + if (result) { + result += length; + if (*result == '=') { + result++; + Tcl_DStringInit(valuePtr); + Tcl_DStringAppend(valuePtr, result, -1); + result = Tcl_DStringValue(valuePtr); + } else { + result = NULL; + } + Tcl_DStringFree(&envStr); + } } Tcl_MutexUnlock(&envMutex); return result; } @@ -607,11 +632,11 @@ *---------------------------------------------------------------------- */ static char * EnvTraceProc( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter whose "env" variable is being * modified. */ const char *name1, /* Better be "env". */ const char *name2, /* Name of variable being modified, or NULL if * whole array is being deleted (UTF-8). */ @@ -621,10 +646,11 @@ * 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. @@ -641,10 +667,11 @@ if (flags & TCL_TRACE_WRITES) { const char *value; value = Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY); TclSetEnv(name2, value); + TclEnvEpoch++; } /* * If a value is being read, call TclGetEnv to do all of the work. */ @@ -664,10 +691,11 @@ * For unset traces, let TclUnsetEnv do all the work. */ if (flags & TCL_TRACE_UNSETS) { TclUnsetEnv(name2); + TclEnvEpoch++; } return NULL; } /* @@ -691,54 +719,42 @@ 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. - */ - - for (i = 0; i < env.cacheSize; i++) { - if (env.cache[i]==oldStr || env.cache[i]==NULL) { - break; - } - } - if (i < env.cacheSize) { - /* - * Replace or delete the old value. - */ - - if (env.cache[i]) { - Tcl_Free(env.cache[i]); - } - - if (newStr) { - env.cache[i] = newStr; - } else { - for (; i < env.cacheSize-1; i++) { - env.cache[i] = env.cache[i+1]; - } - env.cache[env.cacheSize-1] = NULL; - } - } else { - /* - * We need to grow the cache in order to hold the new string. - */ - - const int growth = 5; - - env.cache = (char **)Tcl_Realloc(env.cache, - (env.cacheSize + growth) * sizeof(char *)); - env.cache[env.cacheSize] = newStr; - (void) memset(env.cache+env.cacheSize+1, 0, - (growth-1) * sizeof(char *)); - env.cacheSize += growth; + if (env.cachePtr == NULL) { + env.cachePtr = BA_pchar_Create(); + } + + if (oldStr) { + BP_pchar ptr; + pchar *p = BA_pchar_First(env.cachePtr, &ptr); + + while (p) { + if (*p == oldStr) { + pchar *lastPtr; + + Tcl_Free(*p); + + if (newStr) { + *p = newStr; + return; + } + + lastPtr = BA_pchar_Detach(env.cachePtr); + if (p != lastPtr) { + *p = *lastPtr; + } + return; + } + p = BP_pchar_Next(&ptr); + } + } + + if (newStr) { + pchar *newPtr = BA_pchar_Append(env.cachePtr); + *newPtr = newStr; } } /* *---------------------------------------------------------------------- @@ -768,32 +784,31 @@ * 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; -#ifndef USE_PUTENV - if ((env.ourEnviron != NULL)) { - Tcl_Free(env.ourEnviron); - env.ourEnviron = NULL; - } - env.ourEnvironSize = 0; -#endif - } + if (env.cachePtr) { +#ifdef PURIFY + pchar *p; + while (p = BA_pchar_Detach(env.cachePtr)) { + Tcl_Free(*p); + } +#endif + BA_pchar_Destroy(env.cachePtr); + env.cachePtr = NULL; + } +#ifndef USE_PUTENV + if (env.ourEnviron && (env.ourEnviron != environ)) { + Tcl_Free(env.ourEnviron); + } + env.ourEnviron = NULL; + env.ourEnvironSize = 0; +#endif } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tclEvent.c ================================================================== --- generic/tclEvent.c +++ generic/tclEvent.c @@ -3,19 +3,20 @@ * * This file implements some general event related interfaces including * background errors, exit handlers, and the "vwait" and "update" command * functions. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. - * Copyright (c) 2004 by Zoran Vasiljevic. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1998 Sun Microsystems, Inc. + * Copyright © 2004 Zoran Vasiljevic. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" +#include "tclUuid.h" /* * 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. @@ -46,10 +47,23 @@ 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: */ @@ -81,10 +95,12 @@ 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. */ @@ -113,10 +129,13 @@ */ 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); @@ -204,11 +223,12 @@ */ Tcl_Preserve(assocPtr); Tcl_Preserve(interp); while (assocPtr->firstBgPtr != NULL) { - int code, prefixObjc; + int code; + Tcl_Size prefixObjc; Tcl_Obj **prefixObjv, **tempObjv; /* * Note we copy the handler command prefix each pass through, so we do * support one handler setting another handler. @@ -216,11 +236,11 @@ Tcl_Obj *copyObj = TclListObjCopy(NULL, assocPtr->cmdPrefix); errPtr = assocPtr->firstBgPtr; - Tcl_ListObjGetElements(NULL, copyObj, &prefixObjc, &prefixObjv); + TclListObjGetElementsM(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); @@ -263,13 +283,17 @@ Tcl_DecrRefCount(keyPtr); Tcl_WriteChars(errChannel, "error in background error handler:\n", -1); if (valuePtr) { - Tcl_WriteObj(errChannel, valuePtr); + if (Tcl_WriteObj(errChannel, valuePtr) < 0) { + Tcl_WriteChars(errChannel, ENCODING_ERROR, -1); + } } else { - Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); + if (Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)) < 0) { + Tcl_WriteChars(errChannel, ENCODING_ERROR, -1); + } } Tcl_WriteChars(errChannel, "\n", 1); Tcl_Flush(errChannel); Tcl_DecrRefCount(options); } @@ -324,11 +348,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (void *)NULL); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, valuePtr, &level) == TCL_ERROR) { return TCL_ERROR; } @@ -337,11 +361,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (void *)NULL); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, valuePtr, &code) == TCL_ERROR) { return TCL_ERROR; } @@ -452,22 +476,26 @@ Tcl_IncrRefCount(resultPtr); if (Tcl_FindCommand(interp, "bgerror", NULL, TCL_GLOBAL_ONLY) == NULL) { Tcl_RestoreInterpState(interp, saved); - Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp, - "errorInfo", NULL, TCL_GLOBAL_ONLY)); + if (Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp, + "errorInfo", NULL, TCL_GLOBAL_ONLY)) < 0) { + Tcl_WriteChars(errChannel, ENCODING_ERROR, -1); + } Tcl_WriteChars(errChannel, "\n", -1); } else { Tcl_DiscardInterpState(saved); - Tcl_WriteChars(errChannel, - "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, "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 { @@ -569,11 +597,11 @@ * * BgErrorDeleteProc -- * * This function is associated with the "tclBgError" assoc data for an * interpreter; it is invoked when the interpreter is deleted in order to - * free the information assoicated with any pending error reports. + * free the information associated with any pending error reports. * * Results: * None. * * Side effects: @@ -937,11 +965,11 @@ Tcl_MutexUnlock(&exitMutex); /* * Warning: this function SHOULD NOT return, as there is code that depends * on Tcl_Exit never returning. In fact, we will Tcl_Panic if anyone - * returns, so critical is this dependcy. + * returns, so critical is this dependency. * * If subsystems are not (yet) initialized, proper Tcl-finalization is * impossible, so fallback to system exit, see bug-[f8a33ce3db5d8cc2]. */ @@ -1003,28 +1031,107 @@ * 2. so that they can be finalized in a known order w/o causing the * subsequent re-initialization of a subsystem in the act of shutting * down another. * * Results: - * None. + * The full Tcl version with build information. * * Side effects: * Varied, see the respective initialization routines. * *------------------------------------------------------------------------- */ -void +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 definitly calls back into + * Double check inside the mutex. There are definitely calls back into * this routine from some of the functions below. */ TclpInitLock(); if (subsystemsInitialized == 0) { @@ -1058,10 +1165,11 @@ subsystemsInitialized = 1; } TclpInitUnlock(); } TclInitNotifier(); + return stubInfo.version; } /* *---------------------------------------------------------------------- * @@ -1390,77 +1498,434 @@ 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; + 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 }; - done = 0; + 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 (!done && foundEvent) { - foundEvent = Tcl_DoOneEvent(TCL_ALL_EVENTS); + while (!timedOut && foundEvent && + ((!any && (done < numItems)) || (any && !done))) { + foundEvent = Tcl_DoOneEvent(mask); if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) { break; } if (Tcl_LimitExceeded(interp)) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewStringObj("limit exceeded", -1)); + Tcl_SetErrorCode(interp, "TCL", "EVENT", "LIMIT", (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; + } } - Tcl_UntraceVar2(interp, nameString, NULL, - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - VwaitVarProc, &done); if (!foundEvent) { Tcl_ResetResult(interp); - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't wait for variable \"%s\": would wait forever", - nameString)); - Tcl_SetErrorCode(interp, "TCL", "EVENT", "NO_SOURCES", NULL); - return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewStringObj((numItems == 0) ? + "can't wait: would wait forever" : + "can't wait for variable(s)/channel(s): would wait forever", + -1)); + Tcl_SetErrorCode(interp, "TCL", "EVENT", "NO_SOURCES", (void *)NULL); + result = TCL_ERROR; + goto done; } - if (!done) { + + if (!done && !timedOut) { /* * The interpreter's result was already set to the right error message * prior to exiting the loop above. */ + result = TCL_ERROR; + goto done; + } - return TCL_ERROR; + result = TCL_OK; + if (timeout <= 0) { + /* + * Clear out the interpreter's result, since it may have been set + * by event handlers. + */ + Tcl_ResetResult(interp); + goto done; } /* - * Clear out the interpreter's result, since it may have been set by event - * handlers. + * 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; - Tcl_ResetResult(interp); - return TCL_OK; + if (itemPtr->donePtr != NULL) { + itemPtr->donePtr[0] = 1; + itemPtr->donePtr = NULL; + } } static char * VwaitVarProc( - void *clientData, /* Pointer to integer to set to 1. */ + void *clientData, /* Pointer to vwait info record. */ Tcl_Interp *interp, /* Interpreter containing variable. */ const char *name1, /* Name of variable. */ const char *name2, /* Second part of variable name. */ TCL_UNUSED(int) /*flags*/) /* Information about what happened. */ { - int *donePtr = (int *)clientData; + VwaitItem *itemPtr = (VwaitItem *) clientData; - *donePtr = 1; + 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; } @@ -1486,25 +1951,24 @@ TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int optionIndex; int flags = 0; /* Initialized to avoid compiler warning. */ static const char *const updateOptions[] = {"idletasks", NULL}; - enum updateOptionsEnum {OPT_IDLETASKS}; + enum updateOptionsEnum {OPT_IDLETASKS} optionIndex; if (objc == 1) { flags = TCL_ALL_EVENTS|TCL_DONT_WAIT; } else if (objc == 2) { if (Tcl_GetIndexFromObj(interp, objv[1], updateOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } - switch ((enum updateOptionsEnum) optionIndex) { + switch (optionIndex) { case OPT_IDLETASKS: - flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT; + flags = TCL_IDLE_EVENTS|TCL_DONT_WAIT; break; default: Tcl_Panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions"); } } else { @@ -1588,12 +2052,12 @@ int Tcl_CreateThread( Tcl_ThreadId *idPtr, /* Return, the ID of the thread */ Tcl_ThreadCreateProc *proc, /* Main() function of the thread */ - void *clientData, /* The one argument to Main() */ - size_t stackSize, /* Size of stack for the new thread */ + void *clientData, /* The one argument to Main() */ + size_t stackSize, /* Size of stack for the new thread */ int flags) /* Flags controlling behaviour of the new * thread. */ { #if TCL_THREADS ThreadClientData *cdPtr = (ThreadClientData *)Tcl_Alloc(sizeof(ThreadClientData)); @@ -1605,10 +2069,16 @@ 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 */ } /* Index: generic/tclExecute.c ================================================================== --- generic/tclExecute.c +++ generic/tclExecute.c @@ -1,17 +1,17 @@ /* * 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 - * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. + * Copyright © 1996-1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Scriptics Corporation. + * Copyright © 2001 Kevin B. Kenny. All rights reserved. + * Copyright © 2002-2010 Miguel Sofer. + * Copyright © 2005-2007 Donal K. Fellows. + * Copyright © 2007 Daniel A. Steffen + * 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. */ @@ -109,15 +109,14 @@ */ 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 + 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() \ @@ -133,14 +132,14 @@ } while (0) #define PUSH_TAUX_OBJ(objPtr) \ do { \ if (auxObjList) { \ - objPtr->length += auxObjList->length; \ + (objPtr)->length += auxObjList->length; \ } \ - objPtr->internalRep.twoPtrValue.ptr1 = auxObjList; \ - auxObjList = objPtr; \ + (objPtr)->internalRep.twoPtrValue.ptr1 = auxObjList; \ + auxObjList = (objPtr); \ } while (0) #define POP_TAUX_OBJ() \ do { \ tmpPtr = auxObjList; \ @@ -364,11 +363,11 @@ #define OBJ_UNDER_TOS *(tosPtr-1) #define OBJ_AT_DEPTH(n) *(tosPtr-(n)) -#define CURR_DEPTH ((ptrdiff_t) (tosPtr - initTosPtr)) +#define CURR_DEPTH (tosPtr - initTosPtr) #define STACK_BASE(esPtr) ((esPtr)->stackWords - 1) /* * Macros used to trace instruction execution. The macros TRACE, @@ -377,13 +376,13 @@ */ #ifdef TCL_COMPILE_DEBUG # define TRACE(a) \ while (traceInstructions) { \ - fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, \ - (int) CURR_DEPTH, \ - (unsigned) (pc - codePtr->codeStart), \ + 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) \ @@ -393,13 +392,13 @@ } # 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), \ + 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; \ @@ -442,30 +441,30 @@ } \ } while (0) /* * Macro used in this file to save a function call for common uses of - * TclGetNumberFromObj(). The ANSI C "prototype" is: + * Tcl_GetNumberFromObj(). The ANSI C "prototype" is: * * MODULE_SCOPE int GetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, - * ClientData *ptrPtr, int *tPtr); + * void **ptrPtr, int *tPtr); */ #define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ - ((TclHasIntRep((objPtr), &tclIntType)) \ + ((TclHasInternalRep((objPtr), &tclIntType)) \ ? (*(tPtr) = TCL_NUMBER_INT, \ *(ptrPtr) = (void *) \ (&((objPtr)->internalRep.wideValue)), TCL_OK) : \ - TclHasIntRep((objPtr), &tclDoubleType) \ - ? (((TclIsNaN((objPtr)->internalRep.doubleValue)) \ + TclHasInternalRep((objPtr), &tclDoubleType) \ + ? (((isnan((objPtr)->internalRep.doubleValue)) \ ? (*(tPtr) = TCL_NUMBER_NAN) \ : (*(tPtr) = TCL_NUMBER_DOUBLE)), \ *(ptrPtr) = (void *) \ (&((objPtr)->internalRep.doubleValue)), TCL_OK) : \ (((objPtr)->bytes != NULL) && ((objPtr)->length == 0)) \ ? TCL_ERROR : \ - TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) + Tcl_GetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) /* * Macro used to make the check for type overflow more mnemonic. This works by * comparing sign bits; the rest of the word is irrelevant. The ANSI C * "prototype" (where inttype_t is any integer type) is: @@ -609,20 +608,18 @@ /* * 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[]); +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, int stackTop, + const unsigned char *pc, size_t stackTop, int checkStack); #endif /* TCL_COMPILE_DEBUG */ static ByteCode * CompileExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr); static void DeleteExecStack(ExecStack *esPtr); static void DupExprCodeInternalRep(Tcl_Obj *srcPtr, @@ -634,13 +631,13 @@ Tcl_Obj *valuePtr); static void FreeExprCodeInternalRep(Tcl_Obj *objPtr); static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc, int searchMode, ByteCode *codePtr); static const char * GetSrcInfoForPc(const unsigned char *pc, - ByteCode *codePtr, size_t *lengthPtr, - const unsigned char **pcBeg, int *cmdIdxPtr); -static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, int growth, + ByteCode *codePtr, Tcl_Size *lengthPtr, + const unsigned char **pcBeg, Tcl_Size *cmdIdxPtr); +static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, size_t growth, int move); static void IllegalExprOperandType(Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj *opndPtr); static void InitByteCodeExecution(Tcl_Interp *interp); static inline int wordSkip(void *ptr); @@ -662,11 +659,12 @@ static const Tcl_ObjType exprCodeType = { "exprcode", FreeExprCodeInternalRep, /* freeIntRepProc */ DupExprCodeInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - NULL /* setFromAnyProc */ + NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; /* * Custom object type only used in this file; values of its type should never * be seen by user scripts. @@ -673,11 +671,12 @@ */ static const Tcl_ObjType dictIteratorType = { "dictIterator", ReleaseDictIterator, - NULL, NULL, NULL + NULL, NULL, NULL, + TCL_OBJTYPE_V0 }; /* *---------------------------------------------------------------------- * @@ -699,13 +698,13 @@ ReleaseDictIterator( Tcl_Obj *objPtr) { Tcl_DictSearch *searchPtr; Tcl_Obj *dictPtr; - const Tcl_ObjIntRep *irPtr; + const Tcl_ObjInternalRep *irPtr; - irPtr = TclFetchIntRep(objPtr, &dictIteratorType); + irPtr = TclFetchInternalRep(objPtr, &dictIteratorType); assert(irPtr != NULL); /* * First kill the search, and then release the reference to the dictionary * that we were holding. @@ -791,11 +790,11 @@ ExecEnv * TclCreateExecEnv( Tcl_Interp *interp, /* Interpreter for which the execution * environment is being created. */ - size_t size) /* The initial stack size, in number of words + size_t size) /* The initial stack size, in number of words * [sizeof(Tcl_Obj*)] */ { ExecEnv *eePtr = (ExecEnv *)Tcl_Alloc(sizeof(ExecEnv)); ExecStack *esPtr = (ExecStack *)Tcl_Alloc(offsetof(ExecStack, stackWords) + size * sizeof(Tcl_Obj *)); @@ -973,19 +972,20 @@ static Tcl_Obj ** GrowEvaluationStack( ExecEnv *eePtr, /* Points to the ExecEnv with an evaluation * stack to enlarge. */ - int growth, /* How much larger than the current used + size_t growth1, /* How much larger than the current used * size. */ int move) /* 1 if move words since last marker. */ { ExecStack *esPtr = eePtr->execStackPtr, *oldPtr = NULL; size_t newBytes; - int newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr); + Tcl_Size growth = growth1; + Tcl_Size newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr); Tcl_Obj **markerPtr = esPtr->markerPtr, **memStart; - int moveWords = 0; + Tcl_Size moveWords = 0; if (move) { if (!markerPtr) { Tcl_Panic("STACK: Reallocating with no previous alloc"); } @@ -1227,11 +1227,11 @@ { Interp *iPtr = (Interp *) interp; size_t numWords; if (iPtr == NULL || iPtr->execEnvPtr == NULL) { - return (void *) Tcl_Alloc(numBytes); + return Tcl_Alloc(numBytes); } numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *); return StackAllocWords(interp, numWords); } @@ -1305,11 +1305,11 @@ return TclNRRunCallbacks(interp, TCL_OK, rootPtr); } static int CopyCallback( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { Tcl_Obj **resultPtrPtr = (Tcl_Obj **)data[0]; Tcl_Obj *resultPtr = (Tcl_Obj *)data[1]; @@ -1363,11 +1363,11 @@ return TclNRExecuteByteCode(interp, codePtr); } static int ExprObjCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_InterpState state = (Tcl_InterpState)data[0]; Tcl_Obj *resultPtr = (Tcl_Obj *)data[1]; @@ -1414,32 +1414,32 @@ /* * Get the expression ByteCode from the object. If it exists, make sure it * is valid in the current context. */ - ByteCodeGetIntRep(objPtr, &exprCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &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); + Tcl_StoreInternalRep(objPtr, &exprCodeType, NULL); codePtr = NULL; } } if (codePtr == NULL) { /* * TIP #280: No invoker (yet) - Expression compilation. */ - size_t length; - const char *string = TclGetStringFromObj(objPtr, &length); + Tcl_Size length; + const char *string = Tcl_GetStringFromObj(objPtr, &length); TclInitCompileEnv(interp, &compEnv, string, length, NULL, 0); TclCompileExpr(interp, string, length, &compEnv, 0); /* @@ -1479,20 +1479,20 @@ *---------------------------------------------------------------------- * * DupExprCodeInternalRep -- * * Part of the Tcl object type implementation for Tcl expression - * bytecode. We do not copy the bytecode intrep. Instead, we return + * bytecode. We do not copy the bytecode internalrep. Instead, we return * without setting copyPtr->typePtr, so the copy is a plain string copy * of the expression value, and if it is to be used as a compiled * expression, it will just need a recompile. * * This makes sense, because with Tcl's copy-on-write practices, the * usual (only?) time Tcl_DuplicateObj() will be called is when the copy * is about to be modified, which would invalidate any copied bytecode * anyway. The only reason it might make sense to copy the bytecode is if - * we had some modifying routines that operated directly on the intrep, + * we had some modifying routines that operated directly on the internalrep, * like we do for lists and dicts. * * Results: * None. * @@ -1531,11 +1531,11 @@ static void FreeExprCodeInternalRep( Tcl_Obj *objPtr) { ByteCode *codePtr; - ByteCodeGetIntRep(objPtr, &exprCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &exprCodeType, codePtr); assert(codePtr != NULL); TclReleaseByteCode(codePtr); } @@ -1570,11 +1570,11 @@ * If the object is not already of tclByteCodeType, compile it (and reset * the compilation flags in the interpreter; this should be done after any * compilation). Otherwise, check that it is "fresh" enough. */ - ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr); if (codePtr != NULL) { /* * Make sure the Bytecode hasn't been invalidated by, e.g., someone * redefining a command with a compile procedure (this might make the * compiled code wrong). The object needs to be recompiled if it was @@ -1631,11 +1631,11 @@ * causing 'info frame' to point to the wrong place in the sources. * * Future optimizations ... * (1) Save the location data (ExtCmdLoc) keyed by start line. In that * case we recompile once per location of the literal, but not - * continously, because the moment we have all locations we do not + * continuously, because the moment we have all locations we do not * need to recompile any longer. * * (2) Alternative: Do not recompile, tell the execution engine the * offset between saved starting line and actual one. Then modify * the users to adjust the locations they have by this offset. @@ -1716,11 +1716,11 @@ iPtr->invokeCmdFramePtr = invoker; iPtr->invokeWord = word; TclSetByteCodeFromAny(interp, objPtr, NULL, NULL); iPtr->invokeCmdFramePtr = NULL; - ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr); if (iPtr->varFramePtr->localCachePtr) { codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr; codePtr->localCachePtr->refCount++; } return codePtr; @@ -1729,21 +1729,21 @@ /* *---------------------------------------------------------------------- * * TclIncrObj -- * - * Increment an integeral value in a Tcl_Obj by an integeral value held + * Increment an integral value in a Tcl_Obj by an integral value held * in another Tcl_Obj. Caller is responsible for making sure we can * update the first object. * * Results: * TCL_ERROR if either object is non-integer, and TCL_OK otherwise. On * error, an error message is left in the interpreter (if it is not NULL, * of course). * * Side effects: - * valuePtr gets the new incrmented value. + * valuePtr gets the new incremented value. * *---------------------------------------------------------------------- */ int @@ -1750,11 +1750,11 @@ TclIncrObj( Tcl_Interp *interp, Tcl_Obj *valuePtr, Tcl_Obj *incrPtr) { - ClientData ptr1, ptr2; + void *ptr1, *ptr2; int type1, type2; mp_int value, incr; mp_err err; if (Tcl_IsShared(valuePtr)) { @@ -1798,11 +1798,11 @@ if ((type1 == TCL_NUMBER_INT) && (type2 == TCL_NUMBER_INT)) { Tcl_WideInt w1, w2, sum; w1 = *((const Tcl_WideInt *)ptr1); w2 = *((const Tcl_WideInt *)ptr2); - sum = w1 + w2; + sum = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2); /* * Check for overflow. */ @@ -1848,11 +1848,11 @@ TEBCdata *tdPtr, const unsigned char *pc, int objc, Tcl_Obj **objv) { - int cmd; + Tcl_Size cmd; if (GetSrcInfoForPc(pc, codePtr, NULL, NULL, &cmd)) { TclArgumentBCEnter(interp, objv, objc, codePtr, &tdPtr->cmdFrame, cmd, pc - codePtr->codeStart); } @@ -1875,25 +1875,25 @@ * Almost certainly, depending on the ByteCode's instructions. * *---------------------------------------------------------------------- */ #define bcFramePtr (&TD->cmdFrame) -#define initCatchTop ((ptrdiff_t *) (TD->stack-1)) -#define initTosPtr ((Tcl_Obj **) (initCatchTop+codePtr->maxExceptDepth)) +#define initCatchTop (TD->stack-1) +#define initTosPtr (initCatchTop+codePtr->maxExceptDepth) #define esPtr (iPtr->execEnvPtr->execStackPtr) int TclNRExecuteByteCode( Tcl_Interp *interp, /* Token for command interpreter. */ ByteCode *codePtr) /* The bytecode sequence to interpret. */ { Interp *iPtr = (Interp *) interp; TEBCdata *TD; - int size = sizeof(TEBCdata) - 1 + size_t size = sizeof(TEBCdata) - 1 + (codePtr->maxStackDepth + codePtr->maxExceptDepth) * sizeof(void *); - int numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *); + size_t numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *); TclPreserveByteCode(codePtr); /* * Reserve the stack, setup the TEBCdataPtr (TD) and CallFrame @@ -1947,11 +1947,11 @@ /* * Push the callback for bytecode execution */ TclNRAddCallback(interp, TEBCresume, TD, /* pc */ NULL, - /* cleanup */ INT2PTR(0), INT2PTR(iPtr->evalFlags)); + /* cleanup */ NULL, INT2PTR(iPtr->evalFlags)); /* * Reset discard result flag - because it is applicable for this call only, * and should not affect all the nested invocations may return result. */ @@ -1960,11 +1960,11 @@ return TCL_OK; } static int TEBCresume( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { /* * Compiler cast directive - not a real variable. @@ -2046,12 +2046,12 @@ * NOTE: These are now mostly defined locally where needed. */ Tcl_Obj *objPtr, *valuePtr, *value2Ptr, *part1Ptr, *part2Ptr, *tmpPtr; Tcl_Obj **objv = NULL; - int objc = 0; - int opnd, length, pcAdjustment; + Tcl_Size length, objc = 0; + int opnd, pcAdjustment; Var *varPtr, *arrayPtr; #ifdef TCL_COMPILE_DEBUG char cmdNameBuf[21]; #endif @@ -2063,11 +2063,11 @@ TEBC_DATA_DIG(); #ifdef TCL_COMPILE_DEBUG if (!pc && (tclTraceExec >= 2)) { PrintByteCodeInfo(codePtr); - fprintf(stdout, " Starting stack top=%d\n", (int) CURR_DEPTH); + fprintf(stdout, " Starting stack top=%" TCL_T_MODIFIER "d\n", CURR_DEPTH); fflush(stdout); } #endif if (!pc) { @@ -2122,11 +2122,11 @@ /* * Push the call's object result and continue execution with the next * instruction. */ - TRACE_WITH_OBJ(("%u => ... after \"%.20s\": TCL_OK, result=", + TRACE_WITH_OBJ(("%" TCL_SIZE_MODIFIER "d => ... after \"%.20s\": TCL_OK, result=", objc, cmdNameBuf), Tcl_GetObjResult(interp)); /* * Obtain and reset interp's result to avoid possible duplications of * objects [Bug 781585]. We do not call Tcl_ResetResult to avoid any @@ -2267,11 +2267,11 @@ * Skip the stack depth check if an expansion is in progress. */ CHECK_STACK(); if (traceInstructions) { - fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (int) CURR_DEPTH); + fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER "d ", iPtr->numLevels, CURR_DEPTH); TclPrintInstruction(codePtr, pc); fflush(stdout); } #endif /* TCL_COMPILE_DEBUG */ @@ -2366,11 +2366,11 @@ TRACE_APPEND(("\n")); goto processExceptionReturn; { CoroutineData *corPtr; - int yieldParameter; + void *yieldParameter; case INST_YIELD: corPtr = iPtr->execEnvPtr->corPtr; TRACE(("%.30s => ", O2S(OBJ_AT_TOS))); if (!corPtr) { @@ -2377,28 +2377,28 @@ 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); + (void *)NULL); CACHE_STACK_INFO(); goto gotError; } #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { if (traceInstructions) { TRACE_APPEND(("YIELD...\n")); } else { - fprintf(stdout, "%d: (%u) yielding value \"%.30s\"\n", - iPtr->numLevels, (unsigned)(pc - codePtr->codeStart), + fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) yielding value \"%.30s\"\n", + iPtr->numLevels, (pc - codePtr->codeStart), Tcl_GetString(OBJ_AT_TOS)); } fflush(stdout); } #endif - yieldParameter = 0; + yieldParameter = NULL; /*==CORO_ACTIVATE_YIELD*/ Tcl_SetObjResult(interp, OBJ_AT_TOS); goto doYield; case INST_YIELD_TO_INVOKE: corPtr = iPtr->execEnvPtr->corPtr; @@ -2408,11 +2408,11 @@ 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); + (void *)NULL); CACHE_STACK_INFO(); goto gotError; } if (((Namespace *)TclGetCurrentNamespace(interp))->flags & NS_DYING) { TRACE(("[%.30s] => ERROR: yield in deleted\n", @@ -2419,11 +2419,11 @@ 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); + (void *)NULL); CACHE_STACK_INFO(); goto gotError; } #ifdef TCL_COMPILE_DEBUG @@ -2430,12 +2430,12 @@ if (tclTraceExec >= 2) { if (traceInstructions) { TRACE(("[%.30s] => YIELD...\n", O2S(valuePtr))); } else { /* FIXME: What is the right thing to trace? */ - fprintf(stdout, "%d: (%u) yielding to [%.30s]\n", - iPtr->numLevels, (unsigned)(pc - codePtr->codeStart), + fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) yielding to [%.30s]\n", + iPtr->numLevels, (pc - codePtr->codeStart), TclGetString(valuePtr)); } fflush(stdout); } #endif @@ -2444,15 +2444,16 @@ * Install a tailcall record in the caller and continue with the * yield. The yield is switched into multi-return mode (via the * 'yieldParameter'). */ - Tcl_IncrRefCount(valuePtr); iPtr->execEnvPtr = corPtr->callerEEPtr; + Tcl_IncrRefCount(valuePtr); TclSetTailcall(interp, valuePtr); + corPtr->yieldPtr = valuePtr; iPtr->execEnvPtr = corPtr->eePtr; - yieldParameter = (PTR2INT(NULL)+1); /*==CORO_ACTIVATE_YIELDM*/ + yieldParameter = INT2PTR(1); /*==CORO_ACTIVATE_YIELDM*/ doYield: /* TIP #280: Record the last piece of info needed by * 'TclGetSrcInfoForPc', and push the frame. */ @@ -2466,11 +2467,11 @@ pc++; cleanup = 1; TEBC_YIELD(); TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, - INT2PTR(yieldParameter), NULL, NULL); + yieldParameter, NULL, NULL); return TCL_OK; } case INST_TAILCALL: { Tcl_Obj *listPtr, *nsObjPtr; @@ -2480,11 +2481,11 @@ if (!(iPtr->varFramePtr->isProcCallFrame & 1)) { TRACE(("%d => ERROR: tailcall in non-proc context\n", opnd)); Tcl_SetObjResult(interp, Tcl_NewStringObj( "tailcall can only be called from a proc or lambda", -1)); DECACHE_STACK_INFO(); - Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", NULL); + Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", (void *)NULL); CACHE_STACK_INFO(); goto gotError; } #ifdef TCL_COMPILE_DEBUG @@ -2595,17 +2596,20 @@ 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: @@ -2636,11 +2640,11 @@ TclNewObj(objPtr); objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(CURR_DEPTH); objPtr->length = 0; PUSH_TAUX_OBJ(objPtr); - TRACE(("=> mark depth as %d\n", (int) CURR_DEPTH)); + TRACE(("=> mark depth as %" TCL_T_MODIFIER "d\n", CURR_DEPTH)); NEXT_INST_F(1, 0, 0); break; case INST_EXPAND_DROP: /* @@ -2654,26 +2658,27 @@ POP_TAUX_OBJ(); #ifdef TCL_COMPILE_DEBUG /* Ugly abuse! */ starting = 1; #endif - TRACE(("=> drop %d items\n", objc)); + TRACE(("=> drop %" TCL_SIZE_MODIFIER "d items\n", objc)); NEXT_INST_V(1, objc, 0); case INST_EXPAND_STKTOP: { - int i; - ptrdiff_t moved; + Tcl_Size i; + TEBCdata *newTD; + Tcl_Size oldCatchTopOff, oldTosPtrOff; /* * Make sure that the element at stackTop is a list; if not, just * leave with an error. Note that the element from the expand list * will be removed at checkForCatch. */ objPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(objPtr))); - if (TclListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { + if (TclListObjGetElementsM(interp, objPtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } (void) POP_OBJECT(); @@ -2688,23 +2693,25 @@ 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) { + 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 = (TEBCdata *) (((Tcl_Obj **)TD) + moved); + TD = newTD; - catchTop += moved; - tosPtr += moved; + catchTop = initCatchTop + oldCatchTopOff; + tosPtr = initTosPtr + oldTosPtrOff; } } /* * Expand the list at stacktop onto the stack; free the list. Knowing @@ -2782,18 +2789,18 @@ objv = &OBJ_AT_DEPTH(objc-1); cleanup = objc; #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { - int i; + Tcl_Size i; if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); - TRACE(("%u => call ", objc)); + TRACE(("%" TCL_SIZE_MODIFIER "d => call ", objc)); } else { - fprintf(stdout, "%d: (%u) invoking ", iPtr->numLevels, - (unsigned)(pc - codePtr->codeStart)); + fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) invoking ", iPtr->numLevels, + (pc - codePtr->codeStart)); } for (i = 0; i < objc; i++) { TclPrintObject(stdout, objv[i], 15); fprintf(stdout, " "); } @@ -2818,30 +2825,34 @@ DECACHE_STACK_INFO(); pc += pcAdjustment; TEBC_YIELD(); - return TclNREvalObjv(interp, objc, objv, + 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) { - int i; + Tcl_Size i; if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); - TRACE(("%u => call (implementation %s) ", objc, O2S(objPtr))); + TRACE(("%" TCL_Z_MODIFIER "u => call (implementation %s) ", objc, O2S(objPtr))); } else { fprintf(stdout, - "%d: (%u) invoking (using implementation %s) ", - iPtr->numLevels, (unsigned)(pc - codePtr->codeStart), + "%" TCL_Z_MODIFIER "d: (%" TCL_T_MODIFIER "u) invoking (using implementation %s) ", + iPtr->numLevels, (pc - codePtr->codeStart), O2S(objPtr)); } for (i = 0; i < objc; i++) { if (i < opnd) { fprintf(stdout, "<"); @@ -2879,11 +2890,11 @@ pc += 6; TEBC_YIELD(); TclMarkTailcall(interp); TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL); - Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv); + TclListObjGetElementsM(NULL, objPtr, &objc, &objv); TclNRAddCallback(interp, TclNRReleaseValues, objPtr, NULL, NULL, NULL); return TclNREvalObjv(interp, objc, objv, TCL_EVAL_INVOKE, NULL); /* * ----------------------------------------------------------------- @@ -3039,11 +3050,12 @@ * instructions set the value of some variables and then jump to somme * common execution code. */ { - int storeFlags, len; + int storeFlags; + Tcl_Size len; case INST_STORE_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; goto doStoreArrayDirect; @@ -3290,11 +3302,11 @@ pcAdjustment = 5; while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr))); - if (TclListObjGetElements(interp, valuePtr, &objc, &objv) + if (TclListObjGetElementsM(interp, valuePtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } if (TclIsVarDirectReadable(varPtr) @@ -3316,11 +3328,11 @@ while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } TRACE(("%u \"%.30s\" \"%.30s\" => ", opnd, O2S(part2Ptr), O2S(valuePtr))); - if (TclListObjGetElements(interp, valuePtr, &objc, &objv) + if (TclListObjGetElementsM(interp, valuePtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } if (TclIsVarArray(arrayPtr) && !ReadTraced(arrayPtr) @@ -3358,11 +3370,11 @@ TRACE(("\"%.30s\" \"%.30s\" => ", O2S(part1Ptr), O2S(valuePtr))); goto lappendList; lappendListDirect: objResultPtr = varPtr->value.objPtr; - if (TclListObjLength(interp, objResultPtr, &len) != TCL_OK) { + if (TclListObjLengthM(interp, objResultPtr, &len) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } if (Tcl_IsShared(objResultPtr)) { Tcl_Obj *newValue = Tcl_DuplicateObj(objResultPtr); @@ -3369,21 +3381,21 @@ TclDecrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr = newValue; Tcl_IncrRefCount(newValue); } - if (Tcl_ListObjReplace(interp, objResultPtr, len, 0, objc, objv) + if (TclListObjAppendElements(interp, objResultPtr, objc, objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(pcAdjustment, cleanup, 1); lappendList: opnd = -1; - if (TclListObjGetElements(interp, valuePtr, &objc, &objv) + if (TclListObjGetElementsM(interp, valuePtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } DECACHE_STACK_INFO(); @@ -3417,33 +3429,31 @@ int createdNewObj = 0; Tcl_Obj *valueToAssign; if (!objResultPtr) { valueToAssign = valuePtr; - } else if (TclListObjLength(interp, objResultPtr, &len)!=TCL_OK) { + } else if (TclListObjLengthM(interp, objResultPtr, &len)!=TCL_OK) { TRACE_ERROR(interp); goto gotError; } else { if (Tcl_IsShared(objResultPtr)) { valueToAssign = Tcl_DuplicateObj(objResultPtr); createdNewObj = 1; } else { valueToAssign = objResultPtr; } - if (Tcl_ListObjReplace(interp, valueToAssign, len, 0, + if (TclListObjAppendElements(interp, valueToAssign, objc, objv) != TCL_OK) { if (createdNewObj) { TclDecrRefCount(valueToAssign); } goto errorInLappendListPtr; } } DECACHE_STACK_INFO(); - Tcl_IncrRefCount(valueToAssign); objResultPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, valueToAssign, TCL_LEAVE_ERR_MSG, opnd); - TclDecrRefCount(valueToAssign); CACHE_STACK_INFO(); if (!objResultPtr) { errorInLappendListPtr: TRACE_ERROR(interp); goto gotError; @@ -3457,11 +3467,11 @@ * End of INST_STORE and related instructions. * ----------------------------------------------------------------- * Start of INST_INCR instructions. * * WARNING: more 'goto' here than your doctor recommended! The different - * instructions set the value of some variables and then jump to somme + * instructions set the value of some variables and then jump to some * common execution code. */ /*TODO: Consider more untangling here; merge with LOAD and STORE ? */ @@ -3559,18 +3569,18 @@ while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectModifyable(varPtr)) { - ClientData ptr; + void *ptr; int type; objPtr = varPtr->value.objPtr; if (GetNumberFromObj(NULL, objPtr, &ptr, &type) == TCL_OK) { if (type == TCL_NUMBER_INT) { Tcl_WideInt augend = *((const Tcl_WideInt *)ptr); - Tcl_WideInt sum = augend + increment; + Tcl_WideInt sum = (Tcl_WideInt)((Tcl_WideUInt)augend + (Tcl_WideUInt)increment); /* * Overflow when (augend and sum have different sign) and * (augend and increment have the same sign). This is * encapsulated in the Overflowing macro. @@ -3599,11 +3609,11 @@ varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; /* - * We know the sum value is outside the long range; + * We know the sum value is outside the Tcl_WideInt range; * use macro form that doesn't range test again. */ TclSetIntObj(objPtr, w+increment); } @@ -3987,11 +3997,11 @@ */ TclObjVarErrMsg(interp, part1Ptr, NULL, "array set", "variable isn't array", opnd); DECACHE_STACK_INFO(); - Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", (void *)NULL); CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } TclInitArrayVar(varPtr); @@ -4136,19 +4146,19 @@ * ----------------------------------------------------------------- */ case INST_JUMP1: opnd = TclGetInt1AtPtr(pc+1); - TRACE(("%d => new pc %u\n", opnd, - (unsigned)(pc + opnd - codePtr->codeStart))); + TRACE(("%d => new pc %" TCL_Z_MODIFIER "u\n", opnd, + (size_t)(pc + opnd - codePtr->codeStart))); NEXT_INST_F(opnd, 0, 0); break; case INST_JUMP4: opnd = TclGetInt4AtPtr(pc+1); - TRACE(("%d => new pc %u\n", opnd, - (unsigned)(pc + opnd - codePtr->codeStart))); + TRACE(("%d => new pc %" TCL_Z_MODIFIER "u\n", opnd, + (size_t)(pc + opnd - codePtr->codeStart))); NEXT_INST_F(opnd, 0, 0); { int jmpOffset[2], b; @@ -4186,21 +4196,21 @@ } #ifdef TCL_COMPILE_DEBUG if (b) { if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) { - TRACE_APPEND(("%.20s true, new pc %u\n", O2S(valuePtr), - (unsigned)(pc + jmpOffset[1] - codePtr->codeStart))); + TRACE_APPEND(("%.20s true, new pc %" TCL_Z_MODIFIER "u\n", O2S(valuePtr), + (size_t)(pc + jmpOffset[1] - codePtr->codeStart))); } else { TRACE_APPEND(("%.20s true\n", O2S(valuePtr))); } } else { if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) { TRACE_APPEND(("%.20s false\n", O2S(valuePtr))); } else { - TRACE_APPEND(("%.20s false, new pc %u\n", O2S(valuePtr), - (unsigned)(pc + jmpOffset[0] - codePtr->codeStart))); + TRACE_APPEND(("%.20s false, new pc %" TCL_Z_MODIFIER "u\n", O2S(valuePtr), + (size_t)(pc + jmpOffset[0] - codePtr->codeStart))); } } #endif NEXT_INST_F(jmpOffset[b], 1, 0); } @@ -4214,18 +4224,18 @@ * Jump to location looked up in a hashtable; fall through to next * instr if lookup fails. */ opnd = TclGetInt4AtPtr(pc+1); - jtPtr = (JumptableInfo *) codePtr->auxDataArrayPtr[opnd].clientData; + jtPtr = (JumptableInfo *)BA_AuxData_At(codePtr->auxData, opnd)->clientData; TRACE(("%d \"%.20s\" => ", opnd, O2S(OBJ_AT_TOS))); hPtr = Tcl_FindHashEntry(&jtPtr->hashTable, TclGetString(OBJ_AT_TOS)); if (hPtr != NULL) { int jumpOffset = PTR2INT(Tcl_GetHashValue(hPtr)); - TRACE_APPEND(("found in table, new pc %u\n", - (unsigned)(pc - codePtr->codeStart + jumpOffset))); + TRACE_APPEND(("found in table, new pc %" TCL_Z_MODIFIER "u\n", + (size_t)(pc - codePtr->codeStart + jumpOffset))); NEXT_INST_F(jumpOffset, 1, 0); } else { TRACE_APPEND(("not found in table\n")); NEXT_INST_F(5, 1, 0); } @@ -4261,11 +4271,11 @@ TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); } break; case INST_INFO_LEVEL_NUM: - TclNewIntObj(objResultPtr, iPtr->varFramePtr->level); + TclNewIntObj(objResultPtr, (int)iPtr->varFramePtr->level); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); break; case INST_INFO_LEVEL_ARGS: { int level; @@ -4278,21 +4288,21 @@ goto gotError; } if (level <= 0) { level += framePtr->level; } - for (; (framePtr->level!=level) && (framePtr!=rootFramePtr) ; + for (; ((int)framePtr->level!=level) && (framePtr!=rootFramePtr) ; framePtr = framePtr->callerVarPtr) { /* Empty loop body */ } if (framePtr == rootFramePtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad level \"%s\"", TclGetString(OBJ_AT_TOS))); TRACE_ERROR(interp); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_LEVEL", - TclGetString(OBJ_AT_TOS), NULL); + TclGetString(OBJ_AT_TOS), (void *)NULL); CACHE_STACK_INFO(); goto gotError; } objResultPtr = Tcl_NewListObj(framePtr->objc, framePtr->objv); TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); @@ -4328,11 +4338,11 @@ instOriginError: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid command name \"%s\"", TclGetString(OBJ_AT_TOS))); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", - TclGetString(OBJ_AT_TOS), NULL); + TclGetString(OBJ_AT_TOS), (void *)NULL); CACHE_STACK_INFO(); TRACE_APPEND(("ERROR: not command\n")); goto gotError; } TRACE_APPEND(("\"%.30s\"", O2S(OBJ_AT_TOS))); @@ -4346,11 +4356,11 @@ { Object *oPtr; CallFrame *framePtr; CallContext *contextPtr; - int skip, newDepth; + Tcl_Size skip, newDepth; case INST_TCLOO_SELF: framePtr = iPtr->varFramePtr; if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { @@ -4357,11 +4367,11 @@ TRACE(("=> ERROR: no TclOO call context\n")); Tcl_SetObjResult(interp, Tcl_NewStringObj( "self may only be called from inside a method", -1)); DECACHE_STACK_INFO(); - Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (void *)NULL); CACHE_STACK_INFO(); goto gotError; } contextPtr = (CallContext *)framePtr->clientData; @@ -4385,11 +4395,11 @@ TRACE_APPEND(("ERROR: no TclOO call context\n")); Tcl_SetObjResult(interp, Tcl_NewStringObj( "nextto may only be called from inside a method", -1)); DECACHE_STACK_INFO(); - Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (void *)NULL); CACHE_STACK_INFO(); goto gotError; } contextPtr = (CallContext *)framePtr->clientData; @@ -4398,19 +4408,19 @@ TRACE_APPEND(("ERROR: \"%.30s\" not object\n", O2S(valuePtr))); goto gotError; } else { Class *classPtr = oPtr->classPtr; struct MInvoke *miPtr; - int i; + Tcl_Size i; const char *methodType; if (classPtr == NULL) { TRACE_APPEND(("ERROR: \"%.30s\" not class\n", O2S(valuePtr))); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(valuePtr))); DECACHE_STACK_INFO(); - Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", (void *)NULL); CACHE_STACK_INFO(); goto gotError; } for (i=contextPtr->index+1 ; icallPtr->numChain ; i++) { @@ -4421,13 +4431,13 @@ #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); } else { - fprintf(stdout, "%d: (%u) invoking ", + fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) invoking ", iPtr->numLevels, - (unsigned)(pc - codePtr->codeStart)); + (size_t)(pc - codePtr->codeStart)); } for (i = 0; i < opnd; i++) { TclPrintObject(stdout, objv[i], 15); fprintf(stdout, " "); } @@ -4447,11 +4457,11 @@ methodType = "method"; } TRACE_APPEND(("ERROR: \"%.30s\" not on reachable chain\n", O2S(valuePtr))); - for (i=contextPtr->index ; i>=0 ; i--) { + for (i = contextPtr->index ; i != TCL_INDEX_NONE ; i--) { miPtr = contextPtr->callPtr->chain + i; if (miPtr->isFilter || miPtr->mPtr->declaringClassPtr != classPtr) { continue; } @@ -4458,19 +4468,19 @@ 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); + (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", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", (void *)NULL); CACHE_STACK_INFO(); goto gotError; } case INST_TCLOO_NEXT: @@ -4484,11 +4494,11 @@ TRACE_APPEND(("ERROR: no TclOO call context\n")); Tcl_SetObjResult(interp, Tcl_NewStringObj( "next may only be called from inside a method", -1)); DECACHE_STACK_INFO(); - Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (void *)NULL); CACHE_STACK_INFO(); goto gotError; } contextPtr = (CallContext *)framePtr->clientData; @@ -4513,22 +4523,22 @@ TRACE_APPEND(("ERROR: no TclOO next impl\n")); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "no next %s implementation", methodType)); DECACHE_STACK_INFO(); - Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", (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, "%d: (%u) invoking ", - iPtr->numLevels, (unsigned)(pc - codePtr->codeStart)); + fprintf(stdout, "%" TCL_SIZE_MODIFIER "d: (%" TCL_Z_MODIFIER "u) invoking ", + iPtr->numLevels, (pc - codePtr->codeStart)); } for (i = 0; i < opnd; i++) { TclPrintObject(stdout, objv[i], 15); fprintf(stdout, " "); } @@ -4574,11 +4584,15 @@ { Method *const mPtr = contextPtr->callPtr->chain[newDepth].mPtr; - return mPtr->typePtr->callProc(mPtr->clientData, interp, + 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); @@ -4617,11 +4631,11 @@ * Start of INST_LIST and related instructions. */ { int numIndices, nocase, match, cflags; - size_t slength, length2, fromIdx, toIdx, index, s1len, s2len; + Tcl_Size slength, length2, fromIdx, toIdx, index, s1len, s2len; const char *s1, *s2; case INST_LIST: /* * Pop the opnd (objc) top stack elements into a new list obj and then @@ -4633,44 +4647,90 @@ 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) { + if (TclListObjLengthM(interp, OBJ_AT_TOS, &length) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } TclNewIntObj(objResultPtr, length); - TRACE_APPEND(("%d\n", length)); + TRACE_APPEND(("%" TCL_SIZE_MODIFIER "d\n", length)); NEXT_INST_F(1, 1, 1); case INST_LIST_INDEX: /* lindex with objc == 3 */ value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr))); + + /* special case for AbstractList */ + if (TclObjTypeHasProc(valuePtr,indexProc)) { + DECACHE_STACK_INFO(); + length = TclObjTypeLength(valuePtr); + if (TclGetIntForIndexM(interp, value2Ptr, length-1, &index)!=TCL_OK) { + CACHE_STACK_INFO(); + TRACE_ERROR(interp); + goto gotError; + } + if (TclObjTypeIndex(interp, valuePtr, index, &objResultPtr)!=TCL_OK) { + CACHE_STACK_INFO(); + TRACE_ERROR(interp); + goto gotError; + } + CACHE_STACK_INFO(); + if (objResultPtr == NULL) { + /* Index is out of range, return empty result. */ + TclNewObj(objResultPtr); + } + Tcl_IncrRefCount(objResultPtr); // reference held here + goto lindexDone; + } /* * Extract the desired list element. */ - 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); - } - + { + Tcl_Size value2Length; + Tcl_Obj *indexListPtr = value2Ptr; + if ((TclListObjGetElementsM(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; } @@ -4695,11 +4755,36 @@ /* * 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) { + /* 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 (TclListObjGetElementsM(interp, valuePtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } /* Decode end-offset index values. */ @@ -4706,15 +4791,17 @@ index = TclIndexDecode(opnd, objc - 1); pcAdjustment = 5; lindexFastPath: - if (index < (size_t)objc) { + if (index >= 0 && index < objc) { objResultPtr = objv[index]; } else { TclNewObj(objResultPtr); } + + lindexFastPath2: TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(pcAdjustment, 1, 1); case INST_LIST_INDEX_MULTI: /* 'lindex' with multiple index args */ @@ -4765,21 +4852,29 @@ /* * Compute the new variable value. */ - objResultPtr = TclLsetFlat(interp, valuePtr, numIndices, + 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 */ /* @@ -4834,11 +4929,11 @@ /* * Get the length of the list, making sure that it really is a list * in the process. */ - if (TclListObjLength(interp, valuePtr, &objc) != TCL_OK) { + if (TclListObjLengthM(interp, valuePtr, &objc) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } /* @@ -4871,15 +4966,15 @@ NEXT_INST_F(9, 1, 1); } toIdx = TclIndexDecode(toIdx, objc - 1); if (toIdx == TCL_INDEX_NONE) { goto emptyList; - } else if (toIdx + 1 >= (size_t)objc + 1) { + } else if (toIdx >= objc) { toIdx = objc - 1; } - assert (toIdx < (size_t)objc); + assert (toIdx >= 0 && toIdx < objc); /* assert ( fromIdx != TCL_INDEX_NONE ); * * Extra safety for legacy bytecodes: */ @@ -4887,49 +4982,87 @@ fromIdx = TCL_INDEX_START; } fromIdx = TclIndexDecode(fromIdx, objc - 1); - objResultPtr = TclListObjRange(valuePtr, fromIdx, toIdx); + 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 (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); - } + s1 = Tcl_GetStringFromObj(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 (TclListObjLengthM(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 = Tcl_GetStringFromObj(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; } @@ -4964,15 +5097,106 @@ } 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_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: @@ -5040,54 +5264,54 @@ case INST_STR_UPPER: valuePtr = OBJ_AT_TOS; TRACE(("\"%.20s\" => ", O2S(valuePtr))); if (Tcl_IsShared(valuePtr)) { - s1 = TclGetStringFromObj(valuePtr, &slength); + s1 = Tcl_GetStringFromObj(valuePtr, &slength); TclNewStringObj(objResultPtr, s1, slength); slength = Tcl_UtfToUpper(TclGetString(objResultPtr)); Tcl_SetObjLength(objResultPtr, slength); TRACE_APPEND(("\"%.20s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } else { slength = Tcl_UtfToUpper(TclGetString(valuePtr)); Tcl_SetObjLength(valuePtr, slength); - TclFreeIntRep(valuePtr); + TclFreeInternalRep(valuePtr); TRACE_APPEND(("\"%.20s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } case INST_STR_LOWER: valuePtr = OBJ_AT_TOS; TRACE(("\"%.20s\" => ", O2S(valuePtr))); if (Tcl_IsShared(valuePtr)) { - s1 = TclGetStringFromObj(valuePtr, &slength); + s1 = Tcl_GetStringFromObj(valuePtr, &slength); TclNewStringObj(objResultPtr, s1, slength); slength = Tcl_UtfToLower(TclGetString(objResultPtr)); Tcl_SetObjLength(objResultPtr, slength); TRACE_APPEND(("\"%.20s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } else { slength = Tcl_UtfToLower(TclGetString(valuePtr)); Tcl_SetObjLength(valuePtr, slength); - TclFreeIntRep(valuePtr); + TclFreeInternalRep(valuePtr); TRACE_APPEND(("\"%.20s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } case INST_STR_TITLE: valuePtr = OBJ_AT_TOS; TRACE(("\"%.20s\" => ", O2S(valuePtr))); if (Tcl_IsShared(valuePtr)) { - s1 = TclGetStringFromObj(valuePtr, &slength); + s1 = Tcl_GetStringFromObj(valuePtr, &slength); TclNewStringObj(objResultPtr, s1, slength); slength = Tcl_UtfToTitle(TclGetString(objResultPtr)); Tcl_SetObjLength(objResultPtr, slength); TRACE_APPEND(("\"%.20s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } else { slength = Tcl_UtfToTitle(TclGetString(valuePtr)); Tcl_SetObjLength(valuePtr, slength); - TclFreeIntRep(valuePtr); + TclFreeInternalRep(valuePtr); TRACE_APPEND(("\"%.20s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } case INST_STR_INDEX: @@ -5094,11 +5318,11 @@ value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; TRACE(("\"%.20s\" %.20s => ", O2S(valuePtr), O2S(value2Ptr))); /* - * Get char length to calulate what 'end' means. + * Get char length to calculate what 'end' means. */ slength = Tcl_GetCharLength(valuePtr); DECACHE_STACK_INFO(); if (TclGetIntForIndexM(interp, value2Ptr, slength-1, &index)!=TCL_OK) { @@ -5106,15 +5330,15 @@ TRACE_ERROR(interp); goto gotError; } CACHE_STACK_INFO(); - if (index >= slength) { + if (index < 0 || index >= slength) { TclNewObj(objResultPtr); } else if (TclIsPureByteArray(valuePtr)) { objResultPtr = Tcl_NewByteArrayObj( - Tcl_GetByteArrayFromObj(valuePtr, NULL)+index, 1); + Tcl_GetByteArrayFromObj(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] = ""; @@ -5127,13 +5351,10 @@ */ 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))); @@ -5157,20 +5378,14 @@ 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 { + 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: @@ -5186,54 +5401,23 @@ 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); + 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; - size_t length3; + Tcl_Size length3; Tcl_Obj *value3Ptr; case INST_STR_REPLACE: value3Ptr = POP_OBJECT(); valuePtr = OBJ_AT_DEPTH(2); @@ -5254,27 +5438,27 @@ 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)) { + if ((toIdx < 0) || + (fromIdx > slength) || + (toIdx < fromIdx)) { TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); TclDecrRefCount(value3Ptr); NEXT_INST_F(1, 0, 0); } - if (fromIdx == TCL_INDEX_NONE) { - fromIdx = TCL_INDEX_START; + if (fromIdx < 0) { + fromIdx = 0; } - if (toIdx + 1 > slength + 1) { + if (toIdx > slength) { toIdx = slength; } - if ((fromIdx == TCL_INDEX_START) && (toIdx == slength)) { + if ((fromIdx == 0) && (toIdx == slength)) { TclDecrRefCount(OBJ_AT_TOS); OBJ_AT_TOS = value3Ptr; TRACE_APPEND(("\"%.30s\"\n", O2S(value3Ptr))); NEXT_INST_F(1, 0, 0); } @@ -5302,16 +5486,16 @@ goto doneStringMap; } else if (valuePtr == value2Ptr) { objResultPtr = value3Ptr; goto doneStringMap; } - ustring1 = TclGetUnicodeFromObj(valuePtr, &slength); + ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &slength); if (slength == 0) { objResultPtr = valuePtr; goto doneStringMap; } - ustring2 = TclGetUnicodeFromObj(value2Ptr, &length2); + ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2); if (length2 > slength || length2 == 0) { objResultPtr = valuePtr; goto doneStringMap; } else if (length2 == slength) { if (memcmp(ustring1, ustring2, sizeof(Tcl_UniChar) * slength)) { @@ -5319,68 +5503,70 @@ } else { objResultPtr = value3Ptr; } goto doneStringMap; } - ustring3 = TclGetUnicodeFromObj(value3Ptr, &length3); + ustring3 = Tcl_GetUnicodeFromObj(value3Ptr, &length3); objResultPtr = Tcl_NewUnicodeObj(ustring1, 0); p = ustring1; end = ustring1 + slength; for (; ustring1 < end; ustring1++) { - if ((*ustring1 == *ustring2) && (length2==1 || + if ((*ustring1 == *ustring2) && + /* Fix bug [69218ab7b]: restrict max compare length. */ + ((end-ustring1) >= length2) && (length2==1 || memcmp(ustring1, ustring2, sizeof(Tcl_UniChar) * length2) == 0)) { if (p != ustring1) { - TclAppendUnicodeToObj(objResultPtr, p, ustring1-p); + Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1-p); p = ustring1 + length2; } else { p += length2; } ustring1 = p - 1; - TclAppendUnicodeToObj(objResultPtr, ustring3, length3); + Tcl_AppendUnicodeToObj(objResultPtr, ustring3, length3); } } if (p != ustring1) { /* * Put the rest of the unmapped chars onto result. */ - TclAppendUnicodeToObj(objResultPtr, p, ustring1 - p); + Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1 - p); } doneStringMap: TRACE_WITH_OBJ(("%.20s %.20s %.20s => ", O2S(value2Ptr), O2S(value3Ptr), O2S(valuePtr)), objResultPtr); NEXT_INST_V(1, 3, 1); case INST_STR_FIND: objResultPtr = TclStringFirst(OBJ_UNDER_TOS, OBJ_AT_TOS, 0); - TRACE(("%.20s %.20s => %d\n", + TRACE(("%.20s %.20s => %s\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); case INST_STR_FIND_LAST: - objResultPtr = TclStringLast(OBJ_UNDER_TOS, OBJ_AT_TOS, INT_MAX - 1); + objResultPtr = TclStringLast(OBJ_UNDER_TOS, OBJ_AT_TOS, TCL_SIZE_MAX - 1); - TRACE(("%.20s %.20s => %d\n", + TRACE(("%.20s %.20s => %s\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); case INST_STR_CLASS: opnd = TclGetInt1AtPtr(pc+1); valuePtr = OBJ_AT_TOS; TRACE(("%s \"%.30s\" => ", tclStringClassTable[opnd].name, O2S(valuePtr))); - ustring1 = TclGetUnicodeFromObj(valuePtr, &slength); + ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &slength); match = 1; if (slength > 0) { int ch; end = ustring1 + slength; for (p=ustring1 ; p %d\n", O2S(OBJ_AT_TOS), type1)); NEXT_INST_F(1, 1, 1); @@ -5710,11 +5888,12 @@ if ((wResult < 0 || (wResult == 0 && ((w1 < 0 && w2 > 0) || (w1 > 0 && w2 < 0)))) && (wResult * w2 != w1)) { wResult -= 1; } - wResult = w1 - w2*wResult; + wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 - + (Tcl_WideUInt)w2*(Tcl_WideUInt)wResult); goto wideResultOfArithmetic; } break; case INST_RSHIFT: @@ -5723,11 +5902,11 @@ "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); + (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))); @@ -5737,16 +5916,16 @@ } else { /* * Quickly force large right shifts to 0 or -1. */ - if (w2 >= (Tcl_WideInt)(CHAR_BIT*sizeof(long))) { + if (w2 >= (Tcl_WideInt)(CHAR_BIT*sizeof(w1))) { /* * We assume that INT_MAX is much larger than the - * number of bits in a long. This is a pretty safe + * number of bits in a Tcl_WideInt. This is a pretty safe * assumption, given that the former is usually around - * 4e9 and the latter 32 or 64... + * 4e9 and the latter 64... */ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); if (w1 > 0L) { objResultPtr = TCONST(0); @@ -5756,11 +5935,11 @@ TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } /* - * Handle shifts within the native long range. + * Handle shifts within the native Tcl_WideInt range. */ wResult = w1 >> ((int) w2); goto wideResultOfArithmetic; } @@ -5772,11 +5951,11 @@ "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); + (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))); @@ -5794,25 +5973,25 @@ Tcl_SetObjResult(interp, Tcl_NewStringObj( "integer value too large to represent", -1)); #ifdef ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", - "integer value too large to represent", NULL); + "integer value too large to represent", (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 long range. + * Handle shifts within the native Tcl_WideInt range. */ - if ((size_t) shift < CHAR_BIT*sizeof(long) && (w1 != 0) + if (((size_t)shift < CHAR_BIT*sizeof(w1)) && !((w1>0 ? w1 : ~w1) & - -(1L<<(CHAR_BIT*sizeof(long) - 1 - shift)))) { - wResult = w1 << shift; + -((Tcl_WideUInt)1<<(CHAR_BIT*sizeof(w1) - 1 - shift)))) { + wResult = (Tcl_WideUInt)w1 << shift; goto wideResultOfArithmetic; } } /* @@ -5907,21 +6086,21 @@ NEXT_INST_F(1, 2, 1); } #endif /* - * Handle (long,long) arithmetic as best we can without going out to + * Handle Tcl_WideInt arithmetic as best we can without going out to * an external function. */ if ((type1 == TCL_NUMBER_INT) && (type2 == TCL_NUMBER_INT)) { w1 = *((const Tcl_WideInt *)ptr1); w2 = *((const Tcl_WideInt *)ptr2); switch (*pc) { case INST_ADD: - wResult = w1 + w2; + wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2); /* * Check for overflow. */ if (Overflowing(w1, w2, wResult)) { @@ -5928,11 +6107,11 @@ goto overflow; } goto wideResultOfArithmetic; case INST_SUB: - wResult = w1 - w2; + wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 - (Tcl_WideUInt)w2); /* * Must check for overflow. The macro tests for overflows in * sums by looking at the sign bits. As we have a subtraction * here, we are adding -w2. As -w2 could in turn overflow, we * test with ~w2 instead: it has the opposite sign bit to w2 @@ -6188,11 +6367,11 @@ NEXT_INST_F(1, 0, 0); } if (Tcl_IsShared(valuePtr)) { /* * Here we do some surgery within the Tcl_Obj internals. We want - * to copy the intrep, but not the string, so we temporarily hide + * to copy the internalrep, but not the string, so we temporarily hide * the string so we do not copy it. */ char *savedString = valuePtr->bytes; @@ -6213,11 +6392,11 @@ * ----------------------------------------------------------------- */ case INST_TRY_CVT_TO_BOOLEAN: valuePtr = OBJ_AT_TOS; - if (TclHasIntRep(valuePtr, &tclBooleanType)) { + if (TclHasInternalRep(valuePtr, &tclBooleanType)) { objResultPtr = TCONST(1); } else { int res = (TclSetBooleanFromAny(NULL, valuePtr) == TCL_OK); objResultPtr = TCONST(res); } @@ -6249,24 +6428,22 @@ { 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; + 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. */ opnd = TclGetUInt4AtPtr(pc+1); - infoPtr = (ForeachInfo *)codePtr->auxDataArrayPtr[opnd].clientData; + infoPtr = (ForeachInfo *)BA_AuxData_At(codePtr->auxData, opnd)->clientData; numLists = infoPtr->numLists; TRACE(("%u => ", opnd)); /* * Compute the number of iterations that will be run: iterMax @@ -6276,12 +6453,14 @@ 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", + DECACHE_STACK_INFO(); + if (TclListObjLengthM(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); @@ -6323,11 +6502,11 @@ * falls through. */ pc += 5 - infoPtr->loopCtTemp; - case INST_FOREACH_STEP: + case INST_FOREACH_STEP: /* TODO: address abstract list indexing here! */ /* * "Step" a foreach loop (i.e., begin its next iteration) by assigning * the next value list element to each loop var. */ @@ -6344,10 +6523,11 @@ * 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); @@ -6355,20 +6535,51 @@ listTmpDepth = numLists + 1; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; + int hasAbstractList; listPtr = OBJ_AT_DEPTH(listTmpDepth); - TclListObjGetElements(interp, listPtr, &listLen, &elements); + hasAbstractList = TclObjTypeHasProc(listPtr, indexProc) != 0; + DECACHE_STACK_INFO(); + if (hasAbstractList) { + status = Tcl_ListObjLength(interp, listPtr, &listLen); + elements = NULL; + } else { + status = TclListObjGetElementsM( + 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 { - valuePtr = elements[valIndex]; + 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)) { @@ -6386,11 +6597,11 @@ } else { DECACHE_STACK_INFO(); if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL, valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){ CACHE_STACK_INFO(); - TRACE_APPEND(("ERROR init. index temp %d: %.30s", + TRACE_APPEND(("ERROR init. index temp %" TCL_SIZE_MODIFIER "d: %.30s", varIndex, O2S(Tcl_GetObjResult(interp)))); goto gotError; } CACHE_STACK_INFO(); } @@ -6433,11 +6644,11 @@ */ tmpPtr = OBJ_AT_DEPTH(1); infoPtr = (ForeachInfo *)tmpPtr->internalRep.twoPtrValue.ptr1; numLists = infoPtr->numLists; - TRACE_APPEND(("=> appending to list at depth %d\n", 3 + numLists)); + TRACE_APPEND(("=> appending to list at depth %" TCL_SIZE_MODIFIER "d\n", 3 + numLists)); objPtr = OBJ_AT_DEPTH(3 + numLists); Tcl_ListObjAppendElement(NULL, objPtr, OBJ_AT_TOS); NEXT_INST_F(1, 1, 0); } @@ -6448,24 +6659,24 @@ * Record start of the catch command with exception range index equal * to the operand. Push the current stack depth onto the special catch * stack. */ - *(++catchTop) = CURR_DEPTH; - TRACE(("%u => catchTop=%d, stackTop=%d\n", - TclGetUInt4AtPtr(pc+1), (int) (catchTop - initCatchTop - 1), - (int) CURR_DEPTH)); + *(++catchTop) = (Tcl_Obj *)INT2PTR(CURR_DEPTH); + TRACE(("%u => catchTop=%" TCL_T_MODIFIER "d, stackTop=%" TCL_T_MODIFIER "d\n", + TclGetUInt4AtPtr(pc+1), (catchTop - initCatchTop - 1), + CURR_DEPTH)); NEXT_INST_F(5, 0, 0); break; case INST_END_CATCH: catchTop--; DECACHE_STACK_INFO(); Tcl_ResetResult(interp); CACHE_STACK_INFO(); result = TCL_OK; - TRACE(("=> catchTop=%d\n", (int) (catchTop - initCatchTop - 1))); + TRACE(("=> catchTop=%" TCL_Z_MODIFIER "u\n", (size_t)(catchTop - initCatchTop - 1))); NEXT_INST_F(1, 0, 0); break; case INST_PUSH_RESULT: objResultPtr = Tcl_GetObjResult(interp); @@ -6515,26 +6726,29 @@ * ----------------------------------------------------------------- * Start of dictionary-related instructions. */ { - int opnd2, allocateDict, done, i, allocdict; + int opnd2, allocateDict, done, allocdict; + Tcl_Size i; Tcl_Obj *dictPtr, *statePtr, *keyPtr, *listPtr, *varNamePtr, *keysPtr; Tcl_Obj *emptyPtr, **keyPtrPtr; Tcl_DictSearch *searchPtr; DictUpdateInfo *duiPtr; - case INST_DICT_VERIFY: + case INST_DICT_VERIFY: { + Tcl_Size size; dictPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(dictPtr))); - if (Tcl_DictObjSize(interp, dictPtr, &done) != TCL_OK) { + if (Tcl_DictObjSize(interp, dictPtr, &size) != TCL_OK) { TRACE_APPEND(("ERROR verifying dictionary nature of \"%.30s\": %s\n", O2S(dictPtr), O2S(Tcl_GetObjResult(interp)))); goto gotError; } TRACE_APPEND(("OK\n")); NEXT_INST_F(1, 1, 0); + } break; case INST_DICT_EXISTS: { int found; @@ -6592,11 +6806,11 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "key \"%s\" not known in dictionary", TclGetString(OBJ_AT_TOS))); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT", - TclGetString(OBJ_AT_TOS), NULL); + TclGetString(OBJ_AT_TOS), (void *)NULL); CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); @@ -6884,29 +7098,29 @@ if (Tcl_DictObjFirst(interp, dictPtr, searchPtr, &keyPtr, &valuePtr, &done) != TCL_OK) { /* * dictPtr is no longer on the stack, and we're not - * moving it into the intrep of an iterator. We need + * moving it into the internalrep of an iterator. We need * to drop the refcount [Tcl Bug 9b352768e6]. */ Tcl_DecrRefCount(dictPtr); Tcl_Free(searchPtr); TRACE_ERROR(interp); goto gotError; } { - Tcl_ObjIntRep ir; + Tcl_ObjInternalRep ir; TclNewObj(statePtr); ir.twoPtrValue.ptr1 = searchPtr; ir.twoPtrValue.ptr2 = dictPtr; - Tcl_StoreIntRep(statePtr, &dictIteratorType, &ir); + Tcl_StoreInternalRep(statePtr, &dictIteratorType, &ir); } varPtr = LOCAL(opnd); if (varPtr->value.objPtr) { - if (TclHasIntRep(varPtr->value.objPtr, &dictIteratorType)) { + if (TclHasInternalRep(varPtr->value.objPtr, &dictIteratorType)) { Tcl_Panic("mis-issued dictFirst!"); } TclDecrRefCount(varPtr->value.objPtr); } varPtr->value.objPtr = statePtr; @@ -6916,14 +7130,14 @@ case INST_DICT_NEXT: opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u => ", opnd)); statePtr = (*LOCAL(opnd)).value.objPtr; { - const Tcl_ObjIntRep *irPtr; + const Tcl_ObjInternalRep *irPtr; if (statePtr && - (irPtr = TclFetchIntRep(statePtr, &dictIteratorType))) { + (irPtr = TclFetchInternalRep(statePtr, &dictIteratorType))) { searchPtr = (Tcl_DictSearch *)irPtr->twoPtrValue.ptr1; Tcl_DictObjNext(searchPtr, &keyPtr, &valuePtr, &done); } else { Tcl_Panic("mis-issued dictNext!"); } @@ -6939,11 +7153,11 @@ } TRACE_APPEND(("\"%.30s\" \"%.30s\" %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), done)); /* - * The INST_DICT_FIRST and INST_DICT_NEXT instructsions are always + * The INST_DICT_FIRST and INST_DICT_NEXT instructions are always * followed by a conditional jump, so we can take advantage of this to * do some peephole optimization (note that we're careful to not close * out someone doing something else). */ @@ -6952,11 +7166,11 @@ case INST_DICT_UPDATE_START: opnd = TclGetUInt4AtPtr(pc+1); opnd2 = TclGetUInt4AtPtr(pc+5); TRACE(("%u => ", opnd)); varPtr = LOCAL(opnd); - duiPtr = (DictUpdateInfo *)codePtr->auxDataArrayPtr[opnd2].clientData; + duiPtr = (DictUpdateInfo *)BA_AuxData_At(codePtr->auxData, opnd2)->clientData; while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; @@ -6969,16 +7183,16 @@ TRACE_ERROR(interp); goto gotError; } } Tcl_IncrRefCount(dictPtr); - if (TclListObjGetElements(interp, OBJ_AT_TOS, &length, + if (TclListObjGetElementsM(interp, OBJ_AT_TOS, &length, &keyPtrPtr) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } - if ((size_t)length != duiPtr->length) { + if (length != duiPtr->length) { Tcl_Panic("dictUpdateStart argument length mismatch"); } for (i=0 ; i ", opnd)); varPtr = LOCAL(opnd); - duiPtr = (DictUpdateInfo *)codePtr->auxDataArrayPtr[opnd2].clientData; + duiPtr = (DictUpdateInfo *)BA_AuxData_At(codePtr->auxData, opnd2)->clientData; while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; @@ -7029,11 +7243,11 @@ if (dictPtr == NULL) { TRACE_APPEND(("storage was unset\n")); NEXT_INST_F(9, 1, 0); } if (Tcl_DictObjSize(interp, dictPtr, &length) != TCL_OK - || TclListObjGetElements(interp, OBJ_AT_TOS, &length, + || TclListObjGetElementsM(interp, OBJ_AT_TOS, &length, &keyPtrPtr) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } allocdict = Tcl_IsShared(dictPtr); @@ -7088,11 +7302,11 @@ case INST_DICT_EXPAND: dictPtr = OBJ_UNDER_TOS; listPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" \"%.30s\" =>", O2S(dictPtr), O2S(listPtr))); - if (TclListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { + if (TclListObjGetElementsM(interp, listPtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } objResultPtr = TclDictWithInit(interp, dictPtr, objc, objv); if (objResultPtr == NULL) { @@ -7106,11 +7320,11 @@ keysPtr = POP_OBJECT(); varNamePtr = OBJ_UNDER_TOS; listPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" \"%.30s\" \"%.30s\" => ", O2S(varNamePtr), O2S(valuePtr), O2S(keysPtr))); - if (TclListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { + if (TclListObjGetElementsM(interp, listPtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); TclDecrRefCount(keysPtr); goto gotError; } varPtr = TclObjLookupVarEx(interp, varNamePtr, NULL, @@ -7137,11 +7351,11 @@ listPtr = OBJ_UNDER_TOS; keysPtr = OBJ_AT_TOS; varPtr = LOCAL(opnd); TRACE(("%u <- \"%.30s\" \"%.30s\" => ", opnd, O2S(valuePtr), O2S(keysPtr))); - if (TclListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { + if (TclListObjGetElementsM(interp, listPtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; @@ -7166,29 +7380,29 @@ case INST_CLOCK_READ: { /* Read the wall clock */ Tcl_WideInt wval; Tcl_Time now; - switch(TclGetUInt1AtPtr(pc+1)) { + switch (TclGetUInt1AtPtr(pc+1)) { case 0: /* clicks */ #ifdef TCL_WIDE_CLICKS wval = TclpGetWideClicks(); #else - wval = (Tcl_WideInt) TclpGetClicks(); + wval = (Tcl_WideInt)TclpGetClicks(); #endif break; case 1: /* microseconds */ Tcl_GetTime(&now); - wval = (Tcl_WideInt) now.sec * 1000000 + now.usec; + wval = (Tcl_WideInt)now.sec * 1000000 + now.usec; break; case 2: /* milliseconds */ Tcl_GetTime(&now); - wval = (Tcl_WideInt) now.sec * 1000 + now.usec / 1000; + wval = (Tcl_WideInt)now.sec * 1000 + now.usec / 1000; break; case 3: /* seconds */ Tcl_GetTime(&now); - wval = (Tcl_WideInt) now.sec; + wval = (Tcl_WideInt)now.sec; break; default: Tcl_Panic("clockRead instruction with unknown clock#"); } TclNewIntObj(objResultPtr, wval); @@ -7258,23 +7472,23 @@ TclDecrRefCount(valuePtr); } if (result == TCL_BREAK) { result = TCL_OK; pc = (codePtr->codeStart + rangePtr->breakOffset); - TRACE_APPEND(("%s, range at %d, new pc %d\n", + TRACE_APPEND(("%s, range at %" TCL_SIZE_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n", StringForResultCode(result), rangePtr->codeOffset, rangePtr->breakOffset)); NEXT_INST_F(0, 0, 0); } - if (rangePtr->continueOffset == -1) { + if (rangePtr->continueOffset == TCL_INDEX_NONE) { TRACE_APPEND(("%s, loop w/o continue, checking for catch\n", StringForResultCode(result))); goto checkForCatch; } result = TCL_OK; pc = (codePtr->codeStart + rangePtr->continueOffset); - TRACE_APPEND(("%s, range at %d, new pc %d\n", + TRACE_APPEND(("%s, range at %" TCL_SIZE_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n", StringForResultCode(result), rangePtr->codeOffset, rangePtr->continueOffset)); NEXT_INST_F(0, 0, 0); } #ifdef TCL_COMPILE_DEBUG @@ -7297,18 +7511,18 @@ */ divideByZero: Tcl_SetObjResult(interp, Tcl_NewStringObj("divide by zero", -1)); DECACHE_STACK_INFO(); - Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", NULL); + Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", (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", NULL); + 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 @@ -7318,11 +7532,11 @@ exponOfZero: Tcl_SetObjResult(interp, Tcl_NewStringObj( "exponentiation of zero by negative power", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", - "exponentiation of zero by negative power", NULL); + "exponentiation of zero by negative power", (void *)NULL); CACHE_STACK_INFO(); /* * Almost all error paths feed through here rather than assigning to * result themselves (for a small but consistent saving). @@ -7343,11 +7557,11 @@ if (iPtr->execEnvPtr->rewind) { goto abnormalReturn; } if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { const unsigned char *pcBeg; - size_t xxx1length; + Tcl_Size xxx1length; bytes = GetSrcInfoForPc(pc, codePtr, &xxx1length, &pcBeg, NULL); DECACHE_STACK_INFO(); TclLogCommandInfo(interp, codePtr->source, bytes, bytes ? xxx1length : 0, pcBeg, tosPtr); @@ -7360,12 +7574,12 @@ * INST_BEGIN_CATCH. */ while (auxObjList) { if ((catchTop != initCatchTop) - && (*catchTop > (ptrdiff_t) - auxObjList->internalRep.twoPtrValue.ptr2)) { + && (PTR2INT(*catchTop) > + PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2))) { break; } POP_TAUX_OBJ(); } @@ -7436,20 +7650,20 @@ * its catchOffset after unwinding the operand stack to the depth it * had when starting to execute the range's catch command. */ processCatch: - while (CURR_DEPTH > *catchTop) { + while (CURR_DEPTH > PTR2INT(*catchTop)) { valuePtr = POP_OBJECT(); TclDecrRefCount(valuePtr); } #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { - fprintf(stdout, " ... found catch at %d, catchTop=%d, " - "unwound to %ld, new pc %u\n", - rangePtr->codeOffset, (int) (catchTop - initCatchTop - 1), - (long) *catchTop, (unsigned) rangePtr->catchOffset); + fprintf(stdout, " ... found catch at %" TCL_SIZE_MODIFIER "d, catchTop=%" TCL_T_MODIFIER "d, " + "unwound to %" TCL_T_MODIFIER "d, new pc %" TCL_SIZE_MODIFIER "d\n", + rangePtr->codeOffset, (catchTop - initCatchTop - 1), + PTR2INT(*catchTop), rangePtr->catchOffset); } #endif pc = (codePtr->codeStart + rangePtr->catchOffset); NEXT_INST_F(0, 0, 0); /* Restart the execution loop at pc. */ @@ -7481,14 +7695,14 @@ Tcl_DecrRefCount(objPtr); } if (tosPtr < initTosPtr) { fprintf(stderr, - "\nTclNRExecuteByteCode: abnormal return at pc %u: " - "stack top %d < entry stack top %d\n", - (unsigned)(pc - codePtr->codeStart), - (unsigned) CURR_DEPTH, (unsigned) 0); + "\nTclNRExecuteByteCode: abnormal return at pc %" TCL_T_MODIFIER "d: " + "stack top %" TCL_T_MODIFIER "d < entry stack top %d\n", + (pc - codePtr->codeStart), + CURR_DEPTH, 0); Tcl_Panic("TclNRExecuteByteCode execution failure: end stack top < start stack top"); } CLANG_ASSERT(bcFramePtr); } @@ -7510,11 +7724,11 @@ */ instStartCmdFailed: { const char *bytes; - size_t xxx1length; + Tcl_Size xxx1length; xxx1length = 0; if (TclInterpReady(interp) == TCL_ERROR) { goto gotError; @@ -7550,11 +7764,11 @@ #undef TCONST #undef esPtr static int FinalizeOONext( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; CallContext *contextPtr = (CallContext *)data[1]; @@ -7576,11 +7790,11 @@ return result; } static int FinalizeOONextFilter( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; CallContext *contextPtr = (CallContext *)data[1]; @@ -7722,18 +7936,18 @@ { #define WIDE_RESULT(w) \ if (Tcl_IsShared(valuePtr)) { \ return Tcl_NewWideIntObj(w); \ } else { \ - TclSetIntObj(valuePtr, w); \ + TclSetIntObj(valuePtr, (w)); \ return NULL; \ } #define BIG_RESULT(b) \ if (Tcl_IsShared(valuePtr)) { \ return Tcl_NewBignumObj(b); \ } else { \ - Tcl_SetBignumObj(valuePtr, b); \ + Tcl_SetBignumObj(valuePtr, (b)); \ return NULL; \ } #define DOUBLE_RESULT(d) \ if (Tcl_IsShared(valuePtr)) { \ TclNewDoubleObj(objResultPtr, (d)); \ @@ -7742,18 +7956,18 @@ Tcl_SetDoubleObj(valuePtr, (d)); \ return NULL; \ } int type1, type2; - ClientData ptr1, ptr2; + void *ptr1, *ptr2; double d1, d2, dResult; Tcl_WideInt w1, w2, wResult; mp_int big1, big2, bigResult, bigRemainder; Tcl_Obj *objResultPtr; int invalid, zero; - long shift; - mp_err err; + int shift; + mp_err err; (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1); (void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2); switch (opcode) { @@ -7792,25 +8006,26 @@ /* * Force Tcl's integer division rules. * TODO: examine for logic simplification */ - if (((wQuotient < (Tcl_WideInt) 0) - || ((wQuotient == (Tcl_WideInt) 0) + if (((wQuotient < 0) + || ((wQuotient == 0) && ((w1 < 0 && w2 > 0) || (w1 > 0 && w2 < 0)))) && (wQuotient * w2 != w1)) { - wQuotient -= (Tcl_WideInt) 1; + wQuotient -= 1; } - wRemainder = w1 - w2*wQuotient; + wRemainder = (Tcl_WideInt)((Tcl_WideUInt)w1 - + (Tcl_WideUInt)w2*(Tcl_WideUInt)wQuotient); WIDE_RESULT(wRemainder); } Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); /* TODO: internals intrusion */ - if ((w1 > ((Tcl_WideInt) 0)) ^ !mp_isneg(&big2)) { + if ((w1 > ((Tcl_WideInt)0)) ^ !mp_isneg(&big2)) { /* * Arguments are opposite sign; remainder is sum. */ err = mp_init_i64(&big1, w1); @@ -7831,11 +8046,11 @@ mp_clear(&big2); return NULL; } Tcl_GetBignumFromObj(NULL, valuePtr, &big1); Tcl_GetBignumFromObj(NULL, value2Ptr, &big2); - err = mp_init_multi(&bigResult, &bigRemainder, NULL); + err = mp_init_multi(&bigResult, &bigRemainder, (void *)NULL); if (err == MP_OKAY) { err = mp_div(&big1, &big2, &bigResult, &bigRemainder); } if ((err == MP_OKAY) && !mp_iszero(&bigRemainder) && (bigRemainder.sign != big2.sign)) { /* @@ -7919,13 +8134,13 @@ 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) + & -(((Tcl_WideUInt)1) << (CHAR_BIT*sizeof(Tcl_WideInt) - 1 - shift)))) { - WIDE_RESULT(w1 << shift); + WIDE_RESULT((Tcl_WideUInt)w1 << shift); } } } else { /* * Quickly force large right shifts to 0 or -1. @@ -8076,11 +8291,11 @@ return NULL; } negativeExponent = (w2 < 0); - oddExponent = (int) (w2 & (Tcl_WideInt)1); + oddExponent = (int)w2 & 1; } else { Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); negativeExponent = mp_isneg(&big2); err = mp_mod_2d(&big2, 1, &big2); oddExponent = (err == MP_OKAY) && !mp_iszero(&big2); @@ -8147,11 +8362,11 @@ /* * We refuse to accept exponent arguments that exceed one mp_digit * which means the max exponent value is 2**28-1 = 0x0FFFFFFF = * 268435455, which fits into a signed 32 bit int which is within the - * range of the long int type. This means any numeric Tcl_Obj value + * range of the Tcl_WideInt type. This means any numeric Tcl_Obj value * not using TCL_NUMBER_INT type must hold a value larger than we * accept. */ if (type2 != TCL_NUMBER_INT) { @@ -8166,12 +8381,12 @@ if (w1 == 2) { /* * Reduce small powers of 2 to shifts. */ - if ((Tcl_WideUInt) w2 < (Tcl_WideUInt) CHAR_BIT*sizeof(Tcl_WideInt) - 1) { - WIDE_RESULT(((Tcl_WideInt) 1) << (int)w2); + if ((Tcl_WideUInt)w2 < (Tcl_WideUInt)CHAR_BIT*sizeof(Tcl_WideInt) - 1) { + WIDE_RESULT(((Tcl_WideInt)1) << (int)w2); } goto overflowExpon; } if (w1 == -2) { int signum = oddExponent ? -1 : 1; @@ -8178,12 +8393,12 @@ /* * Reduce small powers of 2 to shifts. */ - if ((Tcl_WideUInt) w2 < CHAR_BIT * sizeof(Tcl_WideInt) - 1) { - WIDE_RESULT(signum * (((Tcl_WideInt) 1) << (int) w2)); + if ((Tcl_WideUInt)w2 < CHAR_BIT * sizeof(Tcl_WideInt) - 1) { + WIDE_RESULT(signum * (((Tcl_WideInt)1) << (int) w2)); } goto overflowExpon; } if (w2 - 2 < (long)MaxBase64Size && w1 <= MaxBase64[w2 - 2] @@ -8297,11 +8512,11 @@ #ifndef ACCEPT_NAN /* * Check now for IEEE floating-point error. */ - if (TclIsNaN(dResult)) { + if (isnan(dResult)) { TclExprFloatError(interp, dResult); return GENERAL_ARITHMETIC_ERROR; } #endif DOUBLE_RESULT(dResult); @@ -8310,11 +8525,11 @@ w1 = *((const Tcl_WideInt *)ptr1); w2 = *((const Tcl_WideInt *)ptr2); switch (opcode) { case INST_ADD: - wResult = w1 + w2; + wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2); if ((type1 == TCL_NUMBER_INT) || (type2 == TCL_NUMBER_INT)) { /* * Check for overflow. */ @@ -8324,11 +8539,11 @@ } } break; case INST_SUB: - wResult = w1 - w2; + 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 @@ -8444,11 +8659,11 @@ static Tcl_Obj * ExecuteExtendedUnaryMathOp( int opcode, /* What operation to perform. */ Tcl_Obj *valuePtr) /* The operand on the stack. */ { - ClientData ptr; + void *ptr = NULL; int type; Tcl_WideInt w; mp_int big; Tcl_Obj *objResultPtr; mp_err err = MP_OKAY; @@ -8524,11 +8739,11 @@ TclCompareTwoNumbers( Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr) { int type1 = TCL_NUMBER_NAN, type2 = TCL_NUMBER_NAN, compare; - ClientData ptr1, ptr2; + void *ptr1, *ptr2; mp_int big1, big2; double d1, d2, tmp; Tcl_WideInt w1, w2; (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1); @@ -8545,16 +8760,16 @@ case TCL_NUMBER_DOUBLE: d2 = *((const double *)ptr2); d1 = (double) w1; /* - * If the double has a fractional part, or if the long can be + * If the double has a fractional part, or if the Tcl_WideInt can be * converted to double without loss of precision, then compare as * doubles. */ - if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) || w1 == (Tcl_WideInt) d1 + if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) || w1 == (Tcl_WideInt)d1 || modf(d2, &tmp) != 0.0) { goto doubleCompare; } /* @@ -8573,11 +8788,11 @@ return MP_GT; } if (d2 > (double)WIDE_MAX) { return MP_LT; } - w2 = (Tcl_WideInt) d2; + w2 = (Tcl_WideInt)d2; goto wideCompare; case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); if (mp_isneg(&big2)) { compare = MP_GT; @@ -8598,23 +8813,23 @@ return (d1 < d2) ? MP_LT : ((d1 > d2) ? MP_GT : MP_EQ); case TCL_NUMBER_INT: w2 = *((const Tcl_WideInt *)ptr2); d2 = (double) w2; if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) - || w2 == (Tcl_WideInt) d2 || modf(d1, &tmp) != 0.0) { + || w2 == (Tcl_WideInt)d2 || modf(d1, &tmp) != 0.0) { goto doubleCompare; } if (d1 < (double)WIDE_MIN) { return MP_LT; } if (d1 > (double)WIDE_MAX) { return MP_GT; } - w1 = (Tcl_WideInt) d1; + w1 = (Tcl_WideInt)d1; goto wideCompare; case TCL_NUMBER_BIG: - if (TclIsInfinite(d1)) { + if (isinf(d1)) { return (d1 > 0.0) ? MP_GT : MP_LT; } Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); if ((d1 < (double)WIDE_MAX) && (d1 > (double)WIDE_MIN)) { if (mp_isneg(&big2)) { @@ -8623,11 +8838,11 @@ compare = MP_LT; } mp_clear(&big2); return compare; } - if (DBL_MANT_DIG > CHAR_BIT*sizeof(long) + if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) && modf(d1, &tmp) != 0.0) { d2 = TclBignumToDouble(&big2); mp_clear(&big2); goto doubleCompare; } @@ -8643,21 +8858,21 @@ compare = mp_cmp_d(&big1, 0); mp_clear(&big1); return compare; case TCL_NUMBER_DOUBLE: d2 = *((const double *)ptr2); - if (TclIsInfinite(d2)) { + if (isinf(d2)) { compare = (d2 > 0.0) ? MP_LT : MP_GT; mp_clear(&big1); return compare; } if ((d2 < (double)WIDE_MAX) && (d2 > (double)WIDE_MIN)) { compare = mp_cmp_d(&big1, 0); mp_clear(&big1); return compare; } - if (DBL_MANT_DIG > CHAR_BIT*sizeof(long) + if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) && modf(d2, &tmp) != 0.0) { d1 = TclBignumToDouble(&big1); mp_clear(&big1); goto doubleCompare; } @@ -8702,40 +8917,42 @@ ByteCode *codePtr) /* The bytecode whose summary is printed to * stdout. */ { Proc *procPtr = codePtr->procPtr; Interp *iPtr = (Interp *) *codePtr->interpHandle; + size_t numAuxDataItems = codePtr->auxData?BA_AuxData_Size(codePtr->auxData):0; 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", + 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, + numAuxDataItems, codePtr->maxStackDepth, #ifdef TCL_COMPILE_STATS codePtr->numSrcBytes? ((float)codePtr->structureSize)/codePtr->numSrcBytes : #endif 0.0); #ifdef TCL_COMPILE_STATS - fprintf(stdout, " Code %lu = header %lu+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n", - (unsigned long) codePtr->structureSize, - (unsigned long) (sizeof(ByteCode)-sizeof(size_t)-sizeof(Tcl_Time)), + fprintf(stdout, " Code %" TCL_Z_MODIFIER "u = header %" TCL_Z_MODIFIER "u+inst %" TCL_Z_MODIFIER + "u+litObj %" TCL_Z_MODIFIER "u+exc %" TCL_Z_MODIFIER "u+aux %" TCL_Z_MODIFIER "u+cmdMap %" TCL_Z_MODIFIER "u\n", + codePtr->structureSize, + offsetof(ByteCode, localCachePtr), codePtr->numCodeBytes, - (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)), - (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)), - (unsigned long) (codePtr->numAuxDataItems * sizeof(AuxData)), + codePtr->numLitObjects * sizeof(Tcl_Obj *), + codePtr->numExceptRanges*sizeof(ExceptionRange), + numAuxDataItems * sizeof(AuxData), codePtr->numCmdLocBytes); #endif /* TCL_COMPILE_STATS */ if (procPtr != NULL) { fprintf(stdout, - " Proc 0x%p, refCt %" TCL_Z_MODIFIER "u, args %d, compiled locals %d\n", + " Proc 0x%p, refCt %" TCL_Z_MODIFIER "u, args %" TCL_Z_MODIFIER "u, compiled locals %" TCL_Z_MODIFIER "u\n", procPtr, procPtr->refCount, procPtr->numArgs, procPtr->numCompiledLocals); } } #endif /* TCL_COMPILE_DEBUG */ @@ -8764,40 +8981,40 @@ 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 + size_t stackTop, /* Current stack top. Must be between * stackLowerBound and stackUpperBound * (inclusive). */ int checkStack) /* 0 if the stack depth check should be * skipped. */ { - int stackUpperBound = codePtr->maxStackDepth; + size_t stackUpperBound = codePtr->maxStackDepth; /* Greatest legal value for stackTop. */ - size_t relativePc = (size_t) (pc - codePtr->codeStart); - size_t codeStart = (size_t) codePtr->codeStart; + size_t relativePc = (size_t)(pc - codePtr->codeStart); + size_t codeStart = (size_t)codePtr->codeStart; size_t codeEnd = (size_t) (codePtr->codeStart + codePtr->numCodeBytes); unsigned char opCode = *pc; - if (((size_t) pc < codeStart) || ((size_t) pc > codeEnd)) { + if ((PTR2UINT(pc) < codeStart) || (PTR2UINT(pc) > codeEnd)) { fprintf(stderr, "\nBad instruction pc 0x%p in TclNRExecuteByteCode\n", pc); Tcl_Panic("TclNRExecuteByteCode execution failure: bad pc"); } - if ((unsigned) opCode >= LAST_INST_OPCODE) { - fprintf(stderr, "\nBad opcode %d at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode\n", - (unsigned) opCode, relativePc); + if (opCode >= LAST_INST_OPCODE) { + fprintf(stderr, "\nBad opcode %u at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode\n", + opCode, relativePc); Tcl_Panic("TclNRExecuteByteCode execution failure: bad opcode"); } if (checkStack && - ((stackTop < 0) || (stackTop > stackUpperBound))) { - size_t numChars; + (stackTop > stackUpperBound)) { + Tcl_Size numChars; const char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars, NULL, NULL); - fprintf(stderr, "\nBad stack top %d at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode (min 0, max %i)", + fprintf(stderr, "\nBad stack top %" TCL_Z_MODIFIER "u at pc %" TCL_Z_MODIFIER "u in TclNRExecuteByteCode (min 0, max %" TCL_Z_MODIFIER "u)", stackTop, relativePc, stackUpperBound); if (cmd != NULL) { Tcl_Obj *message; TclNewLiteralStringObj(message, "\n executing "); @@ -8838,11 +9055,11 @@ const unsigned char *pc, /* Points to the instruction being executed * when the illegal type was found. */ Tcl_Obj *opndPtr) /* Points to the operand holding the value * with the illegal type. */ { - ClientData ptr; + void *ptr; int type; const unsigned char opcode = *pc; const char *description, *op = "unknown"; if (opcode == INST_EXPON) { @@ -8863,11 +9080,11 @@ } 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); + Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, (void *)NULL); } /* *---------------------------------------------------------------------- * @@ -8939,12 +9156,12 @@ * there find the list of word locations for this command. */ ExtCmdLoc *eclPtr; ECL *locPtr = NULL; - size_t srcOffset; - int i; + Tcl_Size srcOffset; + Tcl_Size i; Interp *iPtr = (Interp *) *codePtr->interpHandle; Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr); if (!hePtr) { @@ -8986,32 +9203,32 @@ * return the closest command's source info. * This points within a bytecode instruction * in codePtr's code. */ ByteCode *codePtr, /* The bytecode sequence in which to look up * the command source for the pc. */ - size_t *lengthPtr, /* If non-NULL, the location where the length + Tcl_Size *lengthPtr, /* If non-NULL, the location where the length * of the command's source should be stored. * If NULL, no length is stored. */ const unsigned char **pcBeg,/* If non-NULL, the bytecode location * where the current instruction starts. * If NULL; no pointer is stored. */ - int *cmdIdxPtr) /* If non-NULL, the location where the index + Tcl_Size *cmdIdxPtr) /* If non-NULL, the location where the index * of the command containing the pc should * be stored. */ { - size_t pcOffset = (size_t)(pc - codePtr->codeStart); - size_t numCmds = codePtr->numCommands; + Tcl_Size pcOffset = pc - codePtr->codeStart; + Tcl_Size numCmds = codePtr->numCommands; unsigned char *codeDeltaNext, *codeLengthNext; unsigned char *srcDeltaNext, *srcLengthNext; - size_t codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i; - int bestDist = INT_MAX; /* Distance of pc to best cmd's start pc. */ - int bestSrcOffset = -1; /* Initialized to avoid compiler warning. */ - int bestSrcLength = -1; /* Initialized to avoid compiler warning. */ - int bestCmdIdx = -1; + Tcl_Size codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i; + Tcl_Size bestDist = TCL_SIZE_MAX; /* Distance of pc to best cmd's start pc. */ + Tcl_Size bestSrcOffset = -1; /* Initialized to avoid compiler warning. */ + Tcl_Size bestSrcLength = -1; /* Initialized to avoid compiler warning. */ + Tcl_Size bestCmdIdx = -1; /* The pc must point within the bytecode */ - assert (pcOffset < (size_t)codePtr->numCodeBytes); + assert ((pcOffset >= 0) && (pcOffset < codePtr->numCodeBytes)); /* * Decode the code and source offset and length for each command. The * closest enclosing command is the last one whose code started before * pcOffset. @@ -9083,20 +9300,20 @@ /* * Walk from beginning of command or BC to pc, by complete * instructions. Stop when crossing pc; keep previous. */ - curr = ((bestDist == INT_MAX) ? codePtr->codeStart : pc - bestDist); + curr = ((bestDist == TCL_SIZE_MAX) ? codePtr->codeStart : pc - bestDist); prev = curr; while (curr <= pc) { prev = curr; curr += tclInstructionTable[*curr].numBytes; } *pcBeg = prev; } - if (bestDist == INT_MAX) { + if (bestDist == TCL_SIZE_MAX) { return NULL; } if (lengthPtr != NULL) { *lengthPtr = bestSrcLength; @@ -9148,11 +9365,11 @@ * point or a catch range. */ ByteCode *codePtr) /* Points to the ByteCode in which to search * for the enclosing ExceptionRange. */ { ExceptionRange *rangeArrayPtr; - int numRanges = codePtr->numExceptRanges; + size_t numRanges = codePtr->numExceptRanges; ExceptionRange *rangePtr; size_t pcOffset = pc - codePtr->codeStart; size_t start; if (numRanges == 0) { @@ -9175,11 +9392,11 @@ return rangePtr; } if (searchMode == TCL_BREAK) { return rangePtr; } - if (searchMode == TCL_CONTINUE && rangePtr->continueOffset != -1){ + if (searchMode == TCL_CONTINUE && rangePtr->continueOffset != TCL_INDEX_NONE){ return rangePtr; } } } return NULL; @@ -9238,30 +9455,30 @@ double value) /* Value returned after error; used to * distinguish underflows from overflows. */ { const char *s; - if ((errno == EDOM) || TclIsNaN(value)) { + if ((errno == EDOM) || isnan(value)) { s = "domain error: argument not in valid range"; Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1)); - Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, NULL); - } else if ((errno == ERANGE) || TclIsInfinite(value)) { + Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, (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, NULL); + 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, NULL); + 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), NULL); + TclGetString(objPtr), (void *)NULL); Tcl_SetObjResult(interp, objPtr); } } #ifdef TCL_COMPILE_STATS @@ -9286,18 +9503,14 @@ int TclLog2( int value) /* The integer for which to compute the log * base 2. */ { - int n = value; - int result = 0; - - while (n > 1) { - n = n >> 1; - result++; - } - return result; + if (value == 0) { + return 0; + } + return TclMSB(value); } /* *---------------------------------------------------------------------- * @@ -9315,11 +9528,11 @@ *---------------------------------------------------------------------- */ static int EvalStatsCmd( - ClientData unused, /* Unused. */ + TCL_UNUSED(void *), /* Unused. */ Tcl_Interp *interp, /* The current interpreter. */ int objc, /* The number of arguments. */ Tcl_Obj *const objv[]) /* The argument strings. */ { Interp *iPtr = (Interp *) interp; @@ -9330,11 +9543,13 @@ double objBytesIfUnshared, strBytesIfUnshared, sharingBytesSaved; double strBytesSharedMultX, strBytesSharedOnce; double numInstructions, currentHeaderBytes; size_t numCurrentByteCodes, numByteCodeLits; size_t refCountSum, literalMgmtBytes, sum, decadeHigh, length; - size_t numSharedMultX, numSharedOnce, minSizeDecade, maxSizeDecade, i; + size_t numSharedMultX, numSharedOnce, minSizeDecade, maxSizeDecade; + Tcl_Size i; + size_t ui; char *litTableStats; LiteralEntry *entryPtr; Tcl_Obj *objPtr; #define Percent(a,b) ((a) * 100.0 / (b)) @@ -9357,11 +9572,11 @@ totalCodeBytes = statsPtr->totalByteCodeBytes + totalLiteralBytes; numCurrentByteCodes = statsPtr->numCompilations - statsPtr->numByteCodesFreed; currentHeaderBytes = numCurrentByteCodes - * (sizeof(ByteCode) - sizeof(size_t) - sizeof(Tcl_Time)); + * offsetof(ByteCode, localCachePtr); literalMgmtBytes = sizeof(LiteralTable) + (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)) + (iPtr->literalTable.numEntries * sizeof(LiteralEntry)); currentLiteralBytes = literalMgmtBytes + iPtr->literalTable.numEntries * sizeof(Tcl_Obj) @@ -9466,17 +9681,17 @@ numSharedOnce = 0; objBytesIfUnshared = 0.0; strBytesIfUnshared = 0.0; strBytesSharedMultX = 0.0; strBytesSharedOnce = 0.0; - for (i = 0; i < globalTablePtr->numBuckets; i++) { + for (ui = 0; ui < globalTablePtr->numBuckets; ui++) { for (entryPtr = globalTablePtr->buckets[i]; entryPtr != NULL; entryPtr = entryPtr->nextPtr) { - if (TclHasIntRep(entryPtr->objPtr, &tclByteCodeType)) { + if (TclHasInternalRep(entryPtr->objPtr, &tclByteCodeType)) { numByteCodeLits++; } - (void) TclGetStringFromObj(entryPtr->objPtr, &length); + (void) Tcl_GetStringFromObj(entryPtr->objPtr, &length); refCountSum += entryPtr->refCount; objBytesIfUnshared += (entryPtr->refCount * sizeof(Tcl_Obj)); strBytesIfUnshared += (entryPtr->refCount * (length+1)); if (entryPtr->refCount > 1) { numSharedMultX++; @@ -9495,11 +9710,11 @@ Tcl_AppendPrintfToObj(objPtr, "Current objects\t\t\t%" TCL_Z_MODIFIER "u\n", (tclObjsAlloced - tclObjsFreed)); Tcl_AppendPrintfToObj(objPtr, "Total literal objects\t\t%" TCL_Z_MODIFIER "u\n", statsPtr->numLiteralsCreated); - Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects\t\t%" TCL_Z_MODIFIER "u (%0.1f%% of current objects)\n", + Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects\t\t%" TCL_SIZE_MODIFIER "d (%0.1f%% of current objects)\n", globalTablePtr->numEntries, Percent(globalTablePtr->numEntries, tclObjsAlloced-tclObjsFreed)); Tcl_AppendPrintfToObj(objPtr, " ByteCode literals\t\t%" TCL_Z_MODIFIER "u (%0.1f%% of current literals)\n", numByteCodeLits, Percent(numByteCodeLits, globalTablePtr->numEntries)); @@ -9584,14 +9799,14 @@ maxSizeDecade = i; break; } } sum = 0; - for (i = 0; i <= maxSizeDecade; i++) { - decadeHigh = (1 << (i+1)) - 1; - sum += statsPtr->literalCount[i]; - Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_Z_MODIFIER "u\t\t%8.0f%%\n", + for (ui = 0; ui <= maxSizeDecade; ui++) { + decadeHigh = (1 << (ui+1)) - 1; + sum += statsPtr->literalCount[ui]; + Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n", decadeHigh, Percent(sum, statsPtr->numLiteralsCreated)); } litTableStats = TclLiteralStats(globalTablePtr); Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal table statistics:\n%s\n", @@ -9609,21 +9824,22 @@ if (statsPtr->srcCount[i] > 0) { minSizeDecade = i; break; } } - for (i = 31; i >= 0; i--) { + for (i = 31; i != TCL_INDEX_NONE; i--) { if (statsPtr->srcCount[i] > 0) { - maxSizeDecade = i; - break; + break; /* maxSizeDecade to consume 'i' value + * below... */ } } + maxSizeDecade = i; sum = 0; - for (i = minSizeDecade; i <= maxSizeDecade; i++) { - decadeHigh = (1 << (i+1)) - 1; - sum += statsPtr->srcCount[i]; - Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_Z_MODIFIER "u\t\t%8.0f%%\n", + for (ui = minSizeDecade; ui <= maxSizeDecade; ui++) { + decadeHigh = (1 << (ui+1)) - 1; + sum += statsPtr->srcCount[ui]; + Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n", decadeHigh, Percent(sum, statsPtr->numCompilations)); } Tcl_AppendPrintfToObj(objPtr, "\nByteCode sizes:\n"); Tcl_AppendPrintfToObj(objPtr, "\t Up to size\t\tPercentage\n"); @@ -9632,21 +9848,22 @@ if (statsPtr->byteCodeCount[i] > 0) { minSizeDecade = i; break; } } - for (i = 31; i >= 0; i--) { + for (i = 31; i != TCL_INDEX_NONE; i--) { if (statsPtr->byteCodeCount[i] > 0) { - maxSizeDecade = i; - break; + break; /* maxSizeDecade to consume 'i' value + * below... */ } } + maxSizeDecade = i; sum = 0; - for (i = minSizeDecade; i <= maxSizeDecade; i++) { - decadeHigh = (1 << (i+1)) - 1; - sum += statsPtr->byteCodeCount[i]; - Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_Z_MODIFIER "u\t\t%8.0f%%\n", + for (ui = minSizeDecade; ui <= maxSizeDecade; i++) { + decadeHigh = (1 << (ui+1)) - 1; + sum += statsPtr->byteCodeCount[ui]; + Tcl_AppendPrintfToObj(objPtr, "\t%10" TCL_SIZE_MODIFIER "d\t\t%8.0f%%\n", decadeHigh, Percent(sum, statsPtr->numCompilations)); } Tcl_AppendPrintfToObj(objPtr, "\nByteCode longevity (excludes Current ByteCodes):\n"); Tcl_AppendPrintfToObj(objPtr, "\t Up to ms\t\tPercentage\n"); @@ -9655,20 +9872,21 @@ if (statsPtr->lifetimeCount[i] > 0) { minSizeDecade = i; break; } } - for (i = 31; i >= 0; i--) { + for (i = 31; i != TCL_INDEX_NONE; i--) { if (statsPtr->lifetimeCount[i] > 0) { - maxSizeDecade = i; - break; + break; /* maxSizeDecade to consume 'i' value + * below... */ } } + maxSizeDecade = i; sum = 0; - for (i = minSizeDecade; i <= maxSizeDecade; i++) { - decadeHigh = (1 << (i+1)) - 1; - sum += statsPtr->lifetimeCount[i]; + for (ui = minSizeDecade; ui <= maxSizeDecade; ui++) { + decadeHigh = (1 << (ui+1)) - 1; + sum += statsPtr->lifetimeCount[ui]; Tcl_AppendPrintfToObj(objPtr, "\t%12.3f\t\t%8.0f%%\n", decadeHigh/1000.0, Percent(sum, statsPtr->numByteCodesFreed)); } /* @@ -9695,11 +9913,11 @@ if (objc == 1) { Tcl_SetObjResult(interp, objPtr); } else { Tcl_Channel outChan; - char *str = TclGetStringFromObj(objv[1], &length); + char *str = Tcl_GetStringFromObj(objv[1], &length); if (length) { if (strcmp(str, "stdout") == 0) { outChan = Tcl_GetStdChannel(TCL_STDOUT); } else if (strcmp(str, "stderr") == 0) { Index: generic/tclFCmd.c ================================================================== --- generic/tclFCmd.c +++ generic/tclFCmd.c @@ -2,11 +2,11 @@ * tclFCmd.c * * This file implements the generic portion of file manipulation * subcommands of the "file" command. * - * Copyright (c) 1996-1998 Sun Microsystems, Inc. + * Copyright © 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -45,11 +45,11 @@ *--------------------------------------------------------------------------- */ int TclFileRenameCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interp for error reporting or recursive * calls in the case of a tricky rename. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings passed to Tcl_FileCmd. */ { @@ -74,11 +74,11 @@ *--------------------------------------------------------------------------- */ int TclFileCopyCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Used for error reporting or recursive calls * in the case of a tricky copy. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings passed to Tcl_FileCmd. */ { @@ -212,17 +212,18 @@ *---------------------------------------------------------------------- */ int TclFileMakeDirsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Used for error reporting. */ int objc, /* Number of arguments */ Tcl_Obj *const objv[]) /* Argument strings passed to Tcl_FileCmd. */ { Tcl_Obj *errfile = NULL; - int result, i, j, pobjc; + int result, i; + Tcl_Size j, pobjc; Tcl_Obj *split = NULL; Tcl_Obj *target = NULL; Tcl_StatBuf statBuf; result = TCL_OK; @@ -336,11 +337,11 @@ *---------------------------------------------------------------------- */ int TclFileDeleteCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Used for error reporting */ int objc, /* Number of arguments */ Tcl_Obj *const objv[]) /* Argument strings passed to Tcl_FileCmd. */ { int i, force, result; @@ -423,11 +424,11 @@ } } if (result != TCL_OK) { if (errfile == NULL) { /* - * We try to accomodate poor error results from our Tcl_FS calls. + * We try to accommodate poor error results from our Tcl_FS calls. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error deleting unknown file: %s", Tcl_PosixError(interp))); @@ -868,32 +869,23 @@ *--------------------------------------------------------------------------- */ static Tcl_Obj * FileBasename( - Tcl_Interp *interp, /* Interp, for error return. */ + TCL_UNUSED(Tcl_Interp *), /* Interp, for error return. */ Tcl_Obj *pathPtr) /* Path whose basename to extract. */ { - int objc; + Tcl_Size objc; Tcl_Obj *splitPtr; Tcl_Obj *resultPtr = NULL; splitPtr = Tcl_FSSplitPath(pathPtr, &objc); Tcl_IncrRefCount(splitPtr); if (objc != 0) { - if ((objc == 1) && (*TclGetString(pathPtr) == '~')) { - Tcl_DecrRefCount(splitPtr); - if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) { - return NULL; - } - splitPtr = Tcl_FSSplitPath(pathPtr, &objc); - Tcl_IncrRefCount(splitPtr); - } - - /* - * Return the last component, unless it is the only component, and it + /* + * 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); @@ -944,20 +936,20 @@ *---------------------------------------------------------------------- */ int TclFileAttrsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* The interpreter for error reporting. */ int objc, /* Number of command line arguments. */ Tcl_Obj *const objv[]) /* The command line objects. */ { int result; const char *const *attributeStrings; const char **attributeStringsAllocated = NULL; Tcl_Obj *objStrings = NULL; - int numObjStrings = -1; + Tcl_Size numObjStrings = TCL_INDEX_NONE; Tcl_Obj *filePtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "name ?-option value ...?"); return TCL_ERROR; @@ -977,11 +969,11 @@ * Get the set of attribute names from the filesystem. */ attributeStrings = Tcl_FSFileAttrStrings(filePtr, &objStrings); if (attributeStrings == NULL) { - int index; + Tcl_Size index; Tcl_Obj *objPtr; if (objStrings == NULL) { if (Tcl_GetErrno() != 0) { /* @@ -1004,11 +996,11 @@ /* * Use objStrings as a list object. */ - if (Tcl_ListObjLength(interp, objStrings, &numObjStrings) != TCL_OK) { + if (TclListObjLengthM(interp, objStrings, &numObjStrings) != TCL_OK) { goto end; } attributeStringsAllocated = (const char **) TclStackAlloc(interp, (1+numObjStrings) * sizeof(char *)); for (index = 0; index < numObjStrings; index++) { @@ -1078,11 +1070,11 @@ if (numObjStrings == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\", there are no file attributes in this" " filesystem", TclGetString(objv[0]))); - Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", NULL); + Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", (void *)NULL); goto end; } if (Tcl_GetIndexFromObj(interp, objv[0], attributeStrings, "option", TCL_INDEX_TEMP_TABLE, &index) != TCL_OK) { @@ -1102,11 +1094,11 @@ if (numObjStrings == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\", there are no file attributes in this" " filesystem", TclGetString(objv[0]))); - Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", NULL); + Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", (void *)NULL); goto end; } for (i = 0; i < objc ; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], attributeStrings, @@ -1115,11 +1107,11 @@ } if (i + 1 == objc) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "value for \"%s\" missing", TclGetString(objv[i]))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FATTR", - "NOVALUE", NULL); + "NOVALUE", (void *)NULL); goto end; } if (Tcl_FSFileAttrsSet(interp, index, filePtr, objv[i + 1]) != TCL_OK) { goto end; @@ -1160,11 +1152,11 @@ *---------------------------------------------------------------------- */ int TclFileLinkCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *contents; @@ -1218,11 +1210,11 @@ contents = Tcl_FSLink(objv[index], objv[index+1], linkAction); if (contents == NULL) { /* * We handle three common error cases specially, and for all other - * errors, we use the standard posix error message. + * errors, we use the standard Posix error message. */ if (errno == EEXIST) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not create new link \"%s\": that path already" @@ -1311,11 +1303,11 @@ *---------------------------------------------------------------------- */ int TclFileReadLinkCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *contents; @@ -1362,11 +1354,11 @@ *--------------------------------------------------------------------------- */ int TclFileTemporaryCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *nameVarObj = NULL; /* Variable to store the name of the temporary @@ -1387,13 +1379,13 @@ if (objc > 1) { nameVarObj = objv[1]; TclNewObj(nameObj); } if (objc > 2) { - size_t length; + Tcl_Size length; Tcl_Obj *templateObj = objv[2]; - const char *string = TclGetStringFromObj(templateObj, &length); + const char *string = Tcl_GetStringFromObj(templateObj, &length); /* * Treat an empty string as if it wasn't there. */ @@ -1521,11 +1513,11 @@ *--------------------------------------------------------------------------- */ int TclFileTempDirCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *dirNameObj; /* Object that will contain the directory @@ -1539,13 +1531,13 @@ Tcl_WrongNumArgs(interp, 1, objv, "?template?"); return TCL_ERROR; } if (objc > 1) { - int length; + Tcl_Size length; Tcl_Obj *templateObj = objv[1]; - const char *string = TclGetStringFromObj(templateObj, &length); + const char *string = Tcl_GetStringFromObj(templateObj, &length); const int onWindows = (tclPlatform == TCL_PLATFORM_WINDOWS); /* * Treat an empty string as if it wasn't there. */ @@ -1646,13 +1638,89 @@ 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: */ Index: generic/tclFileName.c ================================================================== --- generic/tclFileName.c +++ generic/tclFileName.c @@ -2,12 +2,12 @@ * tclFileName.c -- * * This file contains routines for converting file names betwen native * and network form. * - * Copyright (c) 1995-1998 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1995-1998 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -24,21 +24,27 @@ /* * Prototypes for local procedures defined in this file: */ -static const char * DoTildeSubst(Tcl_Interp *interp, - const char *user, Tcl_DString *resultPtr); static const char * ExtractWinRoot(const char *path, Tcl_DString *resultPtr, int offset, Tcl_PathType *typePtr); static int SkipToChar(char **stringPtr, int match); static Tcl_Obj * SplitWinPath(const char *path); static Tcl_Obj * SplitUnixPath(const char *path); static int DoGlob(Tcl_Interp *interp, Tcl_Obj *resultPtr, const char *separators, Tcl_Obj *pathPtr, int flags, char *pattern, Tcl_GlobTypeData *types); +static int TclGlob(Tcl_Interp *interp, char *pattern, + Tcl_Obj *pathPrefix, int globFlags, + Tcl_GlobTypeData *types); + +/* Flag values used by TclGlob() */ + +#define TCL_GLOBMODE_DIR 4 +#define TCL_GLOBMODE_TAILS 8 /* * When there is no support for getting the block size of a file in a stat() * call, use this as a guess. Allow it to be overridden in the platform- * specific files. @@ -87,11 +93,11 @@ * specified Tcl_DString. * * Results: * Returns the position in the path immediately after the root including * any trailing slashes. Appends a cleaned up version of the root to the - * Tcl_DString at the specified offest. + * Tcl_DString at the specified offset. * * Side effects: * Modifies the specified Tcl_DString. * *---------------------------------------------------------------------- @@ -240,11 +246,11 @@ * May have match for 'com[1-9]:?', which is a serial port. */ if (path[4] == '\0') { abs = 4; - } else if (path [4] == ':' && path[5] == '\0') { + } else if (path[4] == ':' && path[5] == '\0') { abs = 5; } } else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') { /* @@ -262,11 +268,11 @@ * May have match for 'lpt[1-9]:?' */ if (path[4] == '\0') { abs = 4; - } else if (path [4] == ':' && path[5] == '\0') { + } else if (path[4] == ':' && path[5] == '\0') { abs = 5; } } } else if ((path[0] == 'p' || path[0] == 'P') @@ -360,16 +366,10 @@ * 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: @@ -379,92 +379,64 @@ */ Tcl_PathType TclpGetNativePathType( Tcl_Obj *pathPtr, /* Native path of interest */ - int *driveNameLengthPtr, /* Returns length of drive, if non-NULL and - * path was absolute */ + Tcl_Size *driveNameLengthPtr, /* Returns length of drive, if non-NULL and + * path was absolute */ Tcl_Obj **driveNameRef) { Tcl_PathType type = TCL_PATH_ABSOLUTE; const char *path = TclGetString(pathPtr); - if (path[0] == '~') { - /* - * This case is common to all platforms. Paths that begin with ~ are - * absolute. - */ - - if (driveNameLengthPtr != NULL) { - const char *end = path + 1; - while ((*end != '\0') && (*end != '/')) { - end++; - } - *driveNameLengthPtr = end - path; - } - } else { - switch (tclPlatform) { - case TCL_PLATFORM_UNIX: { - const char *origPath = path; - - /* - * 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; - } - } + 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; } /* @@ -491,11 +463,11 @@ */ Tcl_Obj * TclpNativeSplitPath( Tcl_Obj *pathPtr, /* Path to split. */ - int *lenPtr) /* int to store number of path elements. */ + Tcl_Size *lenPtr) /* int to store number of path elements. */ { Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */ /* * Perform platform specific splitting. @@ -514,11 +486,11 @@ /* * Compute the number of elements in the result. */ if (lenPtr != NULL) { - Tcl_ListObjLength(NULL, resultPtr, lenPtr); + TclListObjLengthM(NULL, resultPtr, lenPtr); } return resultPtr; } /* @@ -544,22 +516,22 @@ * Allocates memory. * *---------------------------------------------------------------------- */ +#undef Tcl_SplitPath void Tcl_SplitPath( const char *path, /* Pointer to string containing a path. */ - int *argcPtr, /* Pointer to location to fill in with the + Tcl_Size *argcPtr, /* Pointer to location to fill in with the * number of elements in the path. */ const char ***argvPtr) /* Pointer to place to store pointer to array * of pointers to path elements. */ { Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */ Tcl_Obj *tmpPtr, *eltPtr; - int i; - size_t size, len; + Tcl_Size i, size, len; char *p; const char *str; /* * Perform the splitting, using objectified, vfs-aware code. @@ -576,11 +548,11 @@ */ size = 1; for (i = 0; i < *argcPtr; i++) { Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr); - (void)TclGetStringFromObj(eltPtr, &len); + (void)Tcl_GetStringFromObj(eltPtr, &len); size += len + 1; } /* * Allocate a buffer large enough to hold the contents of all of the list @@ -596,11 +568,11 @@ */ p = (char *) &(*argvPtr)[(*argcPtr) + 1]; for (i = 0; i < *argcPtr; i++) { Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr); - str = TclGetStringFromObj(eltPtr, &len); + str = Tcl_GetStringFromObj(eltPtr, &len); memcpy(p, str, len + 1); p += len+1; } /* @@ -653,42 +625,28 @@ 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. + * Split on slashes. */ for (;;) { elementStart = path; while ((*path != '\0') && (*path != '/')) { @@ -695,17 +653,12 @@ 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); + nextElt = Tcl_NewStringObj(elementStart, length); + Tcl_ListObjAppendElement(NULL, result, nextElt); } if (*path++ == '\0') { break; } } @@ -746,18 +699,16 @@ /* * Terminate the root portion, if we matched something. */ if (p != path) { - Tcl_ListObjAppendElement(NULL, result, TclDStringToObj(&buf)); + Tcl_ListObjAppendElement(NULL, result, Tcl_DStringToObj(&buf)); } Tcl_DStringFree(&buf); /* - * Split on slashes. Embedded elements that start with tilde or a drive - * letter will be prefixed with "./" so they are not affected by tilde - * substitution. + * Split on slashes. */ do { elementStart = p; while ((*p != '\0') && (*p != '/') && (*p != '\\')) { @@ -764,13 +715,13 @@ p++; } length = p - elementStart; if (length > 0) { Tcl_Obj *nextElt; - if ((elementStart != path) && ((elementStart[0] == '~') - || (isalpha(UCHAR(elementStart[0])) - && elementStart[1] == ':'))) { + if ((elementStart != path) && + isalpha(UCHAR(elementStart[0])) && + (elementStart[1] == ':')) { TclNewLiteralStringObj(nextElt, "./"); Tcl_AppendToObj(nextElt, elementStart, length); } else { nextElt = Tcl_NewStringObj(elementStart, length); } @@ -805,11 +756,11 @@ */ Tcl_Obj * Tcl_FSJoinToPath( Tcl_Obj *pathPtr, /* Valid path or NULL. */ - int objc, /* Number of array elements to join */ + Tcl_Size objc, /* Number of array elements to join */ Tcl_Obj *const objv[]) /* Path elements to join. */ { if (pathPtr == NULL) { return TclJoinPath(objc, objv, 0); } @@ -821,11 +772,11 @@ pair[0] = pathPtr; pair[1] = objv[0]; return TclJoinPath(2, pair, 0); } else { - int elemc = objc + 1; + Tcl_Size elemc = objc + 1; Tcl_Obj *ret, **elemv = (Tcl_Obj**)Tcl_Alloc(elemc*sizeof(Tcl_Obj *)); elemv[0] = pathPtr; memcpy(elemv+1, objv, objc*sizeof(Tcl_Obj *)); ret = TclJoinPath(elemc, elemv, 0); @@ -854,28 +805,28 @@ TclpNativeJoinPath( Tcl_Obj *prefix, const char *joining) { int needsSep; - size_t length; + Tcl_Size length; char *dest; const char *p; const char *start; - start = TclGetStringFromObj(prefix, &length); + start = Tcl_GetStringFromObj(prefix, &length); /* - * Remove the ./ from tilde prefixed elements, and drive-letter prefixed + * Remove the ./ from drive-letter prefixed * elements on Windows, unless it is the first component. */ p = joining; if (length != 0) { - if ((p[0] == '.') && (p[1] == '/') && ((p[2] == '~') - || (tclPlatform==TCL_PLATFORM_WINDOWS && isalpha(UCHAR(p[2])) - && (p[3] == ':')))) { + if ((p[0] == '.') && (p[1] == '/') && + (tclPlatform==TCL_PLATFORM_WINDOWS) && isalpha(UCHAR(p[2])) + && (p[3] == ':')) { p += 2; } } if (*p == '\0') { return; @@ -887,19 +838,19 @@ * Append a separator if needed. */ if (length > 0 && (start[length-1] != '/')) { Tcl_AppendToObj(prefix, "/", 1); - (void)TclGetStringFromObj(prefix, &length); + (void)Tcl_GetStringFromObj(prefix, &length); } needsSep = 0; /* * Append the element, eliminating duplicate and trailing slashes. */ - Tcl_SetObjLength(prefix, length + (int) strlen(p)); + Tcl_SetObjLength(prefix, length + strlen(p)); dest = TclGetString(prefix) + length; for (; *p != '\0'; p++) { if (*p == '/') { while (p[1] == '/') { @@ -923,11 +874,11 @@ */ if ((length > 0) && (start[length-1] != '/') && (start[length-1] != ':')) { Tcl_AppendToObj(prefix, "/", 1); - (void)TclGetStringFromObj(prefix, &length); + (void)Tcl_GetStringFromObj(prefix, &length); } needsSep = 0; /* * Append the element, eliminating duplicate and trailing slashes. @@ -974,16 +925,15 @@ *---------------------------------------------------------------------- */ char * Tcl_JoinPath( - int argc, + Tcl_Size argc, const char *const *argv, Tcl_DString *resultPtr) /* Pointer to previously initialized DString */ { - int i; - size_t len; + Tcl_Size i, len; Tcl_Obj *listObj; Tcl_Obj *resultObj; const char *resultStr; /* @@ -1007,11 +957,11 @@ /* * Store the result. */ - resultStr = TclGetStringFromObj(resultObj, &len); + resultStr = Tcl_GetStringFromObj(resultObj, &len); Tcl_DStringAppend(resultPtr, resultStr, len); Tcl_DecrRefCount(resultObj); /* * Return a pointer to the result. @@ -1024,23 +974,19 @@ *--------------------------------------------------------------------------- * * 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. + * interfaces. * * Results: - * The return value is a pointer to a string containing the name after - * tilde substitution. If there was no tilde substitution, the return - * value is a pointer to a copy of the original string. If there was an + * The return value is a pointer to a string containing the name. + * This may either be the name pointer passed in or space allocated in + * bufferPtr. In all cases, if the return value is not NULL, the caller + * must call Tcl_DStringFree() to free the space. If there was an * error in processing the name, then an error message is left in the * interp's result (if interp was not NULL) and the return value is NULL. - * Space for the return value is allocated in bufferPtr; the caller must - * call Tcl_DStringFree() to free the space if the return value was not - * NULL. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -1053,11 +999,11 @@ const char *name, /* File name, which may begin with "~" (to * indicate current user's home directory) or * "~" (to indicate any user's home * directory). */ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with - * name after tilde substitution. */ + * name. */ { Tcl_Obj *path = Tcl_NewStringObj(name, -1); Tcl_Obj *transPtr; Tcl_IncrRefCount(path); @@ -1148,69 +1094,10 @@ } /* *---------------------------------------------------------------------- * - * 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. * @@ -1223,16 +1110,17 @@ *---------------------------------------------------------------------- */ int Tcl_GlobObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int index, i, globFlags, length, join, dir, result; + int i, globFlags, join, dir, result; + Tcl_Size length; char *string; const char *separators; Tcl_Obj *typePtr, *look; Tcl_Obj *pathOrDir = NULL; Tcl_DString prefix; @@ -1241,21 +1129,21 @@ "-types", "--", NULL }; enum globOptionsEnum { GLOB_DIR, GLOB_JOIN, GLOB_NOCOMPLAIN, GLOB_PATH, GLOB_TAILS, GLOB_TYPE, GLOB_LAST - }; + } index; enum pathDirOptions {PATH_NONE = -1 , PATH_GENERAL = 0, PATH_DIR = 1}; Tcl_GlobTypeData *globTypes = NULL; globFlags = 0; join = 0; dir = PATH_NONE; typePtr = NULL; for (i = 1; i < objc; i++) { - if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[i], options, + "option", 0, &index) != TCL_OK) { string = TclGetString(objv[i]); if (string[0] == '-') { /* * It looks like the command contains an option so signal an * error. @@ -1271,29 +1159,32 @@ Tcl_ResetResult(interp); break; } } - switch ((enum globOptionsEnum) index) { + switch (index) { case GLOB_NOCOMPLAIN: /* -nocomplain */ - globFlags |= TCL_GLOBMODE_NO_COMPLAIN; + /* + * Do nothing; This is normal operations in Tcl 9. + * Keep accepting as a no-op option to accommodate old scripts. + */ break; case GLOB_DIR: /* -dir */ if (i == (objc-1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing argument to \"-directory\"", -1)); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (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", NULL); + "BADOPTIONCOMBINATION", (void *)NULL); return TCL_ERROR; } dir = PATH_DIR; globFlags |= TCL_GLOBMODE_DIR; pathOrDir = objv[i+1]; @@ -1307,21 +1198,21 @@ break; case GLOB_PATH: /* -path */ if (i == (objc-1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing argument to \"-path\"", -1)); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (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", NULL); + "BADOPTIONCOMBINATION", (void *)NULL); return TCL_ERROR; } dir = PATH_GENERAL; pathOrDir = objv[i+1]; i++; @@ -1328,15 +1219,15 @@ break; case GLOB_TYPE: /* -types */ if (i == (objc-1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing argument to \"-types\"", -1)); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", (void *)NULL); return TCL_ERROR; } typePtr = objv[i+1]; - if (Tcl_ListObjLength(interp, typePtr, &length) != TCL_OK) { + if (TclListObjLengthM(interp, typePtr, &length) != TCL_OK) { return TCL_ERROR; } i++; break; case GLOB_LAST: /* -- */ @@ -1349,11 +1240,11 @@ if ((globFlags & TCL_GLOBMODE_TAILS) && (pathOrDir == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-tails\" must be used with either " "\"-directory\" or \"-path\"", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", - "BADOPTIONCOMBINATION", NULL); + "BADOPTIONCOMBINATION", (void *)NULL); return TCL_ERROR; } separators = NULL; switch (tclPlatform) { @@ -1364,13 +1255,13 @@ separators = "/\\:"; break; } if (dir == PATH_GENERAL) { - size_t pathlength; + Tcl_Size pathlength; const char *last; - const char *first = TclGetStringFromObj(pathOrDir,&pathlength); + const char *first = Tcl_GetStringFromObj(pathOrDir,&pathlength); /* * Find the last path separator in the path */ @@ -1413,15 +1304,19 @@ /* * We must ensure that we haven't cut off too much, and turned * a valid path like '/' or 'C:/' into an incorrect path like * '' or 'C:'. The way we do this is to add a separator if - * there are none presently in the prefix. + * there are none presently in the prefix. Similar treatment + * for the zipfs volume. */ - if (strpbrk(TclGetString(pathOrDir), "\\/") == NULL) { + const char *temp = TclGetString(pathOrDir); + if (strpbrk(temp, "\\/") == NULL) { Tcl_AppendToObj(pathOrDir, last-1, 1); + } else if (!strcmp(temp, "//zipfs:")) { + Tcl_AppendToObj(pathOrDir, "/", 1); } } /* * Need to quote 'prefix'. @@ -1454,26 +1349,26 @@ * 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) { + TclListObjLengthM(interp, typePtr, &length); + if (length == 0) { goto skipTypes; } globTypes = (Tcl_GlobTypeData *)TclStackAlloc(interp, sizeof(Tcl_GlobTypeData)); globTypes->type = 0; globTypes->perm = 0; globTypes->macType = NULL; globTypes->macCreator = NULL; - while (--length >= 0) { - size_t len; + while (length-- > 0) { + Tcl_Size len; const char *str; Tcl_ListObjIndex(interp, typePtr, length, &look); - str = TclGetStringFromObj(look, &len); + str = Tcl_GetStringFromObj(look, &len); if (strcmp("readonly", str) == 0) { globTypes->perm |= TCL_GLOB_PERM_RONLY; } else if (strcmp("hidden", str) == 0) { globTypes->perm |= TCL_GLOB_PERM_HIDDEN; } else if (len == 1) { @@ -1523,13 +1418,13 @@ globTypes->macType = look; Tcl_IncrRefCount(look); } else { Tcl_Obj *item; - int llen; + Tcl_Size llen; - if ((Tcl_ListObjLength(NULL, look, &llen) == TCL_OK) + if ((TclListObjLengthM(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))) { @@ -1559,21 +1454,21 @@ badTypesArg: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad argument to \"-types\": %s", TclGetString(look))); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "BAD", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "BAD", (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", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "BAD", (void *)NULL); join = 0; goto endOfGlob; } } } @@ -1631,45 +1526,10 @@ 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) { @@ -1690,12 +1550,11 @@ /* *---------------------------------------------------------------------- * * TclGlob -- * - * Sets the separator string based on the platform, performs tilde - * substitution, and calls DoGlob. + * 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. @@ -1714,11 +1573,11 @@ * The 'pattern' is written to. * *---------------------------------------------------------------------- */ -int +static int TclGlob( Tcl_Interp *interp, /* Interpreter for returning error message or * appending list of matching file names. */ char *pattern, /* Glob pattern to match. Must not refer to a * static string. */ @@ -1727,12 +1586,11 @@ int globFlags, /* Stores or'ed combination of flags */ Tcl_GlobTypeData *types) /* Struct containing acceptable types. May be * NULL. */ { const char *separators; - const char *head; - char *tail, *start; + char *tail; int result; Tcl_Obj *filenamesObj, *savedResultObj; separators = NULL; switch (tclPlatform) { @@ -1742,64 +1600,14 @@ 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; - } + 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 @@ -1834,11 +1642,11 @@ } tail = p; Tcl_IncrRefCount(pathPrefix); } else if (pathPrefix == NULL && (tail[0] == '/' || (tail[0] == '\\' && tail[1] == '\\'))) { - int driveNameLen; + Tcl_Size driveNameLen; Tcl_Obj *driveName; Tcl_Obj *temp = Tcl_NewStringObj(tail, -1); Tcl_IncrRefCount(temp); switch (TclGetPathType(temp, NULL, &driveNameLen, &driveName)) { @@ -1902,13 +1710,13 @@ * Finally if we still haven't managed to generate a path prefix, check if * the path starts with a current volume. */ if (pathPrefix == NULL) { - int driveNameLen; + Tcl_Size driveNameLen; Tcl_Obj *driveName; - if (TclFSNonnativePathType(tail, (int) strlen(tail), NULL, + if (TclFSNonnativePathType(tail, strlen(tail), NULL, &driveNameLen, &driveName) == TCL_PATH_ABSOLUTE) { pathPrefix = driveName; tail += driveNameLen; } } @@ -1915,11 +1723,11 @@ /* * To process a [glob] invocation, this function may be called multiple * times. Each time, the previously discovered filenames are in the * interpreter result. We stash that away here so the result is free for - * error messsages. + * error messages. */ savedResultObj = Tcl_GetObjResult(interp); Tcl_IncrRefCount(savedResultObj); Tcl_ResetResult(interp); @@ -1987,13 +1795,13 @@ * * We do it by rewriting the result list in-place. */ if (globFlags & TCL_GLOBMODE_TAILS) { - int objc, i; + Tcl_Size objc, i; Tcl_Obj **objv; - size_t prefixLen; + Tcl_Size prefixLen; const char *pre; /* * If this length has never been set, set it here. */ @@ -2000,11 +1808,11 @@ if (pathPrefix == NULL) { Tcl_Panic("Called TclGlob with TCL_GLOBMODE_TAILS and pathPrefix==NULL"); } - pre = TclGetStringFromObj(pathPrefix, &prefixLen); + pre = Tcl_GetStringFromObj(pathPrefix, &prefixLen); if (prefixLen > 0 && (strchr(separators, pre[prefixLen-1]) == NULL)) { /* * If we're on Windows and the prefix is a volume relative one * like 'C:', then there won't be a path separator in between, so @@ -2015,14 +1823,14 @@ || (pre[1] != ':')) { prefixLen++; } } - Tcl_ListObjGetElements(NULL, filenamesObj, &objc, &objv); + TclListObjGetElementsM(NULL, filenamesObj, &objc, &objv); for (i = 0; i< objc; i++) { - size_t len; - const char *oldStr = TclGetStringFromObj(objv[i], &len); + Tcl_Size len; + const char *oldStr = Tcl_GetStringFromObj(objv[i], &len); Tcl_Obj *elem; if (len == prefixLen) { if ((pattern[0] == '\0') || (strchr(separators, pattern[0]) == NULL)) { @@ -2229,18 +2037,18 @@ break; } Tcl_SetObjResult(interp, Tcl_NewStringObj( "unmatched open-brace in file name", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "BALANCE", - NULL); + (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", - NULL); + (void *)NULL); return TCL_ERROR; } } /* @@ -2341,46 +2149,39 @@ Tcl_IncrRefCount(subdirsPtr); result = Tcl_FSMatchInDirectory(interp, subdirsPtr, pathPtr, pattern, &dirOnly); *p = save; if (result == TCL_OK) { - int subdirc, i, repair = -1; + Tcl_Size i, subdirc, repair = -1; Tcl_Obj **subdirv; - result = Tcl_ListObjGetElements(interp, subdirsPtr, + result = TclListObjGetElementsM(interp, subdirsPtr, &subdirc, &subdirv); for (i=0; result==TCL_OK && i 0) && (strchr(separators, joined[len-1]) == NULL)) { Tcl_AppendToObj(joinedPtr, "/", 1); } } @@ -2490,12 +2291,12 @@ * 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); + Tcl_Size len; + const char *joined = Tcl_GetStringFromObj(joinedPtr,&len); if ((len > 0) && (strchr(separators, joined[len-1]) == NULL)) { if (Tcl_FSGetPathType(pathPtr) != TCL_PATH_VOLUME_RELATIVE) { Tcl_AppendToObj(joinedPtr, "/", 1); } @@ -2540,12 +2341,12 @@ *--------------------------------------------------------------------------- * * Access functions for Tcl_StatBuf -- * * These functions provide portable read-only access to the portable - * fields of the Tcl_StatBuf structure (really a 'struct stat', 'struct - * stat64' or something else related). [TIP #316] + * fields of the Tcl_StatBuf structure (really a 'struct stat' + * or something else related). [TIP #316] * * Results: * The value from the field being retrieved. * * Side effects: @@ -2601,48 +2402,48 @@ const Tcl_StatBuf *statPtr) { return (int) statPtr->st_rdev; } -Tcl_WideInt +long long Tcl_GetAccessTimeFromStat( const Tcl_StatBuf *statPtr) { - return (Tcl_WideInt) statPtr->st_atime; + return (long long) statPtr->st_atime; } -Tcl_WideInt +long long Tcl_GetModificationTimeFromStat( const Tcl_StatBuf *statPtr) { - return (Tcl_WideInt) statPtr->st_mtime; + return (long long) statPtr->st_mtime; } -Tcl_WideInt +long long Tcl_GetChangeTimeFromStat( const Tcl_StatBuf *statPtr) { - return (Tcl_WideInt) statPtr->st_ctime; + return (long long) statPtr->st_ctime; } -Tcl_WideUInt +unsigned long long Tcl_GetSizeFromStat( const Tcl_StatBuf *statPtr) { - return (Tcl_WideUInt) statPtr->st_size; + return (unsigned long long) statPtr->st_size; } -Tcl_WideUInt +unsigned long long Tcl_GetBlocksFromStat( const Tcl_StatBuf *statPtr) { #ifdef HAVE_STRUCT_STAT_ST_BLOCKS - return (Tcl_WideUInt) statPtr->st_blocks; + return (unsigned long long) statPtr->st_blocks; #else unsigned blksize = Tcl_GetBlockSizeFromStat(statPtr); - return ((Tcl_WideUInt) statPtr->st_size + blksize - 1) / blksize; + return ((unsigned long long) statPtr->st_size + blksize - 1) / blksize; #endif } #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE unsigned Index: generic/tclFileSystem.h ================================================================== --- generic/tclFileSystem.h +++ generic/tclFileSystem.h @@ -1,9 +1,9 @@ /* * tclFileSystem.h -- * - * This file contains the common defintions and prototypes for use by + * This file contains the common definitions and prototypes for use by * Tcl's filesystem and path handling layers. * * Copyright (c) 2003 Vince Darley. * * See the file "license.terms" for information on usage and redistribution of @@ -46,17 +46,17 @@ * tclFileName.c, and any platform-specific filesystem code. */ MODULE_SCOPE Tcl_PathType TclFSGetPathType(Tcl_Obj *pathPtr, const Tcl_Filesystem **filesystemPtrPtr, - int *driveNameLengthPtr); + Tcl_Size *driveNameLengthPtr); MODULE_SCOPE Tcl_PathType TclFSNonnativePathType(const char *pathPtr, - int pathLen, const Tcl_Filesystem **filesystemPtrPtr, - int *driveNameLengthPtr, Tcl_Obj **driveNameRef); + Tcl_Size pathLen, const Tcl_Filesystem **filesystemPtrPtr, + Tcl_Size *driveNameLengthPtr, Tcl_Obj **driveNameRef); MODULE_SCOPE Tcl_PathType TclGetPathType(Tcl_Obj *pathPtr, const Tcl_Filesystem **filesystemPtrPtr, - int *driveNameLengthPtr, Tcl_Obj **driveNameRef); + Tcl_Size *driveNameLengthPtr, Tcl_Obj **driveNameRef); MODULE_SCOPE int TclFSEpochOk(size_t filesystemEpoch); MODULE_SCOPE int TclFSCwdIsNative(void); MODULE_SCOPE Tcl_Obj * TclWinVolumeRelativeNormalize(Tcl_Interp *interp, const char *path, Tcl_Obj **useThisCwdPtr); Index: generic/tclGet.c ================================================================== --- generic/tclGet.c +++ generic/tclGet.c @@ -3,12 +3,12 @@ * * This file contains functions to convert strings into other forms, like * integers or floating-point numbers or booleans, doing syntax checking * along the way. * - * Copyright (c) 1990-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1993 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -51,11 +51,11 @@ code = Tcl_GetIntFromObj(interp, &obj, intPtr); if (obj.refCount > 1) { Tcl_Panic("invalid sharing of Tcl_Obj on C stack"); } - TclFreeIntRep(&obj); + TclFreeInternalRep(&obj); return code; } /* *---------------------------------------------------------------------- @@ -95,11 +95,11 @@ code = Tcl_GetDoubleFromObj(interp, &obj, doublePtr); if (obj.refCount > 1) { Tcl_Panic("invalid sharing of Tcl_Obj on C stack"); } - TclFreeIntRep(&obj); + TclFreeInternalRep(&obj); return code; } /* *---------------------------------------------------------------------- @@ -108,11 +108,11 @@ * * Given a string, return a 0/1 boolean value corresponding to the * string. * * Results: - * The return value is normally TCL_OK; in this case *boolPtr will be set + * The return value is normally TCL_OK; in this case *charPtr will be set * to the 0/1 value equivalent to src. If src is improperly formed then * TCL_ERROR is returned and an error message will be left in the * interp's result. * * Side effects: @@ -119,21 +119,27 @@ * None. * *---------------------------------------------------------------------- */ +#undef Tcl_GetBool +#undef Tcl_GetBoolFromObj int -Tcl_GetBoolean( +Tcl_GetBool( Tcl_Interp *interp, /* Interpreter used for error reporting. */ const char *src, /* String containing one of the boolean values * 1, 0, true, false, yes, no, on, off. */ - int *boolPtr) /* Place to store converted result, which will + 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; @@ -140,17 +146,29 @@ code = TclSetBooleanFromAny(interp, &obj); if (obj.refCount > 1) { Tcl_Panic("invalid sharing of Tcl_Obj on C stack"); } if (code == TCL_OK) { - *boolPtr = obj.internalRep.wideValue != 0; + Tcl_GetBoolFromObj(NULL, &obj, flags, charPtr); } return code; } + +#undef Tcl_GetBoolean +int +Tcl_GetBoolean( + Tcl_Interp *interp, /* Interpreter used for error reporting. */ + const char *src, /* String containing one of the boolean values + * 1, 0, true, false, yes, no, on, off. */ + int *intPtr) /* Place to store converted result, which will + * be 0 or 1. */ +{ + return Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof(int), (char *)(void *)intPtr); +} /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tclGetDate.y ================================================================== --- generic/tclGetDate.y +++ generic/tclGetDate.y @@ -5,11 +5,11 @@ * 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) 1992-1995 Karl Lehenbauer & 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. */ @@ -25,11 +25,11 @@ * 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) 1992-1995 Karl Lehenbauer & 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. * @@ -134,13 +134,13 @@ * Posix requires 1900. */ #define TM_YEAR_BASE 1900 -#define HOUR(x) ((int) (60 * x)) +#define HOUR(x) ((int) (60 * (x))) #define SECSPERDAY (24L * 60L * 60L) -#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) +#define IsLeapYear(x) (((x) % 4 == 0) && ((x) % 100 != 0 || (x) % 400 == 0)) /* * An entry in the lexical lookup table. */ @@ -959,11 +959,11 @@ int TclClockOldscanObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Tcl interpreter */ - int objc, /* Count of paraneters */ + int objc, /* Count of parameters */ Tcl_Obj *const *objv) /* Parameters */ { Tcl_Obj *result, *resultElement; int yr, mo, da; DateInfo dateInfo; ADDED generic/tclHAMT.c Index: generic/tclHAMT.c ================================================================== --- /dev/null +++ generic/tclHAMT.c @@ -0,0 +1,3159 @@ +/* + * tclHAMT.c -- + * + * This file contains an implementation of a hash array mapped trie + * (HAMT). In the first draft, it is just an alternative hash table + * implementation, but later revisions may support concurrency much + * better. + * + * Contributions from Don Porter, NIST, 2015-2017. (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 "tclHAMT.h" +#include + +#if defined(HAVE_INTRIN_H) +# include +#ifdef _WIN64 +# pragma intrinsic(_BitScanForward64) +#else +# pragma intrinsic(_BitScanForward) +#endif +#endif + +/* + * Each KVNode contains a key, value pair. + * + * It also holds a claim counter to support value sharing. The current + * implementation of the claim mechanism makes the overall structure + * suitable for only single-threaded operations. Later refinements in + * development are intended to ease this constraint. + * + * A previous implementation kept lists of pairs to account for hash + * collisions. With 64-bit hashes and any reasonable hash function, + * hash collisions are not just uncommon, they are essentially impossible. + * Instead of making every KVNode capable of handling arbitrary numbers + * of pairs, we let each handle only one pair, and shift the burden of + * taking care of collisions to the overall HAMT structure. + */ + +typedef struct KVNode *KVList; +typedef struct AMNode *ArrayMap; +typedef struct CNode *Collision; + +typedef struct CNode { + size_t claim; + Collision next; + KVList l; +} CNode; + +typedef struct KVNode { + size_t claim; /* How many claims on this struct */ + ClientData key; /* Key... */ + ClientData value; /* ...and Value of this pair */ +} KVNode; + +/* Finally, the top level struct that puts all the pieces together */ + +static size_t HAMTId = 1; + +typedef struct HAMT { + size_t id; + size_t claim; /* How many claims on this struct */ + const TclHAMTKeyType *kt; /* Custom key handling functions */ + const TclHAMTValueType *vt; /* Custom value handling functions */ + KVList kvl; /* When map stores a single KVList, + * just store it here (no tree) ... */ + union { + size_t hash; /* ...with its hash value. */ + ArrayMap am; /* >1 KVList? Here's the tree root. */ + } x; + Collision overflow; +} HAMT; + +/* + * The operations on a KVList: + * KVLClaim Make a claim on the pair. + * KVLDisclaim Release a claim on the pair. + * KVLNew Node creation utility + * KVLFind Find the KV Pair containing an equal key. + * KVLMerge Bring together two KV pairs with same hash. + * KVLInsert Create a new pair, merging new pair onto old one. + * KVLRemove Create a new pair, removing any pair matching key. + */ + +static +void KVLClaim( + KVList l) +{ + assert ( l != NULL ); + l->claim++; +} + +static +void KVLDisclaim( + HAMT *hamt, + KVList l) +{ + const TclHAMTKeyType *kt = hamt->kt; + const TclHAMTValueType *vt = hamt->vt; + + assert ( l != NULL ); + if (--l->claim) { + return; + } + if (kt && kt->dropRefProc) { + kt->dropRefProc(l->key); + } + l->key = NULL; + if (vt && vt->dropRefProc) { + vt->dropRefProc(l->value); + } + l->value = NULL; + Tcl_Free(l); +} + +static +int KVLEqualKeys( + HAMT *hamt, + ClientData key1, + ClientData key2) +{ + const TclHAMTKeyType *kt = hamt->kt; + return (key1 == key2) + || (kt && kt->isEqualProc && kt->isEqualProc( key1, key2) ); +} + +static +KVList KVLFind( + HAMT *hamt, + KVList l, + ClientData key) +{ + assert ( l != NULL); + + if (KVLEqualKeys(hamt, l->key, key)) { + return l; + } + if (hamt->overflow) { + Collision p = hamt->overflow; + while (p) { + if (KVLEqualKeys(hamt, p->l->key, key)) { + return p->l; + } + } + } + return NULL; +} + +static +KVList KVLNew( + HAMT *hamt, + ClientData key, + ClientData value) +{ + const TclHAMTKeyType *kt = hamt->kt; + const TclHAMTValueType *vt = hamt->vt; + KVList node = (KVNode *)Tcl_Alloc(sizeof(KVNode)); + node->claim = 0; + if (kt && kt->makeRefProc) { + kt->makeRefProc(key); + } + node->key = key; + if (vt && vt->makeRefProc) { + vt->makeRefProc(value); + } + node->value = value; + return node; +} + +static +void CNClaim( + Collision c) +{ + assert ( c != NULL); + c->claim++; +} + +static +void CNDisclaim( + HAMT *hamt, + Collision c) +{ + assert ( c != NULL); + if (--c->claim) { + return; + } + KVLDisclaim(hamt, c->l); + c->l = NULL; + if (c->next) { + CNDisclaim(hamt, c->next); + } + c->next = NULL; + Tcl_Free(c); +} + +static +Collision CNNew( + KVList l, + Collision next) +{ + Collision node = (CNode *)Tcl_Alloc(sizeof(CNode)); + node->claim = 0; + if (next) { + CNClaim(next); + } + node->next = next; + KVLClaim(l); + node->l = l; + return node; +} + + +/* + *---------------------------------------------------------------------- + * + * Hash -- + * + * Factored out utility routine to compute the hash of a key for + * a particular HAMT. + * + * Results: + * The computed hash value. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static +size_t Hash( + HAMT *hamt, + ClientData key) +{ + return (hamt->kt && hamt->kt->hashProc) + ? hamt->kt->hashProc(key) : (size_t) key; +} + +/* + * Return the merge of argument KV pairs one and two. + * Caller asserts that the two pairs belong to the same hash. + * It is extremely likely they hold the same key. In that case, the + * result of the merge is to return two, and the overwritten value + * is extracted from one. + * An overwrite by an identical KVNode is detected and turned into + * a no-op. + */ +static +KVList KVLMerge( + HAMT *hamt, + KVList one, + KVList two, + Collision *scratchPtr, + ClientData *valuePtr) +{ + assert ( two != NULL ); + if (one == NULL) { + if (valuePtr) { + *valuePtr = NULL; + } + return two; + } + if ( (one == two) || KVLEqualKeys(hamt, one->key, two->key) ) { + if (valuePtr) { + *valuePtr = one->value; + } + return (one->value == two->value) ? one : two; + } + + /* Argument two holds the KV pair we wish to store. It belongs + * where one is, but one is occupying the slot, and one has a + * different key. two will have to wait in the overflow waiting + * area until the slot opens up. We have to take a scan through + * the overflow to see if we are overwriting. + */ + + *scratchPtr = CNNew(two, *scratchPtr); + + if (hamt->overflow) { + Collision p = hamt->overflow; + while (p) { + if ( (p->l == two) || KVLEqualKeys(hamt, p->l->key, two->key)) { + if (valuePtr) { + *valuePtr = p->l->value; + } + return one; + } + } + } + if (valuePtr) { + *valuePtr = NULL; + } + return one; +} + +static +KVList KVLInsert( + HAMT *hamt, + KVList l, + ClientData key, + ClientData value, + Collision *scratchPtr, + ClientData *valuePtr) +{ + KVList list = KVLNew(hamt, key, value); + KVList result = KVLMerge(hamt, l, list, scratchPtr, valuePtr); + + if (result == l) { + /* Two possibilities here. 1) "new" was an exact duplicate + * of "l", so overwriting did nothing. In that case, the + * lines below will discard "new" as it is not stored. + * 2) "new" had a different key which is a hash collision + * with the key in "l". The storage of "new" got shifted off + * to scratchPtr, and will go into the collision list. In that + * case, the lines below are a harmless toggle of a counter. + * An examination of scratchPtr could eliminate that if there's + * reason to think it matters. */ + KVLClaim(list); + KVLDisclaim(hamt, list); + } + return result; +} + +/* + * Caller asserts that hash of key is same as hash of KVNode l. + * It is extremely likely they hold the same key. In that case, the + * result is NULL as we remove the KV Node matching key, and the + * disappearing value is pulled from l. + */ +static +KVList KVLRemove( + HAMT *hamt, + KVList l, + ClientData key, + Collision *scratchPtr, + ClientData *valuePtr) +{ + Collision p; + size_t hash; + + assert ( l != NULL ); + + if (KVLEqualKeys(hamt, l->key, key)) { + if (valuePtr) { + *valuePtr = l->value; + } + if (hamt->overflow) { + /* We're opening up a slot. Make a pass through the + * overflow waiting area to see if anything is waiting + * for it. */ + hash = Hash(hamt, key); + p = hamt->overflow; + while (p) { + size_t compare = Hash(hamt, p->l->key); + + if (hash == compare) { + *scratchPtr = CNNew(p->l, *scratchPtr); + return p->l; + } + p = p->next; + } + } + return NULL; + } + + /* The key we were seeking for removal did not match the key that was + * stored in the slot. This is a kind of hash collision. We need to + * look in the overflow area in case they key we seek to remove might + * be waiting there. */ + + if (hamt->overflow) { + p = hamt->overflow; + while (p) { + if (KVLEqualKeys(hamt, p->l->key, key)) { + if (valuePtr) { + *valuePtr = p->l->value; + } + *scratchPtr = CNNew(p->l, *scratchPtr); + return l; + } + p = p->next; + } + } + + /* The key is not here. Nothing to remove. Return unchanged list. */ + if (valuePtr) { + *valuePtr = NULL; + } + return l; +} + +/* + * Each interior node of the trie is an ArrayMap. + * + * In concept each ArrayMap stands for a single interior node in the + * complete trie. The mask and id fields identify which node it is. + * The masks are cleared high bits followed by set low bits. The number + * of set bits is a multiple of the branch index size of the tree, and + * the multiplier is the depth of the node in the complete tree. + * + * All hashes for which ( (hash & mask) == id ) are hashes with paths + * that pass through the node identified by those mask and id values. + * + * Since we can name each node in this way, we don't have to store the + * entire tree structure. We can create and operate on only those nodes + * where something consquential happens. In particular we need only nodes + * that have at least 2 children. Entire sub-paths that have no real + * branching are collapsed into single links. + * + * If we demand that each node contain 2 children, we have to permit + * KVLists to be stored in any node. Otherwise, frequently a leaf node + * would only hold one KVList. Each ArrayMap can have 2 types of children, + * KVLists and subnode ArrayMaps. Since we are not limiting storage of + * KVLists to leaf nodes, we cannot derive their hash values from where + * they are stored. We must store the hash values. This means the + * ArrayMap subnode children are identified by a pointer alone, while + * the KVList children need both a hash and a pointer. To deal with + * this we store the two children sets in separate portions of the slot + * array with separate indexing. That is the reason for separate kvMap + * and amMap. + * + * The slot storage is structured with all hash values stored first, + * as indexed by kvMap. Next comes parallel storage of the KVList pointers. + * Last comes the storage of the subnode ArrayMap pointers, as indexed + * by amMap. The size of the AMNode struct must be set so that slot + * has the space needed for all 3 collections. + */ + +typedef struct AMNode { + size_t canWrite; + size_t claim; /* How many claims on this struct */ + size_t size; /* How many pairs stored under this node? */ + size_t mask; /* The mask and id fields together identify the */ + size_t id; /* location of the node in the complete tree */ + size_t kvMap; /* Map to children containing a single KVList each */ + size_t amMap; /* Map to children that are subnodes */ + ClientData slot[]; /* Resizable space for outward links */ +} AMNode; + +#define AMN_SIZE(numList, numSubnode) \ + (sizeof(AMNode) + (2*(numList) + (numSubnode)) * sizeof(void *)) + +/* + * The branching factor of the tree is constrained by our map sizes + * which is determined by the size of size_t. + * + * TODO: Implement way to easily configure these values to explore + * impact of different branching factor. + */ + +/* Bits in a size_t. Use as our branching factor. Max children per node. */ +const int branchFactor = CHAR_BIT * sizeof(size_t); + +/* + * The operations on an ArrayMap: + * AMClaim Make a claim on a node. + * AMDisclaim Release a claim on a node. + * AMNew allocator + * AMNewLeaf Make leaf node from two NVLists. + * AMNewParent Make node to contain two descendant nodes. + * AMNewBranch Make branch mode from NVList and ArrayMap. + * AMFetch Fetch value from node given a key. + * AMMergeList Create new node, merging node and list. + * AMMergeDescendant Merge two nodes where one is ancestor. + * AMMerge Create new node, merging two nodes. + * AMInsert Create a new node, inserting new pair into old node. + * AMRemove Create a new node, with any pair matching key removed. + */ + +/* + *---------------------------------------------------------------------- + * + * NumBits -- + * + * Results: + * Number of set bits (aka Hamming weight, aka population count) in + * a size_t value. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static inline int +NumBits( + size_t value) +{ +#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))) + return __builtin_popcountll((long long)value); +#elif defined(_MSC_VER) + return __popcnt(value); +#else +#error NumBits not implemented! +#endif +} + +/* + *---------------------------------------------------------------------- + * + * LSB -- + * + * Results: + * Least significant set bit in a size_t value. + * AKA, number of trailing cleared bits in the value. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static inline int +LSB( + size_t value) +{ +#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))) + return __builtin_ctzll(value); +#elif defined(_MSC_VER) && defined(_WIN64) + unsigned long r = 64; + _BitScanForward64(&r, value); + return r; +#elif defined(_MSC_VER) + unsigned long r = 32; + _BitScanForward(&r, value); + return r; +#else +#error LSB not implemented! +#endif +} + +static +void AMClaim( + ArrayMap am) +{ + if (am != NULL) { + am->claim++; + } +} + +static +void AMDisclaim( + HAMT *hamt, + ArrayMap am) +{ + int i, numList, numSubnode; + + if (am == NULL) { + return; + } + am->claim--; + if (am->claim) { + return; + } + + numList = NumBits(am->kvMap); + numSubnode = NumBits(am->amMap); + + am->mask = 0; + am->id = 0; + am->kvMap = 0; + am->amMap = 0; + + for (i = 0; i < numList; i++) { + am->slot[i] = NULL; + } + for (i = numList; i < 2*numList; i++) { + KVLDisclaim(hamt, (KVList)am->slot[i]); + am->slot[i] = NULL; + } + for (i = 2*numList; i < 2*numList + numSubnode; i++) { + AMDisclaim(hamt, (ArrayMap)am->slot[i]); + am->slot[i] = NULL; + } + + Tcl_Free(am); +} + +/* + *---------------------------------------------------------------------- + * + * AMNew -- + * + * Create an ArrayMap with space for numList lists and + * numSubnode subnodes, and initialize with mask and id. + * + * Results: + * The created ArrayMap. + * + * Side effects: + * Memory is allocated. + * + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMNew( + TclHAMT hamt, + int numList, + int numSubnode, + size_t mask, + size_t id) +{ + ArrayMap map = (ArrayMap)Tcl_Alloc(AMN_SIZE(numList, numSubnode)); + + map->canWrite = (hamt) ? hamt->id : 0; + map->claim = 0; + map->size = 0; + map->mask = mask; + map->id = id; + return map; +} +/* + *---------------------------------------------------------------------- + * + * AMNewParent -- + * + * Create an ArrayMap to serve as a container for + * two ArrayMap subnodes. + * + * Results: + * The created ArrayMap. + * + * Side effects: + * Memory is allocated. + * + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMNewParent( + TclHAMT hamt, + ArrayMap one, + ArrayMap two) +{ + /* Mask used to carve out branch index. */ + const int branchMask = (branchFactor - 1); + + /* Bits in a index selecting a child of a node */ + const int branchShift = TclMSB(branchFactor); + + /* The depth of the tree for the node we must create. + * Determine by lowest bit where hashes differ. */ + int depth = LSB(one->id ^ two->id) / branchShift; + + /* Compute the mask for all nodes at this depth */ + size_t mask = ((size_t)1 << (depth * branchShift)) - 1; + + int idx1 = (one->id >> (depth * branchShift)) & branchMask; + int idx2 = (two->id >> (depth * branchShift)) & branchMask; + ArrayMap map = AMNew(hamt, 0, 2, mask, one->id & mask); + + assert ( idx1 != idx2 ); + assert ( (two->id & mask) == map->id ); + + map->size = one->size + two->size; + map->kvMap = 0; + map->amMap = ((size_t)1 << idx1) | ((size_t)1 << idx2); + + AMClaim(one); + AMClaim(two); + + if (idx1 < idx2) { + map->slot[0] = one; + map->slot[1] = two; + } else { + map->slot[0] = two; + map->slot[1] = one; + } + return map; +} +/* + *---------------------------------------------------------------------- + * + * AMNewBranch -- + * + * Create an ArrayMap to serve as a container for + * one KVList and one ArrayMap subnode. + * + * Results: + * The created ArrayMap. + * + * Side effects: + * Memory is allocated. + * + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMNewBranch( + TclHAMT hamt, + ArrayMap sub, + size_t hash, + KVList l) +{ + /* Mask used to carve out branch index. */ + const int branchMask = (branchFactor - 1); + + /* Bits in a index selecting a child of a node */ + const int branchShift = TclMSB(branchFactor); + + /* The depth of the tree for the node we must create. + * Determine by lowest bit where hashes differ. */ + int depth = LSB(hash ^ sub->id) / branchShift; + + /* Compute the mask for all nodes at this depth */ + size_t mask = ((size_t)1 << (depth * branchShift)) - 1; + + int idx1 = (hash >> (depth * branchShift)) & branchMask; + int idx2 = (sub->id >> (depth * branchShift)) & branchMask; + ArrayMap map = AMNew(hamt, 1, 1, mask, hash & mask); + + assert ( idx1 != idx2 ); + assert ( (sub->id & mask) == map->id ); + + map->size = sub->size + 1; + map->kvMap = (size_t)1 << idx1; + map->amMap = (size_t)1 << idx2; + + KVLClaim(l); + AMClaim(sub); + + map->slot[0] = (ClientData)hash; + map->slot[1] = l; + map->slot[2] = sub; + + return map; +} +/* + *---------------------------------------------------------------------- + * + * AMNewLeaf -- + * + * Create an ArrayMap to serve as a container for + * two KVLists given their hash values. + * + * Results: + * The created ArrayMap. + * + * Side effects: + * Memory is allocated. + * + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMNewLeaf( + TclHAMT hamt, + size_t hash1, + KVList l1, + size_t hash2, + KVList l2) +{ + /* Mask used to carve out branch index. */ + const int branchMask = (branchFactor - 1); + + /* Bits in a index selecting a child of a node */ + const int branchShift = TclMSB(branchFactor); + + size_t *hashes; + KVList *lists; + + /* The depth of the tree for the node we must create. + * Determine by lowest bit where hashes differ. */ + int depth = LSB(hash1 ^ hash2) / branchShift; + + /* Compute the mask for all nodes at this depth */ + size_t mask = ((size_t)1 << (depth * branchShift)) - 1; + + int idx1 = (hash1 >> (depth * branchShift)) & branchMask; + int idx2 = (hash2 >> (depth * branchShift)) & branchMask; + + ArrayMap map = AMNew(hamt, 2, 0, mask, hash1 & mask); + + assert ( idx1 != idx2 ); + assert ( (hash2 & mask) == map->id ); + + map->size = 2; + map->kvMap = ((size_t)1 << idx1) | ((size_t)1 << idx2); + map->amMap = 0; + + KVLClaim(l1); + KVLClaim(l2); + + hashes = (size_t *)&(map->slot); + lists = (KVList *) (hashes + 2); + if (idx1 < idx2) { + hashes[0] = hash1; + hashes[1] = hash2; + lists[0] = l1; + lists[1] = l2; + } else { + hashes[0] = hash2; + hashes[1] = hash1; + lists[0] = l2; + lists[1] = l1; + } + + return map; +} + +/* + *---------------------------------------------------------------------- + * + * AMFetch -- + * + * Lookup key in this subset of the key/value map. + * + * Results: + * The corresponding value, or NULL, if the key was not there. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static +ClientData AMFetch( + HAMT *hamt, + ArrayMap am, + size_t hash, + ClientData key) +{ + /* Mask used to carve out branch index. */ + const int branchMask = (branchFactor - 1); + + size_t tally; + + if ((am->mask & hash) != am->id) { + /* Hash indicates key is not in this subtree */ + return NULL; + } + + tally = (size_t)1 << ((hash >> LSB(am->mask + 1)) & branchMask); + if (tally & am->kvMap) { + KVList l; + + /* Hash is consistent with one of our KVList children... */ + int offset = NumBits(am->kvMap & (tally - 1)); + + if (am->slot[offset] != (ClientData)hash) { + /* ...but does not actually match. */ + return NULL; + } + + l = KVLFind(hamt, (KVList)am->slot[offset + NumBits(am->kvMap)], key); + return l ? l->value : NULL; + } + if (tally & am->amMap) { + /* Hash is consistent with one of our subnode children... */ + + return AMFetch(hamt, (ArrayMap)am->slot[2 * NumBits(am->kvMap) + + NumBits(am->amMap & (tally - 1))], hash, key); + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * AMMergeList -- + * Merge a node and list together to make a node. + * + * Results: + * The node created by the merge. + * + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMMergeList( + HAMT *hamt, + ArrayMap am, + size_t hash, + KVList kvl, + Collision *scratchPtr, + ClientData *valuePtr, + int listIsFirst) +{ + /* Mask used to carve out branch index. */ + const int branchMask = (branchFactor - 1); + + size_t tally; + int numList, numSubnode, loffset, soffset, i; + ClientData *src, *dst; + ArrayMap map, sub; + + if ((am->mask & hash) != am->id) { + /* Hash indicates list does not belong in this subtree */ + /* Create a new subtree to be parent of both am and kvl. */ + return AMNewBranch(hamt, am, hash, kvl); + } + + /* Hash indicates key should be descendant of am, which? */ + tally = (size_t)1 << ((hash >> LSB(am->mask + 1)) & branchMask); + + numList = NumBits(am->kvMap); + numSubnode = NumBits(am->amMap); + loffset = NumBits(am->kvMap & (tally - 1)); + soffset = NumBits(am->amMap & (tally - 1)); + src = am->slot; + + if (tally & am->kvMap) { + /* Hash consistent with existing list child */ + + if (am->slot[loffset] == (ClientData)hash) { + /* Hash of list child matches. Merge to it. */ + KVList l, child = (KVList) am->slot[loffset + numList]; + + if (kvl == child) { + if (valuePtr) { + *valuePtr = kvl->value; + } + return am; + } + + if (listIsFirst) { + l = KVLMerge(hamt, kvl, child, scratchPtr, valuePtr); + if ((l == kvl) && (kvl->key == child->key) + && (kvl->value == child->value)) { + KVLClaim(kvl); + KVLDisclaim(hamt, child); + am->slot[loffset + numList] = kvl; + } + } else { + l = KVLMerge(hamt, child, kvl, scratchPtr, valuePtr); + if ((l == child) && (kvl->key == child->key) + && (kvl->value == child->value)) { + KVLClaim(kvl); + KVLDisclaim(hamt, child); + am->slot[loffset + numList] = kvl; + } + } + if (l == child) { + return am; + } + + if (am->canWrite && (am->canWrite == hamt->id)) { + KVLClaim(l); + KVLDisclaim(hamt, (KVList)am->slot[numList + loffset]); + am->slot[numList + loffset] = l; + return am; + } + map = AMNew(hamt, numList, numSubnode, am->mask, am->id); + + map->size = am->size; + map->kvMap = am->kvMap; + map->amMap = am->amMap; + dst = map->slot; + + /* Copy all hashes */ + for (i = 0; i < numList; i++) { + *dst++ = *src++; + } + + /* Copy all lists and insert one */ + for (i = 0; i < loffset; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + src++; + KVLClaim(l); + *dst++ = l; + for (i = loffset + 1; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + + /* Copy all subnodes */ + for (i = 0; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + return map; + } + /* Hashes do not match. Create Leaf to hold both. */ + sub = AMNewLeaf(hamt, (size_t)am->slot[loffset], + (KVList)am->slot[loffset + numList], hash, kvl); + + /* Remove the list, Insert the leaf subnode */ + map = AMNew(hamt, numList - 1, numSubnode + 1, am->mask, am->id); + + map->size = am->size + 1; + + map->kvMap = am->kvMap & ~tally; + map->amMap = am->amMap | tally; + dst = map->slot; + /* hashes */ + for (i = 0; i < loffset; i++) { + *dst++ = *src++; + } + src++; + for (i = loffset + 1; i < numList; i++) { + *dst++ = *src++; + } + /* lists */ + for (i = 0; i < loffset; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + src++; + for (i = loffset + 1; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + /* subnodes */ + for (i = 0; i < soffset; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + AMClaim(sub); + *dst++ = sub; + for (i = soffset; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + return map; + } + if (tally & am->amMap) { + /* Hash consistent with existing subnode child */ + ArrayMap child = (ArrayMap)am->slot[2*numList + soffset]; + + /* Merge the list into that subnode child... */ + sub = AMMergeList(hamt, child, hash, kvl, + scratchPtr, valuePtr, listIsFirst); + if (sub == child) { + /* Subnode unchanged, map unchanged, just return */ + return am; + } + + /* Overwrite when we have suitable transient */ + if (am->canWrite && (am->canWrite == hamt->id)) { + am->size = am->size - child->size + sub->size; + AMClaim(sub); + AMDisclaim(hamt, child); + am->slot[2*numList + soffset] = sub; + return am; + } + /* Copy slots, replacing the subnode with the merge result */ + map = AMNew(hamt, numList, numSubnode, am->mask, am->id); + + map->size = am->size - child->size + sub->size; + + map->kvMap = am->kvMap; + map->amMap = am->amMap; + dst = map->slot; + + /* Copy all hashes */ + for (i = 0; i < numList; i++) { + *dst++ = *src++; + } + + /* Copy all lists */ + for (i = 0; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + + /* Copy all subnodes, replacing one */ + for (i = 0; i < soffset; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + src++; + AMClaim(sub); + *dst++ = sub; + for (i = soffset + 1; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + return map; + } + + /* am is not using this tally; copy am and add it. */ + map = AMNew(hamt, numList + 1, numSubnode, am->mask, am->id); + + map->size = am->size + 1; + map->kvMap = am->kvMap | tally; + map->amMap = am->amMap; + dst = map->slot; + + /* Copy all hashes and insert one */ + for (i = 0; i < loffset; i++) { + *dst++ = *src++; + } + *dst++ = (ClientData)hash; + for (i = loffset; i < numList; i++) { + *dst++ = *src++; + } + + /* Copy all lists and insert one */ + for (i = 0; i < loffset; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + KVLClaim(kvl); + *dst++ = kvl; + for (i = loffset; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + + /* Copy all subnodes */ + for (i = 0; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + + return map; +} + +/* Forward declaration for mutual recursion */ +static ArrayMap AMMerge(HAMT *hamt, ArrayMap one, ArrayMap two, + int *idPtr, Collision *scratchPtr); + + +/* + *---------------------------------------------------------------------- + * + * AMMergeContents -- + * Merge the contents of two nodes with same id together to make + * a single node with the union of children. + * + * Results: + * The node created by the merge. + * + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMMergeContents( + HAMT *hamt, + ArrayMap one, + ArrayMap two, + int *identicalPtr, + Collision *scratchPtr) +{ + ArrayMap map, am = NULL; + KVList l = NULL; + int numList, numSubnode, goodOneSlots = 0, goodTwoSlots = 0; + int identical = 1; + size_t size = 0; + + /* If either tree has a particular subnode, the merger must too */ + size_t amMap = one->amMap | two->amMap; + + /* If only one of two has list child, the merge will too, providing + * there's not already a subnode claiming the slot. */ + size_t kvMap = (one->kvMap ^ two->kvMap) & ~amMap; + + size_t tally; + ClientData *src1= one->slot; + ClientData *src2 = two->slot; + ClientData *dst; + + int numList1 = NumBits(one->kvMap); + int numList2 = NumBits(two->kvMap); + + assert ( one != two ); + + for (tally = (size_t)1; tally; tally = tally << 1) { + if (!(tally & (amMap | kvMap))) { + assert ((one->amMap & tally)== 0); /* would be in amMap */ + assert ((two->amMap & tally)== 0); /* would be in amMap */ + assert ((one->kvMap & tally) == (two->kvMap & tally)); + + /* Remaining case is when both have list child @ tally ... */ + if (tally & one->kvMap) { + if (*src1 == *src2) { + /* When hashes same, this will make a merged list in merge. */ + kvMap = kvMap | tally; + } else { + /* When hashes differ, this will make a subnode child in merge. */ + amMap = amMap | tally; + } + } + } + if (tally & one->kvMap) { + src1++; + } + if (tally & two->kvMap) { + src2++; + } + } + + /* We now have the maps for the merged node. */ + numList = NumBits(kvMap); + numSubnode = NumBits(amMap); + + /* Check for case where merge is same as one */ + src1 = one->slot; + src2 = two->slot; + tally = (size_t)1; + if ((kvMap == one->kvMap) && (amMap == one->amMap)) { + src1 += numList1; + src2 += numList2; + for (; tally; tally = tally << 1) { + if ((tally & kvMap) == 0) { + if (tally & two->kvMap) { + src2++; + } + continue; + } + if ((tally & two->kvMap) == 0) { + /* Merge empty to one -> one */ + src1++; + continue; + } + if (*src1 == *src2) { + /* Merge one to one -> one */ + src1++; + src2++; + continue; + } + + /* General merge - check result */ + l = KVLMerge(hamt, (KVList)*src1, (KVList)*src2, scratchPtr, NULL); + if (l != *src1) { + identical = 0; + goto notOne; + } + /* Check whether *src1 and *src2 are identical values. + * If so, Make them the same value. */ + if ((l->key == ((KVList)(*src2))->key) + && (l->value == ((KVList)(*src2))->value)) { + KVLClaim(l); + KVLDisclaim(hamt, (KVList)*src2); + *src2 = l; + } else { + identical = 0; + } + src1++; + src2++; + } +assert ( src1 == one->slot + 2*numList1 ); +assert ( src2 == two->slot + 2*numList2 ); + + if (amMap) { + for (tally = (size_t)1; tally; tally = tally << 1) { +assert( (src2 - two->slot) <= 2*numList2 + NumBits(two->amMap) ); + if ((tally & amMap) == 0) { + continue; + } + if (tally & two->amMap) { + int id; + if (*src1 == *src2) { + /* Merge one into one -> one */ + src1++; + src2++; + continue; + } + am = AMMerge(hamt, (ArrayMap)*src1, (ArrayMap)*src2, &id, scratchPtr); + identical = identical && id; + if (am != *src1) { + goto notOne; + } + if (id) { + AMClaim((ArrayMap)*src1); + AMDisclaim(hamt, (ArrayMap)*src2); + *src2 = *src1; + } + src2++; + } else if (tally & two->kvMap) { + int loffset = NumBits(two->kvMap & (tally - 1)); + + identical = 0; + am = AMMergeList(hamt, (ArrayMap)*src1, (size_t)two->slot[loffset], + (KVList)two->slot[loffset + numList2], + scratchPtr, NULL, 0); + if (am != *src1) { + + /* TODO: detect and fix cases failing here + * that should not. +fprintf(stdout, "BAIL %p %p\n", am, *src1); fflush(stdout); + */ + goto notOne; + } + } + src1++; + } + } + /* If you get here, congrats! the merge is same as one */ + if (identicalPtr) { + *identicalPtr = identical; + } + return one; + } + + notOne: + /* src1 points to first failed slot */ + identical = 0; + goodOneSlots = src1 - one->slot; + + if ((kvMap == two->kvMap) && (amMap == two->amMap)) { + ClientData *src = one->slot + numList1; + + src2 = two->slot + numList2; + if (src1 > src) { + while (src < src1) { + if (*src != *src2) { + goto notTwo; + } + src++; + src2++; + } + } + + if (src1 < one->slot + 2*numList1) { + for (; tally; tally = tally << 1) { +assert( (src2 - two->slot) < 2*numList2 + NumBits(two->amMap) ); + if ((tally & kvMap) == 0) { + continue; + } + if ((tally & one->kvMap) == 0) { + /* Merge two to empty -> two */ + src2++; + continue; + } + if (src < src1) { + src++; + src2++; + } + if ((src == src1) && (l != *src2)) { + goto notTwo; + } + if (*src == *src2) { + /* Merge two to two -> two */ + src++; + src2++; + continue; + } + + /* General merge - check result */ + l = KVLMerge(hamt, (KVList)*src, (KVList)*src2, scratchPtr, NULL); + if (l != *src2) { + goto notTwo; + } + src++; + src2++; + } + tally = (size_t)1; + } + + if (amMap) { + for (; tally; tally = tally << 1) { +assert( (src2 - two->slot) < 2*numList2 + NumBits(two->amMap) ); + if ((tally & amMap) == 0) { + continue; + } + if ((tally & (one->kvMap | one->amMap)) == 0) { + /* Merge two to empty -> two */ + src2++; + continue; + } + if (src < src1) { + src++; + src2++; + continue; + } + if ((src == src1) && (am != *src2)) { + goto notTwo; + } + + if (tally & one->amMap) { + int id; + if (*src == *src2) { + /* Merge two into two -> two */ + src++; + src2++; + continue; + } + am = AMMerge(hamt, (ArrayMap)*src, (ArrayMap)*src2, &id, scratchPtr); + if (am != *src2) { + goto notTwo; + } + if (id) { + AMClaim((ArrayMap)*src1); + AMDisclaim(hamt, (ArrayMap)*src2); + *src2 = *src1; + } + src++; + } else { + /* (tally & one->kvMap) */ + int loffset = NumBits(one->kvMap & (tally - 1)); + + identical = 0; + am = AMMergeList(hamt, (ArrayMap)*src2, (size_t)one->slot[loffset], + (KVList)one->slot[loffset + numList1], + scratchPtr, NULL, 1); + if (am != *src2) { + goto notTwo; + } + } + src2++; + } + } + + /* If you get here, congrats! the merge is same as two */ + assert ( identical == 0 ); + if (identicalPtr) { + *identicalPtr = identical; + } + return two; + } + notTwo: + /* src1 and src2 point to first failed slots */ + if ((kvMap == two->kvMap) && (amMap == two->amMap)) { + goodTwoSlots = src2 - two->slot; + } + + /* TODO: Overwrite one when possible. This can only help + * multi-argument merges or could help creation operations + * if they were recasted into multi-merge instead of + * multi-insert. Low prio for now. */ + + map = AMNew(hamt, numList, numSubnode, one->mask, one->id); + + map->kvMap = kvMap; + map->amMap = amMap; + dst = map->slot; + + if (goodOneSlots >= goodTwoSlots) { + if (goodOneSlots) { + memcpy(dst, one->slot, goodOneSlots * sizeof(void *)); + dst += goodOneSlots; + } + } else { + memcpy(dst, two->slot, goodTwoSlots * sizeof(void *)); + dst += goodTwoSlots; + } + + /* Copy the hashes */ + if (dst < map->slot + numList) { + assert(src1 == one->slot); + assert(src2 == two->slot); + for (tally = (size_t)1; tally; tally = tally << 1) { + if (tally & kvMap) { + if (tally & one->kvMap) { + *dst = *src1; + } + if (tally & two->kvMap) { + *dst = *src2; + } + dst++; + } + if (tally & one->kvMap) { + src1++; + } + if (tally & two->kvMap) { + src2++; + } + } + tally = (size_t)1; + } + if (src1 < one->slot + numList1) { + src1 = one->slot + numList1; + } + if (src2 < two->slot + numList2) { + src2 = two->slot + numList2; + } + + /* Copy/merge the lists */ + if (dst < map->slot + 2*numList) { + for (; tally; tally = tally << 1) { + if (tally & kvMap) { + if ((tally & one->kvMap) && (tally & two->kvMap) + && (*src1 != *src2)) { + l = KVLMerge(hamt, (KVList)*src1, (KVList)*src2, scratchPtr, NULL); + if (l == *src1) { + /* Check whether *src1 and *src2 are identical values. + * If so, Make them the same value. */ + if ((l->key == ((KVList)(*src2))->key) + && (l->value == ((KVList)(*src2))->value)) { + KVLClaim(l); + KVLDisclaim(hamt, (KVList)*src2); + *src2 = l; + } + } + *dst++ = l; + } else if (tally & one->kvMap) { + *dst++ = *src1; + } else { + assert (tally & two->kvMap); + *dst++ = *src2; + } + } + if (tally & one->kvMap) { + src1++; + } + if (tally & two->kvMap) { + src2++; + } + } + tally = (size_t)1; + } + if (src1 < one->slot + 2*numList1) { + src1 = one->slot + 2*numList1; + } + if (src2 < two->slot + 2*numList2) { + src2 = two->slot + 2*numList2; + } + + /* Copy/merge the subnodes */ + for (; tally; tally = tally << 1) { + if (tally & amMap) { + int loffset1, loffset2; + size_t hash1, hash2; + KVList l1, l2; + + if ((tally & one->amMap) && (tally & two->amMap)) { + int id; + am = AMMerge(hamt, (ArrayMap)*src1, (ArrayMap)*src2, &id, scratchPtr); + *dst++ = am; + if (id) { + AMClaim((ArrayMap)*src1); + AMDisclaim(hamt, (ArrayMap)*src2); + *src2 = *src1; + } + src1++; + src2++; + } else if (tally & one->amMap) { + if (tally & two->kvMap) { + loffset2 = NumBits(two->kvMap & (tally - 1)); + hash2 = (size_t)two->slot[loffset2]; + l2 = (KVList)two->slot[loffset2 + numList2]; + + am = AMMergeList(hamt, (ArrayMap)*src1++, hash2, l2, + scratchPtr, NULL, 0); + } else { + am = (ArrayMap)*src1++; + } + *dst++ = am; + } else if (tally & two->amMap) { + if (tally & one->kvMap) { + loffset1 = NumBits(one->kvMap & (tally - 1)); + hash1 = (size_t)one->slot[loffset1]; + l1 = (KVList)one->slot[loffset1 + numList1]; + am = AMMergeList(hamt, (ArrayMap)*src2++, hash1, l1, + scratchPtr, NULL, 1); + } else { + am = (ArrayMap)*src2++; + } + *dst++ = am; + } else { + /* TRICKY!!! Have to create node from two lists. */ + loffset1 = NumBits(one->kvMap & (tally - 1)); + loffset2 = NumBits(two->kvMap & (tally - 1)); + hash1 = (size_t)one->slot[loffset1]; + hash2 = (size_t)two->slot[loffset2]; + l1 = (KVList)one->slot[loffset1 + numList1]; + l2 = (KVList)two->slot[loffset2 + numList2]; + + am = AMNewLeaf(hamt, hash1, l1, hash2, l2); + *dst++ = am; + } + size += am->size; + } + } + dst = map->slot + numList; + while (dst < map->slot + 2 * numList) { + KVLClaim((KVList)*dst++); + } + while (dst < map->slot + 2 * numList + numSubnode) { + AMClaim((ArrayMap)*dst++); + } + map->size = size + numList; + assert ( identical == 0 ); + if (identicalPtr) { + *identicalPtr = identical; + } + return map; +} + +/* + *---------------------------------------------------------------------- + * + * AMMergeDescendant -- + * Merge two nodes together where one is an ancestor. + * + * Results: + * The node created by the merge. + * + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMMergeDescendant( + HAMT *hamt, + ArrayMap ancestor, + ArrayMap descendant, + Collision *scratchPtr, + int ancestorIsFirst) +{ + const int branchMask = (branchFactor - 1); + int numList = NumBits(ancestor->kvMap); + int numSubnode = NumBits(ancestor->amMap); + size_t tally = (size_t)1 << ( + (descendant->id >> LSB(ancestor->mask + 1)) & branchMask); + int i; + int loffset = NumBits(ancestor->kvMap & (tally - 1)); + int soffset = NumBits(ancestor->amMap & (tally - 1)); + ClientData *dst, *src = ancestor->slot; + + ArrayMap map, sub; + + if (tally & ancestor->kvMap) { + /* Already have list child there. Must merge them. */ + sub = AMMergeList(hamt, descendant, (size_t)ancestor->slot[loffset], + (KVList)ancestor->slot[loffset + numList], + scratchPtr, NULL, ancestorIsFirst); + map = AMNew(hamt, numList - 1, numSubnode + 1, ancestor->mask, ancestor->id); + + map->size = ancestor->size - 1 + sub->size; + map->kvMap = ancestor->kvMap & ~tally; + map->amMap = ancestor->amMap | tally; + dst = map->slot; + + /* hashes */ + for (i = 0; i < loffset; i++) { + *dst++ = *src++; + } + src++; + for (i = loffset + 1; i < numList; i++) { + *dst++ = *src++; + } + /* lists */ + for (i = 0; i < loffset; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + src++; + /* lists */ + for (i = loffset + 1; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + /* subnodes */ + for (i = 0; i < soffset; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + AMClaim(sub); + *dst++ = sub; + for (i = soffset; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + return map; + } + if (tally & ancestor->amMap) { + ArrayMap child = (ArrayMap)ancestor->slot[2*numList + soffset]; + int id; + + /* Already have node child there. Must merge them. */ + if (ancestorIsFirst) { + sub = AMMerge(hamt, child, descendant, &id, scratchPtr); + } else { + sub = AMMerge(hamt, descendant, child, &id, scratchPtr); + } + if (sub == child) { + if (id) { + AMClaim(descendant); + AMDisclaim(hamt, child); + ancestor->slot[2*numList + soffset] = descendant; + } + return ancestor; + } + + if (ancestor->canWrite && (ancestor->canWrite == hamt->id)) { + ancestor->size = ancestor->size - child->size + sub->size; + AMClaim(sub); + AMDisclaim(hamt, child); + ancestor->slot[2*numList + soffset] = sub; + return ancestor; + } + map = AMNew(hamt, numList, numSubnode, ancestor->mask, ancestor->id); + + map->size = ancestor->size - child->size + sub->size; + map->kvMap = ancestor->kvMap; + map->amMap = ancestor->amMap; + dst = map->slot; + + /* hashes */ + for (i = 0; i < numList; i++) { + *dst++ = *src++; + } + /* lists */ + for (i = 0; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + /* subnodes */ + for (i = 0; i < soffset; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + src++; + AMClaim(sub); + *dst++ = sub; + for (i = soffset + 1; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + return map; + } + /* Nothing in the way. Make modified copy with new subnode */ + map = AMNew(hamt, numList, numSubnode + 1, ancestor->mask, ancestor->id); + + map->size = ancestor->size + descendant->size; + map->kvMap = ancestor->kvMap; + map->amMap = ancestor->amMap | tally; + dst = map->slot; + + /* hashes */ + for (i = 0; i < numList; i++) { + *dst++ = *src++; + } + /* lists */ + for (i = 0; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + /* subnodes */ + for (i = 0; i < soffset; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + AMClaim(descendant); + *dst++ = descendant; + for (i = soffset; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + return map; +} + +/* + *---------------------------------------------------------------------- + * + * AMMerge -- + * Merge two nodes together to make a node. + * + * Results: + * The node created by the merge. + * + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMMerge( + HAMT *hamt, + ArrayMap one, + ArrayMap two, + int *idPtr, + Collision *scratchPtr) +{ + if (one->mask == two->mask) { + /* Nodes at the same depth ... */ + if (one->id == two->id) { + /* ... and the same id; merge contents */ + if (one == two) { + if (idPtr) { + *idPtr = 0; /* Same is not identical */ + } + return one; + } + return AMMergeContents(hamt, one, two, idPtr, scratchPtr); + } + /* ... but are not same. Create parent to contain both. */ + if (idPtr) { + *idPtr = 0; + } + return AMNewParent(hamt, one, two); + } + if (idPtr) { + *idPtr = 0; + } + if (one->mask < two->mask) { + /* two is deeper than one... */ + if ((one->mask & two->id) == one->id) { + /* ... and is a descendant of one. */ + return AMMergeDescendant(hamt, one, two, scratchPtr, 1); + } + /* ...but is not a descendant. Create parent to contain both. */ + return AMNewParent(hamt, one, two); + } + /* one is deeper than two... */ + if ((two->mask & one->id) == two->id) { + /* ... and is a descendant of two. */ + return AMMergeDescendant(hamt, two, one, scratchPtr, 0); + } + return AMNewParent(hamt, one, two); +} + +/* + *---------------------------------------------------------------------- + * + * AMInsert -- + * + * Insert new key, value pair into this subset of the key/value map. + * + * Results: + * A new revised subset containing the new pair. + * + * Side effects: + * If valuePtr is not NULL, write to *valuePtr the + * previous value associated with key in subset + * or NULL if the key was not there before. + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMInsert( + HAMT *hamt, + ArrayMap am, + size_t hash, + ClientData key, + ClientData value, + Collision *scratchPtr, + ClientData *valuePtr) +{ + KVList list = KVLInsert(hamt, NULL, key, value, NULL, valuePtr); + ArrayMap result = AMMergeList(hamt, am, hash, list, scratchPtr, valuePtr, 0); + + if (result == am) { + /* No-op insert; discard new node */ + KVLClaim(list); + KVLDisclaim(hamt, list); + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * AMRemove -- + * + * Remove the key, value pair containing key from this subset of + * the key/value map, if present. + * + * Results: + * A new revised subset without a pair containing key. + * OR + * NULL, then hashPtr, listPtr have hash and KVList values + * written to them for the single list left. + * + * Side effects: + * If valuePtr is not NULL, write to *valuePtr the + * previous value associated with key in subset + * or NULL if the key was not there before. + *---------------------------------------------------------------------- + */ + +static +ArrayMap AMRemove( + HAMT *hamt, + ArrayMap am, + size_t hash, + ClientData key, + Collision *scratchPtr, + size_t *hashPtr, + KVList *listPtr, + ClientData *valuePtr) +{ + /* Mask used to carve out branch index. */ + const int branchMask = (branchFactor - 1); + + size_t tally; + int numList, numSubnode, loffset, soffset, i; + ArrayMap map, sub; + ClientData *src, *dst; + KVList l; + + if ((am->mask & hash) != am->id) { + /* Hash indicates key is not in this subtree */ + + if (valuePtr) { + *valuePtr = NULL; + } + return am; + } + + /* Hash indicates key should be descendant of am */ + numList = NumBits(am->kvMap); + numSubnode = NumBits(am->amMap); + + tally = (size_t)1 << ((hash >> LSB(am->mask + 1)) & branchMask); + if (tally & am->kvMap) { + + /* Hash is consistent with one of our KVList children... */ + loffset = NumBits(am->kvMap & (tally - 1)); + + if (am->slot[loffset] != (ClientData)hash) { + /* ...but does not actually match. Key not here. */ + + if (valuePtr) { + *valuePtr = NULL; + } + return am; + } + + /* Found the right KVList. Remove the pair from it. */ + l = KVLRemove(hamt, (KVList)am->slot[loffset + numList], key, + scratchPtr, valuePtr); + + if (l == am->slot[loffset + numList]) { + /* list unchanged -> ArrayMap unchanged. */ + return am; + } + + /* Create new ArrayMap with removed KVList */ + + if (l != NULL) { + if (am->canWrite && (am->canWrite == hamt->id)) { + am->size--; + KVLClaim(l); + KVLDisclaim(hamt, (KVList)am->slot[loffset + numList]); + am->slot[loffset + numList] = l; + return am; + } + + /* Modified copy of am, list replaced. */ + map = AMNew(hamt, numList, numSubnode, am->mask, am->id); + + map->size = am->size - 1; + map->kvMap = am->kvMap; + map->amMap = am->amMap; + + src = am->slot; + dst = map->slot; + /* Copy all hashes */ + for (i = 0; i < numList; i++) { + *dst++ = *src++; + } + + /* Copy list (except one we're replacing) */ + for (i = 0; i < loffset; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + src++; + KVLClaim(l); + *dst++ = l; + for (i = loffset + 1; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + + /* Copy all subnodes */ + for (i = 0; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + return map; + } + if (numList + numSubnode > 2) { + /* Modified copy of am, list removed. */ + map = AMNew(hamt, numList - 1, numSubnode, am->mask, am->id); + + map->size = am->size - 1; + map->kvMap = am->kvMap & ~tally; + map->amMap = am->amMap; + + src = am->slot; + dst = map->slot; + + /* Copy hashes (except one we're deleting) */ + for (i = 0; i < loffset; i++) { + *dst++ = *src++; + } + src++; + for (i = loffset + 1; i < numList; i++) { + *dst++ = *src++; + } + + /* Copy list (except one we're deleting) */ + for (i = 0; i < loffset; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + src++; + for (i = loffset + 1; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + + /* Copy all subnodes */ + for (i = 0; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + return map; + } + if (numSubnode) { + /* Removal will leave the subnode. */ + return (ArrayMap)am->slot[2]; + } else { + /* Removal will leave a list. */ + *hashPtr = (size_t) am->slot[1 - loffset]; + *listPtr = (KVList) am->slot[3 - loffset]; + return NULL; + } + } + if (tally & am->amMap) { + size_t subhash; + ArrayMap child; + + /* Hash is consistent with one of our subnode children... */ + soffset = NumBits(am->amMap & (tally - 1)); + child = (ArrayMap)am->slot[2*numList + soffset]; + sub = AMRemove(hamt, child, hash, key, + scratchPtr, &subhash, &l, valuePtr); + + if (sub) { + if (am->canWrite && (am->canWrite == hamt->id)) { + am->size = am->size - child->size + sub->size; + AMClaim(sub); + AMDisclaim(hamt, child); + am->slot[2*numList + soffset] = sub; + return am; + } + + /* Modified copy of am, subnode replaced. */ + map = AMNew(hamt, numList, numSubnode, am->mask, am->id); + + map->size = am->size - child->size + sub->size; + map->kvMap = am->kvMap; + map->amMap = am->amMap; + + src = am->slot; + dst = map->slot; + /* Copy all hashes */ + for (i = 0; i < numList; i++) { + *dst++ = *src++; + } + + /* Copy all lists */ + for (i = 0; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + + /* Copy subnodes */ + for (i = 0; i < soffset; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + src++; + AMClaim(sub); + *dst++ = sub; + for (i = soffset + 1; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + return map; + } else { + /* Modified copy of am, + list - sub */ + + loffset = NumBits(am->kvMap & (tally - 1)); + + map = AMNew(hamt, numList + 1, numSubnode - 1, am->mask, am->id); + + map->size = am->size - child->size + 1; + + map->kvMap = am->kvMap | tally; + map->amMap = am->amMap & ~tally; + + src = am->slot; + dst = map->slot; + /* Copy hashes (up to one we're inserting) */ + for (i = 0; i < loffset; i++) { + *dst++ = *src++; + } + *dst++ = (ClientData) subhash; + for (i = loffset; i < numList; i++) { + *dst++ = *src++; + } + + /* Copy list (except one we're deleting) */ + for (i = 0; i < loffset; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + KVLClaim(l); + *dst++ = l; + for (i = loffset; i < numList; i++) { + KVLClaim((KVList) *src); + *dst++ = *src++; + } + + /* Copy subnodes and add the new one */ + for (i = 0; i < soffset; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + src++; + for (i = soffset + 1; i < numSubnode; i++) { + AMClaim((ArrayMap) *src); + *dst++ = *src++; + } + + return map; + } + } + + /* Key is not here. */ + if (valuePtr) { + *valuePtr = NULL; + } + return am; +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTCreate -- + * + * Create and return a new empty TclHAMT, with key operations + * governed by the TclHAMTType struct pointed to by hktPtr. + * + * Results: + * A new empty TclHAMT. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TclHAMT +TclHAMTCreate( + const TclHAMTKeyType *kt, /* Custom key handling functions */ + const TclHAMTValueType *vt) /* Custom value handling functions */ +{ + HAMT *hamt = (HAMT *)Tcl_Alloc(sizeof(HAMT)); + + hamt->id = 0; + hamt->claim = 0; + hamt->kt = kt; + hamt->vt = vt; + hamt->kvl = NULL; + hamt->x.am = NULL; + hamt->overflow = NULL; + return hamt; +} + +TclHAMT +TclHAMTLock( + TclHAMT hamt) +{ + TclHAMT map; + + if (hamt->id == 0) { + return hamt; /* Already a locked immutable HAMT */ + } + map = TclHAMTCreate(hamt->kt, hamt->vt); + if (hamt->kvl) { + KVLClaim(hamt->kvl); + map->kvl = hamt->kvl; + map->x.hash = hamt->x.hash; + } else if (hamt->x.am) { + AMClaim(hamt->x.am); + map->x.am = hamt->x.am; + } + if (hamt->overflow) { + CNClaim(hamt->overflow); + map->overflow = hamt->overflow; + } + hamt->id = 0; /* Lock it! */ + /* TODO: Appears we just made an identical copy */ + /* Rethink the details of this. */ + return map; +} + +TclHAMT +TclHAMTUnlock( + TclHAMT hamt) +{ + TclHAMT map; + if (hamt->id) { + /* TODO: consider alternatives */ + Tcl_Panic("Already unlocked"); + } + map = TclHAMTCreate(hamt->kt, hamt->vt); + map->id = HAMTId++; /* TODO: thread safety */ + if (hamt->kvl) { + KVLClaim(hamt->kvl); + map->kvl = hamt->kvl; + map->x.hash = hamt->x.hash; + } else if (hamt->x.am) { + AMClaim(hamt->x.am); + map->x.am = hamt->x.am; + } + if (hamt->overflow) { + CNClaim(hamt->overflow); + map->overflow = hamt->overflow; + } + return map; +} + +static +TclHAMT HAMTNewList( + TclHAMT hamt, + KVList l, + size_t hash, + Collision overflow) +{ + TclHAMT map; + + KVLClaim(l); + if (overflow) { + CNClaim(overflow); + } + + if (hamt->id) { + /* transient -> overwrite */ + map = hamt; + if (map->kvl) { + KVLDisclaim(map, map->kvl); + } else if (map->x.am) { + AMDisclaim(map, map->x.am); + } + if (map->overflow) { + CNDisclaim(map, map->overflow); + } + } else { + map = TclHAMTCreate(hamt->kt, hamt->vt); + } + + map->kvl = l; + map->x.hash = hash; + map->overflow = overflow; + return map; +} + +static +TclHAMT HAMTNewRoot( + TclHAMT hamt, + ArrayMap am, + Collision overflow) +{ + TclHAMT map; + + AMClaim(am); + if (overflow) { + CNClaim(overflow); + } + + if (hamt->id) { + /* transient -> overwrite */ + map = hamt; + if (map->kvl) { + KVLDisclaim(map, map->kvl); + map->kvl = NULL; + } else if (map->x.am) { + AMDisclaim(map, map->x.am); + } + if (map->overflow) { + CNDisclaim(map, map->overflow); + } + } else { + map = TclHAMTCreate(hamt->kt, hamt->vt); + } + + map->x.am = am; + map->overflow = overflow; + return map; +} + +/* + * This routine is some post-processing after a merge or insert operation + * on one and possibly two has resulted in a hash collision leaving some + * KVPair(s) in the scratch list. We must produce the collision overflow + * for the hamt result of the merge or insert operation. + */ +static +Collision CollisionMerge( + HAMT *one, + HAMT *two, + Collision scratch) +{ + /* Everything on the scratch list will be in the final overflow list */ + Collision p, result = scratch; + + /* A pair on the second overflow list will be on the final list unless + * its key is already on the scratch list. */ + if (two && two->overflow) { + if (scratch == NULL) { + result = two->overflow; + } else { + p = two->overflow; + while (p) { + Collision q = scratch; + while (q) { + if (KVLEqualKeys(one, p->l->key, q->l->key)) { + break; + } + q = q->next; + } + if (q == NULL) { + result = CNNew(p->l, result); + } + p = p->next; + } + } + scratch = result; + } + /* A pair on the first overflow list will be on the final list unless + * its key is already on the scratch list. */ + if (one && one->overflow) { + if (scratch == NULL) { + result = one->overflow; + } else { + p = one->overflow; + while (p) { + Collision q = scratch; + while (q) { + if (KVLEqualKeys(one, p->l->key, q->l->key)) { + break; + } + q = q->next; + } + if (q == NULL) { + result = CNNew(p->l, result); + } + p = p->next; + } + } + } + + return result; +} + +/* + * This routine is some post-processing after a remove operation + * on hamt has resulted in a hash collision leaving some + * KVPair(s) in the scratch list. We must produce the collision overflow + * left when the item on the scratch list is removed from hamt->overflow. + */ +static +Collision CollisionRemove( + HAMT *hamt, + Collision scratch) +{ + Collision result, last, p = hamt->overflow; + if (scratch == NULL) { + return hamt->overflow; + } + if (scratch->next != NULL) { + Tcl_Panic("Remove op put multiple items on the scratch list"); + } + if (p == NULL) { + Tcl_Panic("Empty collision list, but item on scratch"); + } + if (p->l == scratch->l) { + return p->next; + } + result = last = CNNew(p->l, NULL); + while (p->next) { + p = p->next; + if (p->l == scratch->l) { + last->next = p->next; + return result; + } + last->next = CNNew(p->l, NULL); + last = last->next; + } + Tcl_Panic("Scratch item not on the collision list"); +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTClaim-- + * + * Record a claim on a TclHAMT. + * + * Results: + * None. + * + * Side effects: + * HAMT is claimed. + * + *---------------------------------------------------------------------- + */ + +void +TclHAMTClaim( + TclHAMT hamt) +{ + assert ( hamt != NULL ); + hamt->claim++; +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTDisclaim-- + * + * Release a claim on a TclHAMT. + * + * Results: + * None. + * + * Side effects: + * HAMT is released. Other claims may release. Memory may free. + * + *---------------------------------------------------------------------- + */ + +void +TclHAMTDisclaim( + TclHAMT hamt) +{ + if (hamt == NULL) { + return; + } + hamt->claim--; + if (hamt->claim) { + return; + } + if (hamt->kvl) { + KVLDisclaim(hamt, hamt->kvl); + hamt->kvl = NULL; + hamt->x.hash = 0; + } else if (hamt->x.am) { + AMDisclaim(hamt, hamt->x.am); + hamt->x.am = NULL; + } + if (hamt->overflow) { + CNDisclaim(hamt, hamt->overflow); + } + hamt->kt = NULL; + hamt->vt = NULL; + Tcl_Free(hamt); +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTFetch -- + * + * Lookup key in the key/value map. + * + * Results: + * The corresponding value, or NULL, if the key was not in the map. + * + * NOTE: This design is using NULL to indicate "not found". + * The implication is that NULL cannot be in the valid value range. + * This limits the value types this HAMT design can support. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +ClientData +TclHAMTFetch( + TclHAMT hamt, + ClientData key) +{ + if (hamt->kvl) { + /* Map holds a single KVList. Is it for the right hash? */ + if (hamt->x.hash == Hash(hamt, key)) { + /* Yes, try to find key in it. */ + KVList l = KVLFind(hamt, hamt->kvl, key); + return l ? l->value : NULL; + } + /* No. Map doesn't hold the key. */ + return NULL; + } + if (hamt->x.am == NULL) { + /* Map is empty. No key is in it. */ + return NULL; + } + /* Map has a tree. Fetch from it. */ + return AMFetch(hamt, hamt->x.am, Hash(hamt, key), key); +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTInsert-- + * + * Insert new key, value pair into the TclHAMT. + * + * Results: + * The new revised TclHAMT. + * + * Side effects: + * If valuePtr is not NULL, write to *valuePtr the + * previous value associated with key in the TclHAMT, + * or NULL if the key is new to the map. + * + *---------------------------------------------------------------------- + */ + +TclHAMT +TclHAMTInsert( + TclHAMT hamt, + ClientData key, + ClientData value, + ClientData *valuePtr) +{ + KVList l; + ArrayMap am; + Collision scratch = NULL; + + if (hamt->kvl) { + /* Map holds a single KVList. Is it for the same hash? */ + size_t hash = Hash(hamt, key); + if (hamt->x.hash == hash) { + /* Yes. Indeed we have a hash collision! This is the right + * KVList to insert our pair into. */ + l = KVLInsert(hamt, hamt->kvl, key, value, &scratch, valuePtr); + scratch = CollisionMerge(hamt, NULL, scratch); + if ((l == hamt->kvl) && (scratch == hamt->overflow)) { + /* list unchanged -> HAMT unchanged. */ + return hamt; + } + + /* Construct a new HAMT with a new kvl */ + return HAMTNewList(hamt, l, hash, scratch); + } + /* No. Insertion should not be into the singleton KVList. + * We get to build a tree out of the singleton KVList and + * a new list holding our new pair. */ + + return HAMTNewRoot(hamt, + AMNewLeaf(hamt, hamt->x.hash, hamt->kvl, hash, + KVLInsert(hamt, NULL, key, value, NULL, valuePtr)), + hamt->overflow); + } + if (hamt->x.am == NULL) { + /* Map is empty. No key is in it. Create singleton KVList + * out of new pair. */ + return HAMTNewList(hamt, + KVLInsert(hamt, NULL, key, value, NULL, valuePtr), + Hash(hamt, key), NULL); + } + /* Map has a tree. Insert into it. */ + am = AMInsert(hamt, hamt->x.am, + Hash(hamt, key), key, value, &scratch, valuePtr); + scratch = CollisionMerge(hamt, NULL, scratch); + if ((am == hamt->x.am) && (scratch == hamt->overflow)) { + /* Map did not change (overwrite same value) */ + return hamt; + } + return HAMTNewRoot(hamt, am, scratch); +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTRemove-- + * + * Remove the key, value pair from hamt that contains the + * given key, if any. + * + * Results: + * The new revised TclHAMT. + * + * Side effects: + * If valuePtr is not NULL, write to *valuePtr the + * value of the removed key, value pair, or NULL if + * no pair was removed. + * + *---------------------------------------------------------------------- + */ + +TclHAMT +TclHAMTRemove( + TclHAMT hamt, + ClientData key, + ClientData *valuePtr) +{ + size_t hash; + KVList l; + ArrayMap am; + Collision scratch = NULL; + + if (hamt->kvl) { + /* Map holds a single KVList. Is it for the same hash? */ + if (hamt->x.hash == Hash(hamt, key)) { + /* Yes. Indeed we have a hash collision! This is the right + * KVList to remove our pair from. */ + + l = KVLRemove(hamt, hamt->kvl, key, &scratch, valuePtr); + + scratch = CollisionRemove(hamt, scratch); + if ((l == hamt->kvl) && (scratch == hamt->overflow)) { + /* list unchanged -> HAMT unchanged. */ + return hamt; + } + + /* Construct a new HAMT with a new kvl */ + if (l) { + return HAMTNewList(hamt, + l, hamt->x.hash, scratch); + } + /* TODO: Implement a shared empty HAMT ? */ + /* CAUTION: would need one for each set of key & value types */ + return TclHAMTCreate(hamt->kt, hamt->vt); + } + + /* The key is not in the only KVList we have. */ + if (valuePtr) { + *valuePtr = NULL; + } + return hamt; + } + if (hamt->x.am == NULL) { + /* Map is empty. No key is in it. */ + if (valuePtr) { + *valuePtr = NULL; + } + return hamt; + } + + /* Map has a tree. Remove from it. */ + am = AMRemove(hamt, hamt->x.am, Hash(hamt, key), key, + &scratch, &hash, &l, valuePtr); + scratch = CollisionRemove(hamt, scratch); + if ((am == hamt->x.am) && (scratch == hamt->overflow)) { + /* Removal was no-op. */ + return hamt; + } + + if (am) { + return HAMTNewRoot(hamt, am, scratch); + } + return HAMTNewList(hamt, l, hash, scratch); +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTMerge -- + * + * Merge two TclHAMTS. + * + * Results: + * The new TclHAMT, merger of two arguments. + * + *---------------------------------------------------------------------- + */ + +TclHAMT +TclHAMTMerge( + TclHAMT one, + TclHAMT two) +{ + ArrayMap am; + Collision scratch = NULL; + + /* Sanity check for incompatible customizations. */ + if ((one->kt != two->kt) || (one->vt != two->vt)) { + /* For now, panic. Consider returning empty. */ + Tcl_Panic("Cannot merge incompatible HAMTs"); + } + + /* Merge to self */ + if (one == two) { + return one; + } + + /* Merge any into empty -> any */ + if ((one->kvl == NULL) && (one->x.am == NULL)) { + return two; + } + + /* Merge empty into any -> any */ + if ((two->kvl == NULL) && (two->x.am == NULL)) { + return one; + } + + /* Neither empty */ + if (one->kvl) { + if (two->kvl) { + /* Both are lists. */ + if (one->x.hash == two->x.hash) { + /* Same hash -> merge the lists */ + KVList l; + KVList l1 = one->kvl; + KVList l2 = two->kvl; + + if ((l1 == l2) && (two->overflow == NULL)) { + return one; + } + l = KVLMerge(one, l1, l2, &scratch, NULL); + scratch = CollisionMerge(one, two, scratch); + if (l == l1) { + /* Good possibility that one->kvl and two->kvl are + * identical values. If so, make them the same value. + * NOTE: Do this only for identical values, not just + * equal values. Equal, but distinct, keys should be + * preserved. */ + if (l != l2 && (l->key == l2->key) + && (l->value == l2->value)) { + /* Convert identical values to same values */ + KVLClaim(l); + KVLDisclaim(one, l2); + two->kvl = l; + } + if (scratch == one->overflow) { + return one; + } + } + if ((l == l2) && (scratch == two->overflow)) { + return two; + } + + return HAMTNewList(one, l, one->x.hash, scratch); + } + /* Different hashes; create leaf to hold pair */ + return HAMTNewRoot(one, + AMNewLeaf(one, one->x.hash, one->kvl, two->x.hash, two->kvl), + CollisionMerge(one, two, NULL)); + } + /* two has a tree */ + am = AMMergeList(one, two->x.am, one->x.hash, one->kvl, + &scratch, NULL, 1); + + scratch = CollisionMerge(one, two, scratch); + if ((am == two->x.am) && (scratch == two->overflow)) { + /* Merge gave back same tree. Avoid a copy. */ + return two; + } + return HAMTNewRoot(one, am, scratch); + } + + /* one has a tree */ + if (two->kvl) { + am = AMMergeList(one, one->x.am, two->x.hash, two->kvl, + &scratch, NULL, 0); + scratch = CollisionMerge(one, two, scratch); + if ((am == one->x.am) && (scratch == one->overflow)) { + /* Merge gave back same tree. Avoid a copy. */ + return one; + } + return HAMTNewRoot(one, am, scratch); + } + + /* Merge two trees */ + am = AMMerge(one, one->x.am, two->x.am, NULL, &scratch); + scratch = CollisionMerge(one, two, scratch); + if ((am == one->x.am) && (scratch == one->overflow)) { + return one; + } + if ((am == two->x.am) && (scratch == two->overflow)) { + return two; + } + return HAMTNewRoot(one, am, scratch); +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTSize -- + * + * Size of a TclHAMT. + * + * Results: + * A size_t value holding the number of key value pairs in hamt. + * + *---------------------------------------------------------------------- + */ + +size_t +TclHAMTSize( + TclHAMT hamt) +{ + size_t size = 0; + if (hamt->kvl) { + size = 1; + } else if (hamt->x.am) { + size = hamt->x.am->size; + } + if (hamt->overflow) { + Collision p = hamt->overflow; + while (p) { + size++; + p = p->next; + } + } + return size; +} + + +/* A struct to hold our place as we iterate through a HAMT */ + +typedef struct Idx { + TclHAMT hamt; + Collision overflow; + KVList kvl; /* Traverse the KVList */ + KVList *kvlv; /* Traverse a KVList array... */ + int kvlc; /* ... until no more. */ + ArrayMap *top; /* Active KVList array is in the */ + ArrayMap stack[]; /* ArrayMap at top of stack. */ +} Idx; + + +/* + *---------------------------------------------------------------------- + * + * TclHAMTFirst -- + * + * Starts an iteration through hamt. + * + * Results: + * If hamt is empty, returns NULL. + * If hamt is non-empty, returns a TclHAMTIdx that refers to the + * first key, value pair in an interation through hamt. + * + *---------------------------------------------------------------------- + */ + +TclHAMTIdx +TclHAMTFirst( + TclHAMT hamt) +{ + const int branchShift = TclMSB(branchFactor); + const int depth = CHAR_BIT * sizeof(size_t) / branchShift; + + Idx *i; + ArrayMap am; + int n; + + assert ( hamt ); + + if (hamt->kvl == NULL && hamt->x.am == NULL) { + /* Empty */ + return NULL; + } + + i = (Idx *)Tcl_Alloc(sizeof(Idx) + depth*sizeof(ArrayMap)); + + /* + * We claim an interest in hamt. After that we need not claim any + * interest in any of its sub-parts since it already takes care of + * that for us. + */ + + TclHAMTClaim(hamt); + i->hamt = hamt; + i->overflow = hamt->overflow; + i->top = i->stack; + + if (hamt->kvl) { + /* One bucket */ + /* Our place is the only place. Pointing at the sole bucket */ + i->kvlv = &(hamt->kvl); + i->kvlc = 0; + i->kvl = i->kvlv[0]; + i->top[0] = NULL; + return i; + } + /* There's a tree. Must traverse it to leftmost KVList. */ + am = hamt->x.am; + while ((n = NumBits(am->kvMap)) == 0) { + /* No buckets in the ArrayMap; Must have subnodes. Go Left */ + i->top[0] = am; + i->top++; + am = (ArrayMap) am->slot[0]; + } + i->top[0] = am; + i->kvlv = (KVList *)(am->slot + n); + i->kvlc = n - 1; + i->kvl = i->kvlv[0]; + return i; +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTNext -- + * + * Given a non-NULL *idxPtr referring to key, value pair in an + * iteration of a hamt, transform it to refer to the next key, value + * pair in that iteration. + * If there are no more key, value pairs in the iteration, release + * all claims and overwrite *idxPtr with a NULL idx. + * + * Results: + * None. + *---------------------------------------------------------------------- + */ + +static void +HAMTNext( + TclHAMTIdx *idxPtr, + size_t *histPtr) +{ + Idx *i = *idxPtr; + ArrayMap am, popme; + ClientData *slotPtr; + int n, seen = 0; + + assert ( i ); + assert ( i->kvl ); + + /* On to the next KVList bucket. */ + if (i->kvlc) { + i->kvlv++; + i->kvlc--; + i->kvl = i->kvlv[0]; + return; + } + + /* On to the subnodes */ + if (i->top[0] == NULL) { + /* Only get here for hamt of one key, value pair. */ + if (i->overflow) { + i->kvl = i->overflow->l; + i->overflow = i->overflow->next; + return; + } + TclHAMTDone((TclHAMTIdx) i); + *idxPtr = NULL; + return; + } + + /* + * We're working through the subnodes. When we entered, i->kvlv + * pointed to a KVList within ArrayMap i->top[0], and it must have + * pointed to the last one. Either this ArrayMap has subnodes or + * it doesn't. + */ + while (1) { + if (NumBits(i->top[0]->amMap) - seen) { + /* There are subnodes. Traverse to the leftmost KVList. */ + am = (ArrayMap)(i->kvlv[1]); + + i->top++; + while ((n = NumBits(am->kvMap)) == 0) { + /* No buckets in the ArrayMap; Must have subnodes. Go Left */ + i->top[0] = am; + i->top++; + am = (ArrayMap) am->slot[0]; + } + i->top[0] = am; + i->kvlv = (KVList *)(am->slot + n); + i->kvlc = n - 1; + i->kvl = i->kvlv[0]; + return; + } + + /* i->top[0] is an ArrayMap with no subnodes. We're done with it. + * Need to pop. */ + popme = i->top[0]; + /* Account for nodes as they pop */ + if (histPtr) { + histPtr[2*NumBits(popme->kvMap) + NumBits(popme->amMap)]++; + } + + if (i->top == i->stack) { + /* Nothing left to pop. Stack exhausted. We're done. */ + if (i->overflow) { + i->kvl = i->overflow->l; + i->overflow = i->overflow->next; + i->top[0] = NULL; + return; + } + TclHAMTDone((TclHAMTIdx) i); + *idxPtr = NULL; + return; + } + i->top[0] = NULL; + i->top--; + am = i->top[0]; + slotPtr = am->slot + 2*NumBits(am->kvMap); + seen = 1; + while (slotPtr[0] != (ClientData)popme) { + seen++; + slotPtr++; + } + i->kvlv = (KVList *)slotPtr; + + } +} + +void +TclHAMTNext( + TclHAMTIdx *idxPtr) +{ + HAMTNext(idxPtr, NULL); +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTGet -- + * + * Given an idx returned by TclHAMTFirst() or TclHAMTNext() and + * never passed to TclHAMtDone(), retrieve the key and value it + * refers to. + * + *---------------------------------------------------------------------- + */ + +void +TclHAMTGet( + TclHAMTIdx idx, + ClientData *keyPtr, + ClientData *valuePtr) +{ + Idx *i = idx; + + assert ( i ); + assert ( i->kvl ); + assert ( keyPtr ); + assert ( valuePtr ); + + *keyPtr = i->kvl->key; + *valuePtr = i->kvl->value; +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTDone -- + * + * Given an idx returned by TclHAMTFirst() or TclHAMTNext() and + * never passed to TclHAMtDone(), release any claims. + * + *---------------------------------------------------------------------- + */ + +void +TclHAMTDone( + TclHAMTIdx idx) +{ + Idx *i = idx; + + TclHAMTDisclaim(i->hamt); + i->hamt = NULL; + Tcl_Free(i); +} + +/* + *---------------------------------------------------------------------- + * + * TclHAMTInfo -- + * + * Statistical information on a hamt. + * + * Results: + * A Tcl_Obj holding text description of storage stats. + * + *---------------------------------------------------------------------- + */ + +Tcl_Obj * +TclHAMTInfo( + TclHAMT hamt) +{ + const int branchShift = TclMSB(branchFactor); + const int depth = CHAR_BIT * sizeof(size_t) / branchShift; + size_t *accum = (size_t *)Tcl_Alloc(depth*sizeof(size_t)); + size_t size = TclHAMTSize(hamt); + double avg = 0.0; + int i, collisions = 0; + size_t nodes = 0; + size_t numBytes = 0; + size_t slots = 0; + size_t hist[129]; + + TclHAMTIdx idx = TclHAMTFirst(hamt); + Tcl_Obj *result = Tcl_NewStringObj("hamt holds ", -1); + Tcl_Obj *count = Tcl_NewWideIntObj((Tcl_WideInt)size); + + Tcl_AppendObjToObj(result, count); + Tcl_AppendToObj(result, " pairs", -1); + Tcl_DecrRefCount(count); + + for (i = 0; i < depth; i++) { + accum[i] = 0; + } + for (i = 0; i < 129; i++) { + hist[i] = 0; + } + + while (idx) { + accum[ idx->top - idx->stack ]++; + HAMTNext(&idx, hist); + } + + if (hamt->overflow) { + Collision p = hamt->overflow; + while (p) { + collisions++; + p = p->next; + } + } + Tcl_AppendPrintfToObj(result, "\nnumber of collisions: %d", collisions); + + for (i = 0; i < 129; i++) { + + if (hist[i] == 0) continue; + + Tcl_AppendPrintfToObj(result, "\nnumber of nodes with %2d slots: ", i); + count = Tcl_NewWideIntObj((Tcl_WideInt)hist[i]); + Tcl_AppendObjToObj(result, count); + Tcl_DecrRefCount(count); + + nodes += hist[i]; + slots += hist[i] * i; + numBytes += hist[i] * ((i * sizeof(void *)) + sizeof(AMNode)); + } + if (nodes) { + Tcl_AppendToObj(result, "\nnumber of nodes: ", -1); + count = Tcl_NewWideIntObj((Tcl_WideInt)nodes); + Tcl_AppendObjToObj(result, count); + Tcl_DecrRefCount(count); + Tcl_AppendToObj(result, "\namount of node memory: ", -1); + count = Tcl_NewWideIntObj((Tcl_WideInt)numBytes); + Tcl_AppendObjToObj(result, count); + Tcl_DecrRefCount(count); + Tcl_AppendPrintfToObj(result, "\naverage slots per node: %g", + (1.0 * slots)/nodes); + Tcl_AppendPrintfToObj(result, "\naverage bytes per node: %g", + (1.0 * numBytes)/nodes); + Tcl_AppendPrintfToObj(result, "\naverage pairs per node: %g", + (1.0 * size)/nodes); + } + + if (size) { + for (i = 0; i < depth; i++) { + double fraction; + + if (accum[i] == 0) continue; + Tcl_AppendPrintfToObj(result, "\nnumber of leafs at %2d hops: ", i); + count = Tcl_NewWideIntObj((Tcl_WideInt)accum[i]); + Tcl_AppendObjToObj(result, count); + Tcl_DecrRefCount(count); + + fraction = (1.0 * accum[i]) / size; + avg += i * fraction; + } + Tcl_AppendPrintfToObj(result, "\naverage hops: %g ", avg); + } + Tcl_Free(accum); + + return result; +} + + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ ADDED generic/tclHAMT.h Index: generic/tclHAMT.h ================================================================== --- /dev/null +++ generic/tclHAMT.h @@ -0,0 +1,127 @@ +/* + * tclHAMT.h -- + * + * This file contains the declarations of the types and routines + * of the hash array map trie . + * + * Contributions from Don Porter, NIST, 2015-2017. (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. + */ + +#ifndef TCL_HAMT_H +#define TCL_HAMT_H + +#include "tclInt.h" + +/* + * The point of this data structure is to store a map from keys to + * values. Let's first establish what keys and values are. We + * want to be usable by creators with different perspectives on that, + * so we build in some configurability by letting a creator describe + * what we need to know about keys and values via defining their "type". + * + * We will store values (received as ClientData) and some kinds of + * values will want to be notified when we start holding on to them + * and conversely when we declare we are not using them any more. + * They can define routines of the following types to be called back + * at those times. + * + * We will also store keys (also received as ClientData), so they also + * have the opporunity to define these callbacks. + * + * If the creator has no need of these notifications, the type or its + * fields can be left NULL. + */ + +typedef void (TclClaimProc) (ClientData value); + +/* + * We also need to operate on keys. First we need to be able to check + * when two key values are the same according to the logic of the + * creator. We make the assumption that identical key values are seen + * as the same key by any plausible creator logic. But when key values + * are distinct, they may still represent "the same" key when interpreted + * as the creator intends. If so, the creator must give us a callback + * routine we can use to check that. + */ + +typedef int (TclIsEqualProc) (ClientData x, ClientData y); + +/* + * Finally we expect the creator to tell us what hash function to use + * on its set of keys. The hash value has type size_t. Good hash + * functions will distribute hash values evenly over the whole size_t + * range given the domain of key values. Good hash functions should also + * compute as quickly as possible. Since our view on the key is a single + * ClientData, the number of possible distinct keys is the same as the + * number of possible hashes. If the creator fails to specify a hash + * function, we will just use the key value as its own hash. + */ + +typedef size_t (TclHashProc) (ClientData key); + +/* + * The TclHAMTValueType gathers together the callback routines needed + * for the creator to describe its values. + */ + +typedef struct { + TclClaimProc *makeRefProc; + TclClaimProc *dropRefProc; +} TclHAMTValueType; + +/* + * The TclHAMTKeyType gathers together the callback routines needed + * for the creator to describe its keys. + */ + +typedef struct { + TclClaimProc *makeRefProc; + TclClaimProc *dropRefProc; + TclIsEqualProc *isEqualProc; + TclHashProc *hashProc; +} TclHAMTKeyType; + +/* + * Opaque pointers to define the protoypes. + */ + +typedef struct HAMT *TclHAMT; +typedef struct Idx *TclHAMTIdx; + +/* + * Interface procedure declarations. + */ + +MODULE_SCOPE TclHAMT TclHAMTCreate(const TclHAMTKeyType *ktPtr, + const TclHAMTValueType *vtPtr); +MODULE_SCOPE void TclHAMTClaim(TclHAMT hamt); +MODULE_SCOPE void TclHAMTDisclaim(TclHAMT hamt); +MODULE_SCOPE TclHAMT TclHAMTInsert(TclHAMT hamt, ClientData key, + ClientData value, ClientData *valuePtr); +MODULE_SCOPE TclHAMT TclHAMTRemove(TclHAMT hamt, ClientData key, + ClientData *valuePtr); +MODULE_SCOPE ClientData TclHAMTFetch(TclHAMT hamt, ClientData key); +MODULE_SCOPE TclHAMT TclHAMTMerge(TclHAMT one, TclHAMT two); +MODULE_SCOPE size_t TclHAMTSize(TclHAMT hamt); +MODULE_SCOPE TclHAMT TclHAMTLock(TclHAMT hamt); +MODULE_SCOPE TclHAMT TclHAMTUnlock(TclHAMT hamt); + +MODULE_SCOPE TclHAMTIdx TclHAMTFirst(TclHAMT hamt); +MODULE_SCOPE void TclHAMTNext(TclHAMTIdx *idxPtr); +MODULE_SCOPE void TclHAMTGet(TclHAMTIdx idx, ClientData *keyPtr, + ClientData *valuePtr); +MODULE_SCOPE void TclHAMTDone(TclHAMTIdx idx); +MODULE_SCOPE Tcl_Obj * TclHAMTInfo(TclHAMT hamt); + +#endif /* TCL_HAMT_H */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ ADDED generic/tclHAMTObj.c Index: generic/tclHAMTObj.c ================================================================== --- /dev/null +++ generic/tclHAMTObj.c @@ -0,0 +1,3609 @@ +/* + * tclHAMTObj.c -- + * + * This file contains functions that implement the Tcl hamt object type + * and its accessor command. + * + * Contributions from Don Porter, NIST, 2015-2017. (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 "tclHAMT.h" + +/* + * Prototypes for functions defined later in this file: + */ + +static void SetHAMTObj(Tcl_Obj *objPtr, TclHAMT hamt); +static TclHAMT GetHAMTFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr); +static Tcl_Obj *NewHAMTObj(TclHAMT hamt); + +static TclClaimProc ObjClaim; +static TclClaimProc ObjDisclaim; +static TclIsEqualProc ObjKeyIsEqual; +static TclHashProc ObjKeyHash; + +static Tcl_DupInternalRepProc DupHamtInternalRep; +static Tcl_FreeInternalRepProc FreeHamtInternalRep; +static Tcl_SetFromAnyProc SetHamtFromAny; +static Tcl_UpdateStringProc UpdateStringOfHamt; + +/* Customizing structs for the HAMT */ + +const TclHAMTValueType hamtValueType = { + ObjClaim, /* makeRefProc */ + ObjDisclaim /* dropRefProc */ +}; + +const TclHAMTKeyType hamtKeyType = { + ObjClaim, /* makeRefProc */ + ObjDisclaim, /* dropRefProc */ + ObjKeyIsEqual, /* isEqualProc */ + ObjKeyHash /* hashProc */ +}; + +/* + * Accessor macro for converting between a Tcl_Obj* and a Dict. Note that this + * must be assignable as well as readable. + */ +#define HAMT(hamtObj) (*((TclHAMT *)&(hamtObj)->internalRep.twoPtrValue.ptr1)) + +/* + * The structure below defines the hamt object type by means of + * functions that can be invoked by generic object code. + */ + +const Tcl_ObjType hamtType = { + "hamt", + FreeHamtInternalRep, /* freeIntRepProc */ + DupHamtInternalRep, /* dupIntRepProc */ + UpdateStringOfHamt, /* updateStringProc */ + SetHamtFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V0 +}; + +/* + *---------------------------------------------------------------------- + * + * ObjClaim, ObjDisclaim -- + * + * Manage refcounting of keys and values held in HAMT. + * + *---------------------------------------------------------------------- + */ + +static +void ObjClaim( + ClientData clientData) +{ + Tcl_Obj *objPtr = (Tcl_Obj *)clientData; + + Tcl_IncrRefCount(objPtr); +} + +static +void ObjDisclaim( + ClientData clientData) +{ + Tcl_Obj *objPtr = (Tcl_Obj *)clientData; + + Tcl_DecrRefCount(objPtr); +} + +/* + *---------------------------------------------------------------------- + * + * ObjKeyIsEqual -- + * + * Check two Tcl_Obj keys, k1 and k2, for equality. + * It is assumed the two arguments are different. The caller + * is expected to know a key is equal to itself and not ask us. + * + * Results: + * Boolean indicating whether the keys are equal. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static +int ObjKeyIsEqual( + ClientData k1, + ClientData k2) +{ + Tcl_Obj *objPtr1 = (Tcl_Obj *)k1; + Tcl_Obj *objPtr2 = (Tcl_Obj *)k2; + const char *p1, *p2; + size_t l1, l2; + + p1 = TclGetString(objPtr1); + l1 = objPtr1->length; + p2 = TclGetString(objPtr2); + l2 = objPtr2->length; + + /* + * Only compare if the string representations are of the same length. + */ + + if (l1 == l2) { + for (;; p1++, p2++, l1--) { + if (*p1 != *p2) { + break; + } + if (l1 == 0) { + return 1; + } + } + } + + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * ObjKeyHash -- + * + * Compute a size_t hash of the string representation of the Tcl_Obj. + * + * Results: + * The hash value. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static +size_t ObjKeyHash( + ClientData key) /* Key from which to compute hash value. */ +{ + Tcl_Obj *objPtr = (Tcl_Obj *)key; + const char *string = TclGetString(objPtr); + size_t length = objPtr->length; + size_t result = 0; + + if (length > 0) { + result = UCHAR(*string); + while (--length) { + result += (result << 3) + UCHAR(*++string); + } + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * DupHamtInternalRep -- + * + * Initialize the internal representation of a hamt Tcl_Obj to a + * copy of the internal representation of an existing hamt object. + * + * Results: + * None. + * + * Side effects: + * "srcPtr"s dictionary internal rep pointer should not be NULL and we + * assume it is not NULL. We set "copyPtr"s internal rep to a pointer to + * a newly allocated dictionary rep that, in turn, points to "srcPtr"s + * key and value objects. Those objects are not actually copied but are + * shared between "srcPtr" and "copyPtr". The ref count of each key and + * value object is incremented. + * + *---------------------------------------------------------------------- + */ + +static void +DupHamtInternalRep( + Tcl_Obj *srcPtr, + Tcl_Obj *copyPtr) +{ + TclHAMT hamt = HAMT(srcPtr); + + TclHAMTClaim(hamt); + HAMT(copyPtr) = hamt; + + copyPtr->internalRep.twoPtrValue.ptr2 = NULL; + copyPtr->typePtr = &hamtType; +} + +/* + *---------------------------------------------------------------------- + * + * FreeHamtInternalRep -- + * + * Release a claim on the hamt object's internal representation. + * + * Results: + * None + *---------------------------------------------------------------------- + */ + +static void +FreeHamtInternalRep( + Tcl_Obj *objPtr) +{ + TclHAMT hamt = HAMT(objPtr); + + TclHAMTDisclaim(hamt); + HAMT(objPtr) = NULL; + objPtr->typePtr = NULL; +} + +/* + *---------------------------------------------------------------------- + * + * SetHamtFromAny -- + * + * Convert a non-hamt object into a hamt object. Build on top of + * list infrastructure. Get it working correctly. Streamline later. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * If conversion succeeds, hamt internal rep is stored. + * + *---------------------------------------------------------------------- + */ + +static int +SetHamtFromAny( + Tcl_Interp *interp, + Tcl_Obj *objPtr) +{ + Tcl_Size i, objc; + Tcl_Obj **objv; + TclHAMT old, unlocked; + + if (objPtr->typePtr == &hamtType) { + return TCL_OK; + } + + if (TCL_OK != TclListObjGetElementsM(interp, objPtr, &objc, &objv)) { + return TCL_ERROR; + } + + if (objc & 1) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "missing value attempting to create hamt", -1)); + Tcl_SetErrorCode(interp, "TCL", "HAMT", "MISSING", "VALUE", NULL); + return TCL_ERROR; + } + + /* Iterative insertion */ + /* TODO: When transients are available, use them. */ + /* TODO: Consider copy by merges instead? */ + old = TclHAMTCreate( &hamtKeyType, &hamtValueType); + TclHAMTClaim(old); + unlocked = TclHAMTUnlock(old); + TclHAMTClaim(unlocked); + TclHAMTDisclaim(old); + old = unlocked; + for (i = 0; i < objc; i += 2) { + TclHAMT hamt = TclHAMTInsert(old, objv[i], objv[i+1], NULL); + TclHAMTClaim(hamt); + TclHAMTDisclaim(old); + old = hamt; + } + + TclFreeInternalRep(objPtr); + SetHAMTObj(objPtr, old); + TclHAMTDisclaim(old); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * UpdateStringOfHamt -- + * + * Update the string representation for a hamt object. + * + * Results: + * None. + *---------------------------------------------------------------------- + */ + +static Tcl_Obj * +HamtToList( + TclHAMT hamt) +{ + TclHAMTIdx idx = TclHAMTFirst(hamt); + Tcl_Obj *listPtr = Tcl_NewObj(); + while (idx) { + Tcl_Obj *keyPtr; + Tcl_Obj *valuePtr; + + TclHAMTGet(idx, (ClientData *)&keyPtr, (ClientData *)&valuePtr); + Tcl_ListObjAppendElement(NULL, listPtr, keyPtr); + Tcl_ListObjAppendElement(NULL, listPtr, valuePtr); + TclHAMTNext(&idx); + } + return listPtr; +} + +static void +UpdateStringOfHamt( + Tcl_Obj *objPtr) +{ + Tcl_Obj *listPtr = HamtToList(HAMT(objPtr)); + objPtr->bytes = Tcl_GetString(listPtr); + objPtr->bytes = listPtr->bytes; + listPtr->bytes = NULL; + Tcl_DecrRefCount(listPtr); +} + +/* + * Prototypes for functions defined later in this file: + */ + +static Tcl_ObjCmdProc HamtCreateCmd; +static Tcl_ObjCmdProc HamtGetCmd; +static Tcl_ObjCmdProc HamtInfoCmd; +static Tcl_ObjCmdProc HamtMergeCmd; +static Tcl_ObjCmdProc HamtRemoveCmd; +static Tcl_ObjCmdProc HamtReplaceCmd; +static Tcl_ObjCmdProc HamtSizeCmd; + +/* + * Table of hamt subcommand names and implementations. + */ + +static const EnsembleImplMap implementationMap[] = { + {"create", HamtCreateCmd, NULL, NULL, NULL, 0 }, + {"get", HamtGetCmd, NULL, NULL, NULL, 0 }, + {"info", HamtInfoCmd, NULL, NULL, NULL, 0 }, + {"merge", HamtMergeCmd, NULL, NULL, NULL, 0 }, + {"remove", HamtRemoveCmd, NULL, NULL, NULL, 0 }, + {"replace", HamtReplaceCmd, NULL, NULL, NULL, 0 }, + {"size", HamtSizeCmd, NULL, NULL, NULL, 0 }, + {NULL, NULL, NULL, NULL, NULL, 0} +}; + +static void +SetHAMTObj( + Tcl_Obj *objPtr, + TclHAMT hamt) +{ + TclHAMT locked = TclHAMTLock(hamt); + TclHAMTClaim(locked); + HAMT(objPtr) = locked; + objPtr->internalRep.twoPtrValue.ptr2 = NULL; + objPtr->typePtr = &hamtType; +} + +static Tcl_Obj * +NewHAMTObj( + TclHAMT hamt) +{ + Tcl_Obj *objPtr = Tcl_NewObj(); + + TclInvalidateStringRep(objPtr); + SetHAMTObj(objPtr, hamt); + return objPtr; +} + +static TclHAMT +GetHAMTFromObj( + Tcl_Interp *interp, + Tcl_Obj *objPtr) +{ + if (TCL_OK != SetHamtFromAny(interp, objPtr)) { + return NULL; + } + return HAMT(objPtr); +} +/* + *---------------------------------------------------------------------- + * + * HamtCreateCmd -- + * + * This function implements the "hamt create" Tcl command. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +HamtCreateCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Tcl_Obj *hamtObj = Tcl_NewListObj(objc - 1, objv + 1); + (void)dummy; + + if (NULL == GetHAMTFromObj(interp, hamtObj)) { + Tcl_DecrRefCount(hamtObj); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, hamtObj); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * HamtGetCmd -- + * + * This function implements the "hamt get" Tcl command. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +HamtGetCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + TclHAMT hamt; + Tcl_Obj *val = NULL; + (void)dummy; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "hamt ?key ...?"); + return TCL_ERROR; + } + + /* Make sure first argument is a hamt. */ + hamt = GetHAMTFromObj(interp, objv[1]); + if (NULL == hamt) { + return TCL_ERROR; + } + + /* No keys -> return list of all key value pairs */ + if (objc == 2) { + Tcl_SetObjResult(interp, HamtToList(hamt)); + return TCL_OK; + } + + objc -= 2; + objv += 2; + + while (objc--) { + val = (Tcl_Obj *)TclHAMTFetch(hamt, (ClientData)(*objv)); + + if (NULL == val) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "key \"%s\" not known in hamt", + TclGetString(*objv))); + + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HAMT", + TclGetString(*objv), NULL); + return TCL_ERROR; + } + + if (objc) { + hamt = GetHAMTFromObj(interp, val); + if (NULL == hamt) { + return TCL_ERROR; + } + objv++; + } + } + Tcl_SetObjResult(interp, val); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * HamtMergeCmd -- + * + * This function implements the "hamt merge" Tcl command. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +HamtMergeCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + TclHAMT accum; + int i; + (void)dummy; + + if (objc == 1) { + /* + * No dictionary arguments; return default (empty value). + */ + + return TCL_OK; + } + + /* + * Make sure first argument is a hamt. + */ + + accum = GetHAMTFromObj(interp, objv[1]); + if (NULL == accum) { + return TCL_ERROR; + } + + if (objc == 2) { + /* + * Single argument, return it. + */ + + Tcl_SetObjResult(interp, objv[1]); + return TCL_OK; + } + + /* + * Normal behaviour: combining two (or more) hamt. + */ + + accum = TclHAMTUnlock(accum); + TclHAMTClaim(accum); + + for (i=2 ; i 4) { + old = TclHAMTUnlock(old); + } + TclHAMTClaim(old); + for (i=2 ; ientry.key.objPtr = objPtr; + Tcl_IncrRefCount(objPtr); + Tcl_SetHashValue(&cPtr->entry, NULL); + cPtr->prevPtr = cPtr->nextPtr = NULL; + + return &cPtr->entry; +} + +/* + * Helper functions that disguise most of the details relating to how the + * linked list of hash entries is managed. In particular, these manage the + * creation of the table and initializing of the chain, the deletion of the + * table and chain, the adding of an entry to the chain, and the removal of an + * entry from the chain. + */ + +static inline void +InitChainTable( + Dict *dict) +{ + Tcl_InitCustomHashTable(&dict->table, TCL_CUSTOM_PTR_KEYS, + &chainHashType); + dict->entryChainHead = dict->entryChainTail = NULL; +} + +static inline void +DeleteChainTable( + Dict *dict) +{ + ChainEntry *cPtr; + + for (cPtr=dict->entryChainHead ; cPtr!=NULL ; cPtr=cPtr->nextPtr) { + Tcl_Obj *valuePtr = Tcl_GetHashValue(&cPtr->entry); + + TclDecrRefCount(valuePtr); + } + Tcl_DeleteHashTable(&dict->table); +} + +static inline Tcl_HashEntry * +CreateChainEntry( + Dict *dict, + Tcl_Obj *keyPtr, + int *newPtr) +{ + ChainEntry *cPtr = (ChainEntry *) + Tcl_CreateHashEntry(&dict->table, keyPtr, newPtr); + + /* + * If this is a new entry in the hash table, stitch it into the chain. + */ + + if (*newPtr) { + cPtr->nextPtr = NULL; + if (dict->entryChainHead == NULL) { + cPtr->prevPtr = NULL; + dict->entryChainHead = cPtr; + dict->entryChainTail = cPtr; + } else { + cPtr->prevPtr = dict->entryChainTail; + dict->entryChainTail->nextPtr = cPtr; + dict->entryChainTail = cPtr; + } + } + + return &cPtr->entry; +} + +static inline int +DeleteChainEntry( + Dict *dict, + Tcl_Obj *keyPtr) +{ + ChainEntry *cPtr = (ChainEntry *) + Tcl_FindHashEntry(&dict->table, keyPtr); + + if (cPtr == NULL) { + return 0; + } else { + Tcl_Obj *valuePtr = Tcl_GetHashValue(&cPtr->entry); + + TclDecrRefCount(valuePtr); + } + + /* + * Unstitch from the chain. + */ + + if (cPtr->nextPtr) { + cPtr->nextPtr->prevPtr = cPtr->prevPtr; + } else { + dict->entryChainTail = cPtr->prevPtr; + } + if (cPtr->prevPtr) { + cPtr->prevPtr->nextPtr = cPtr->nextPtr; + } else { + dict->entryChainHead = cPtr->nextPtr; + } + + Tcl_DeleteHashEntry(&cPtr->entry); + return 1; +} + +/* + *---------------------------------------------------------------------- + * + * DeleteDict -- + * + * Delete the structure that is used to implement a dictionary's internal + * representation. Called when either the dictionary object loses its + * internal representation or when the last iteration over the dictionary + * completes. + * + * Results: + * None + * + * Side effects: + * Decrements the reference count of all key and value objects in the + * dictionary, which may free them. + * + *---------------------------------------------------------------------- + */ + +static void +DeleteDict( + Dict *dict) +{ + DeleteChainTable(dict); + Tcl_Free(dict); +} + +/* + *---------------------------------------------------------------------- + * + * TclTraceDictPath -- + * + * Trace through a tree of dictionaries using the array of keys given. If + * the flags argument has the DICT_PATH_UPDATE flag is set, a + * backward-pointing chain of dictionaries is also built (in the Dict's + * chain field) and the chained dictionaries are made into unshared + * dictionaries (if they aren't already.) + * + * Results: + * The object at the end of the path, or NULL if there was an error. Note + * that this it is an error for an intermediate dictionary on the path to + * not exist. If the flags argument has the DICT_PATH_EXISTS set, a + * non-existent path gives a DICT_PATH_NON_EXISTENT result. + * + * Side effects: + * If the flags argument is zero or DICT_PATH_EXISTS, there are no side + * 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; + + if (dictPtr->typePtr != &tclDictType + && SetDictFromAny(interp, dictPtr) != TCL_OK) { + return NULL; + } + dict = DICT(dictPtr); + if (flags & DICT_PATH_UPDATE) { + dict->chain = NULL; + } + + for (i=0 ; itable, keyv[i]); + Tcl_Obj *tmpObj; + + if (hPtr == NULL) { + int isNew; /* Dummy */ + + if (flags & DICT_PATH_EXISTS) { + return DICT_PATH_NON_EXISTENT; + } + 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_GetHashValue(hPtr); + if (tmpObj->typePtr != &tclDictType + && SetDictFromAny(interp, tmpObj) != TCL_OK) { + return NULL; + } + } + + newDict = DICT(tmpObj); + if (flags & DICT_PATH_UPDATE) { + if (Tcl_IsShared(tmpObj)) { + TclDecrRefCount(tmpObj); + tmpObj = Tcl_DuplicateObj(tmpObj); + Tcl_IncrRefCount(tmpObj); + Tcl_SetHashValue(hPtr, tmpObj); + dict->epoch++; + newDict = DICT(tmpObj); + } + + 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 = DICT(dictObj); + + do { + TclInvalidateStringRep(dictObj); + dict->epoch++; + dictObj = dict->chain; + if (dictObj == NULL) { + break; + } + dict->chain = NULL; + dict = DICT(dictObj); + } while (dict != NULL); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DictObjPut -- + * + * Add a key,value pair to a dictionary, or update the value for a key if + * that key already has a mapping in the dictionary. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * The object pointed to by dictPtr is converted to a dictionary if it is + * not already one, and any string representation that it has is + * invalidated. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_DictObjPut( + Tcl_Interp *interp, + Tcl_Obj *dictPtr, + Tcl_Obj *keyPtr, + Tcl_Obj *valuePtr) +{ + Dict *dict; + Tcl_HashEntry *hPtr; + int isNew; + + if (Tcl_IsShared(dictPtr)) { + Tcl_Panic("%s called with shared object", "Tcl_DictObjPut"); + } + + if (dictPtr->typePtr != &tclDictType + && SetDictFromAny(interp, dictPtr) != TCL_OK) { + return TCL_ERROR; + } + + if (dictPtr->bytes != NULL) { + TclInvalidateStringRep(dictPtr); + } + dict = DICT(dictPtr); + hPtr = CreateChainEntry(dict, keyPtr, &isNew); + Tcl_IncrRefCount(valuePtr); + if (!isNew) { + Tcl_Obj *oldValuePtr = Tcl_GetHashValue(hPtr); + + TclDecrRefCount(oldValuePtr); + } + Tcl_SetHashValue(hPtr, valuePtr); + dict->epoch++; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DictObjGet -- + * + * Given a key, get its value from the dictionary (or NULL if key is not + * found in dictionary.) + * + * Results: + * A standard Tcl result. The variable pointed to by valuePtrPtr is + * updated with the value for the key. Note that it is not an error for + * the key to have no mapping in the dictionary. + * + * Side effects: + * The object pointed to by dictPtr is converted to a dictionary if it is + * not already one. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_DictObjGet( + Tcl_Interp *interp, + Tcl_Obj *dictPtr, + Tcl_Obj *keyPtr, + Tcl_Obj **valuePtrPtr) +{ + Dict *dict; + Tcl_HashEntry *hPtr; + + if (dictPtr->typePtr != &tclDictType + && SetDictFromAny(interp, dictPtr) != TCL_OK) { + *valuePtrPtr = NULL; + return TCL_ERROR; + } + + dict = DICT(dictPtr); + hPtr = Tcl_FindHashEntry(&dict->table, keyPtr); + if (hPtr == NULL) { + *valuePtrPtr = NULL; + } else { + *valuePtrPtr = Tcl_GetHashValue(hPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DictObjRemove -- + * + * Remove the key,value pair with the given key from the dictionary; the + * key does not need to be present in the dictionary. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * The object pointed to by dictPtr is converted to a dictionary if it is + * not already one, and any string representation that it has is + * invalidated. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_DictObjRemove( + Tcl_Interp *interp, + Tcl_Obj *dictPtr, + Tcl_Obj *keyPtr) +{ + Dict *dict; + + if (Tcl_IsShared(dictPtr)) { + Tcl_Panic("%s called with shared object", "Tcl_DictObjRemove"); + } + + if (dictPtr->typePtr != &tclDictType + && SetDictFromAny(interp, dictPtr) != TCL_OK) { + return TCL_ERROR; + } + + dict = DICT(dictPtr); + if (DeleteChainEntry(dict, keyPtr)) { + if (dictPtr->bytes != NULL) { + TclInvalidateStringRep(dictPtr); + } + dict->epoch++; + } + 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; + + if (dictPtr->typePtr != &tclDictType + && SetDictFromAny(interp, dictPtr) != TCL_OK) { + return TCL_ERROR; + } + + dict = DICT(dictPtr); + *sizePtr = dict->table.numEntries; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DictObjFirst -- + * + * Start a traversal of the dictionary. Caller must supply the search + * context, pointers for returning key and value, and a pointer to allow + * indication of whether the dictionary has been traversed (i.e. the + * dictionary is empty). The order of traversal is undefined. + * + * Results: + * A standard Tcl result. Updates the variables pointed to by keyPtrPtr, + * valuePtrPtr and donePtr. Either of keyPtrPtr and valuePtrPtr may be + * NULL, in which case the key/value is not made available to the caller. + * + * Side effects: + * The dictPtr object is converted to a dictionary type if it is not a + * dictionary already. The search context is initialised if the search + * has not finished. The dictionary's internal rep is Tcl_Preserve()d if + * the dictionary has at least one element. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_DictObjFirst( + Tcl_Interp *interp, /* For error messages, or NULL if no error + * messages desired. */ + Tcl_Obj *dictPtr, /* Dictionary to traverse. */ + Tcl_DictSearch *searchPtr, /* Pointer to a dict search context. */ + Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the first key + * written into, or NULL. */ + Tcl_Obj **valuePtrPtr, /* Pointer to a variable to have the first + * value written into, or NULL.*/ + int *donePtr) /* Pointer to a variable which will have a 1 + * written into when there are no further + * values in the dictionary, or a 0 + * otherwise. */ +{ + Dict *dict; + ChainEntry *cPtr; + + if (dictPtr->typePtr != &tclDictType + && SetDictFromAny(interp, dictPtr) != TCL_OK) { + return TCL_ERROR; + } + + dict = DICT(dictPtr); + cPtr = dict->entryChainHead; + if (cPtr == NULL) { + searchPtr->epoch = 0; + *donePtr = 1; + } else { + *donePtr = 0; + searchPtr->dictionaryPtr = (Tcl_Dict) dict; + searchPtr->epoch = dict->epoch; + searchPtr->next = cPtr->nextPtr; + dict->refCount++; + if (keyPtrPtr != NULL) { + *keyPtrPtr = Tcl_GetHashKey(&dict->table, &cPtr->entry); + } + if (valuePtrPtr != NULL) { + *valuePtrPtr = Tcl_GetHashValue(&cPtr->entry); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DictObjNext -- + * + * Continue a traversal of a dictionary previously started with + * Tcl_DictObjFirst. This function is safe against concurrent + * modification of the underlying object (including type shimmering), + * treating such situations as if the search has terminated, though it is + * up to the caller to ensure that the object itself is not disposed + * until the search has finished. It is _not_ safe against modifications + * from other threads. + * + * Results: + * Updates the variables pointed to by keyPtrPtr, valuePtrPtr and + * donePtr. Either of keyPtrPtr and valuePtrPtr may be NULL, in which + * case the key/value is not made available to the caller. + * + * Side effects: + * Removes a reference to the dictionary's internal rep if the search + * terminates. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_DictObjNext( + Tcl_DictSearch *searchPtr, /* Pointer to a hash search context. */ + Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the first key + * written into, or NULL. */ + Tcl_Obj **valuePtrPtr, /* Pointer to a variable to have the first + * value written into, or NULL.*/ + int *donePtr) /* Pointer to a variable which will have a 1 + * 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 == 0) { + *donePtr = 1; + return; + } + + /* + * Bail out if the dictionary has had any elements added, modified or + * removed. This *shouldn't* happen, but... + */ + + if (((Dict *)searchPtr->dictionaryPtr)->epoch != searchPtr->epoch) { + Tcl_Panic("concurrent dictionary modification and search"); + } + + cPtr = searchPtr->next; + if (cPtr == NULL) { + Tcl_DictObjDone(searchPtr); + *donePtr = 1; + return; + } + + searchPtr->next = cPtr->nextPtr; + *donePtr = 0; + if (keyPtrPtr != NULL) { + *keyPtrPtr = Tcl_GetHashKey( + &((Dict *)searchPtr->dictionaryPtr)->table, &cPtr->entry); + } + if (valuePtrPtr != NULL) { + *valuePtrPtr = Tcl_GetHashValue(&cPtr->entry); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DictObjDone -- + * + * Call this if you want to stop a search before you reach the end of the + * dictionary (e.g. because of abnormal termination of the search). It + * need not be used if the search reaches its natural end (i.e. if either + * Tcl_DictObjFirst or Tcl_DictObjNext sets its donePtr variable to 1). + * + * Results: + * None. + * + * Side effects: + * Removes a reference to the dictionary's internal rep. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_DictObjDone( + Tcl_DictSearch *searchPtr) /* Pointer to a hash search context. */ +{ + Dict *dict; + + if (searchPtr->epoch != 0) { + searchPtr->epoch = 0; + dict = (Dict *) searchPtr->dictionaryPtr; + if (dict->refCount-- <= 1) { + DeleteDict(dict); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DictObjPutKeyList -- + * + * Add a key...key,value pair to a dictionary tree. The main dictionary + * value must not be shared, though sub-dictionaries may be. All + * intermediate dictionaries on the path must exist. + * + * Results: + * A standard Tcl result. Note that in the error case, a message is left + * in interp unless that is NULL. + * + * Side effects: + * If the dictionary and any of its sub-dictionaries on the path have + * string representations, these are invalidated. + * + *---------------------------------------------------------------------- + */ + +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; + } + + dict = DICT(dictPtr); + hPtr = CreateChainEntry(dict, keyv[keyc-1], &isNew); + Tcl_IncrRefCount(valuePtr); + if (!isNew) { + Tcl_Obj *oldValuePtr = Tcl_GetHashValue(hPtr); + + TclDecrRefCount(oldValuePtr); + } + Tcl_SetHashValue(hPtr, valuePtr); + InvalidateDictChain(dictPtr); + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DictObjRemoveKeyList -- + * + * Remove a key...key,value pair from a dictionary tree (the value + * removed is implicit in the key path). The main dictionary value must + * not be shared, though sub-dictionaries may be. It is not an error if + * there is no value associated with the given key list, but all + * intermediate dictionaries on the key path must exist. + * + * Results: + * A standard Tcl result. Note that in the error case, a message is left + * in interp unless that is NULL. + * + * Side effects: + * If the dictionary and any of its sub-dictionaries on the key path have + * string representations, these are invalidated. + * + *---------------------------------------------------------------------- + */ + +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; + } + + dict = DICT(dictPtr); + DeleteChainEntry(dict, keyv[keyc-1]); + InvalidateDictChain(dictPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_NewDictObj -- + * + * This function is normally called when not debugging: i.e., when + * TCL_MEM_DEBUG is not defined. It creates a new dict object without any + * content. + * + * When TCL_MEM_DEBUG is defined, this function just returns the result + * of calling the debugging version Tcl_DbNewDictObj. + * + * Results: + * A new dict object is returned; it has no keys defined in it. The new + * object's string representation is left NULL, and the ref count of the + * object is 0. + * + * Side Effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_Obj * +Tcl_NewDictObj(void) +{ +#ifdef TCL_MEM_DEBUG + return Tcl_DbNewDictObj("unknown", 0); +#else /* !TCL_MEM_DEBUG */ + + Tcl_Obj *dictPtr; + Dict *dict; + + TclNewObj(dictPtr); + TclInvalidateStringRep(dictPtr); + dict = Tcl_Alloc(sizeof(Dict)); + InitChainTable(dict); + dict->epoch = 1; + dict->chain = NULL; + dict->refCount = 1; + DICT(dictPtr) = dict; + dictPtr->internalRep.twoPtrValue.ptr2 = NULL; + dictPtr->typePtr = &tclDictType; + return dictPtr; +#endif +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DbNewDictObj -- + * + * This function is normally called when debugging: i.e., when + * TCL_MEM_DEBUG is defined. It creates new dict objects. It is the same + * as the Tcl_NewDictObj 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_NewDictObj. + * + * Results: + * A new dict object is returned; it has no keys defined in it. The new + * object's string representation is left NULL, and the ref count of the + * object is 0. + * + * Side Effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_Obj * +Tcl_DbNewDictObj( + const char *file, + int line) +{ +#ifdef TCL_MEM_DEBUG + Tcl_Obj *dictPtr; + Dict *dict; + + TclDbNewObj(dictPtr, file, line); + TclInvalidateStringRep(dictPtr); + dict = Tcl_Alloc(sizeof(Dict)); + InitChainTable(dict); + dict->epoch = 1; + dict->chain = NULL; + dict->refCount = 1; + DICT(dictPtr) = dict; + dictPtr->internalRep.twoPtrValue.ptr2 = NULL; + dictPtr->typePtr = &tclDictType; + return dictPtr; +#else /* !TCL_MEM_DEBUG */ + return Tcl_NewDictObj(); +#endif +} + +/***** START OF FUNCTIONS IMPLEMENTING TCL COMMANDS *****/ + + +/* + *---------------------------------------------------------------------- + * + * DictKeysCmd -- + * + * This function implements the "dict keys" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictKeysCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Tcl_Obj *listPtr; + const char *pattern = NULL; + + if (objc!=2 && objc!=3) { + Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?pattern?"); + return TCL_ERROR; + } + + /* + * A direct check that we have a dictionary. We don't start the iteration + * yet because that might allocate memory or set locks that we do not + * need. [Bug 1705778, leak K04] + */ + + if (objv[1]->typePtr != &tclDictType + && SetDictFromAny(interp, objv[1]) != TCL_OK) { + return TCL_ERROR; + } + + if (objc == 3) { + pattern = TclGetString(objv[2]); + } + listPtr = Tcl_NewListObj(0, NULL); + if ((pattern != NULL) && TclMatchIsTrivial(pattern)) { + Tcl_Obj *valuePtr = NULL; + + Tcl_DictObjGet(interp, objv[1], objv[2], &valuePtr); + if (valuePtr != NULL) { + Tcl_ListObjAppendElement(NULL, listPtr, objv[2]); + } + } else { + Tcl_DictSearch search; + Tcl_Obj *keyPtr = NULL; + int done = 0; + + /* + * At this point, we know we have a dictionary (or at least something + * that can be represented; it could theoretically have shimmered away + * when the pattern was fetched, but that shouldn't be damaging) so we + * can start the iteration process without checking for failures. + */ + + Tcl_DictObjFirst(NULL, objv[1], &search, &keyPtr, NULL, &done); + for (; !done ; Tcl_DictObjNext(&search, &keyPtr, NULL, &done)) { + if (!pattern || Tcl_StringMatch(TclGetString(keyPtr), pattern)) { + Tcl_ListObjAppendElement(NULL, listPtr, keyPtr); + } + } + Tcl_DictObjDone(&search); + } + + Tcl_SetObjResult(interp, listPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * DictValuesCmd -- + * + * This function implements the "dict values" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictValuesCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Tcl_Obj *valuePtr = NULL, *listPtr; + Tcl_DictSearch search; + int done; + const char *pattern; + + if (objc!=2 && objc!=3) { + Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?pattern?"); + return TCL_ERROR; + } + + if (Tcl_DictObjFirst(interp, objv[1], &search, NULL, &valuePtr, + &done) != TCL_OK) { + return TCL_ERROR; + } + if (objc == 3) { + pattern = TclGetString(objv[2]); + } else { + pattern = NULL; + } + listPtr = Tcl_NewListObj(0, NULL); + for (; !done ; Tcl_DictObjNext(&search, NULL, &valuePtr, &done)) { + if (pattern==NULL || Tcl_StringMatch(TclGetString(valuePtr),pattern)) { + /* + * Assume this operation always succeeds. + */ + + Tcl_ListObjAppendElement(interp, listPtr, valuePtr); + } + } + Tcl_DictObjDone(&search); + + Tcl_SetObjResult(interp, listPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * DictExistsCmd -- + * + * This function implements the "dict exists" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictExistsCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Tcl_Obj *dictPtr, *valuePtr; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "dictionary key ?key ...?"); + return TCL_ERROR; + } + + dictPtr = TclTraceDictPath(interp, objv[1], objc-3, objv+2, + DICT_PATH_EXISTS); + if (dictPtr == NULL || dictPtr == DICT_PATH_NON_EXISTENT + || Tcl_DictObjGet(interp, dictPtr, objv[objc-1], + &valuePtr) != TCL_OK) { + Tcl_SetObjResult(interp, Tcl_NewLongObj(0)); + } else { + Tcl_SetObjResult(interp, Tcl_NewLongObj(valuePtr != NULL)); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * DictIncrCmd -- + * + * This function implements the "dict incr" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictIncrCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + int code = TCL_OK; + Tcl_Obj *dictPtr, *valuePtr = NULL; + + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?increment?"); + return TCL_ERROR; + } + + dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); + if (dictPtr == NULL) { + /* + * Variable didn't yet exist. Create new dictionary value. + */ + + dictPtr = Tcl_NewDictObj(); + } else if (Tcl_DictObjGet(interp, dictPtr, objv[2], &valuePtr) != TCL_OK) { + /* + * Variable contents are not a dict, report error. + */ + + return TCL_ERROR; + } + if (Tcl_IsShared(dictPtr)) { + /* + * A little internals surgery to avoid copying a string rep that will + * soon be no good. + */ + + char *saved = dictPtr->bytes; + Tcl_Obj *oldPtr = dictPtr; + + dictPtr->bytes = NULL; + dictPtr = Tcl_DuplicateObj(dictPtr); + oldPtr->bytes = saved; + } + if (valuePtr == NULL) { + /* + * Key not in dictionary. Create new key with increment as value. + */ + + if (objc == 4) { + /* + * Verify increment is an integer. + */ + + mp_int increment; + + code = Tcl_GetBignumFromObj(interp, objv[3], &increment); + if (code != TCL_OK) { + Tcl_AddErrorInfo(interp, "\n (reading increment)"); + } else { + /* + * Remember to dispose with the bignum as we're not actually + * using it directly. [Bug 2874678] + */ + + mp_clear(&increment); + Tcl_DictObjPut(NULL, dictPtr, objv[2], objv[3]); + } + } else { + Tcl_DictObjPut(NULL, dictPtr, objv[2], Tcl_NewIntObj(1)); + } + } else { + /* + * Key in dictionary. Increment its value with minimum dup. + */ + + if (Tcl_IsShared(valuePtr)) { + valuePtr = Tcl_DuplicateObj(valuePtr); + Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr); + } + if (objc == 4) { + code = TclIncrObj(interp, valuePtr, objv[3]); + } else { + Tcl_Obj *incrPtr = Tcl_NewLongObj(1); + + Tcl_IncrRefCount(incrPtr); + code = TclIncrObj(interp, valuePtr, incrPtr); + TclDecrRefCount(incrPtr); + } + } + if (code == TCL_OK) { + TclInvalidateStringRep(dictPtr); + valuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL, + dictPtr, TCL_LEAVE_ERR_MSG); + if (valuePtr == NULL) { + code = TCL_ERROR; + } else { + Tcl_SetObjResult(interp, valuePtr); + } + } else if (dictPtr->refCount == 0) { + TclDecrRefCount(dictPtr); + } + return code; +} + +/* + *---------------------------------------------------------------------- + * + * DictLappendCmd -- + * + * This function implements the "dict lappend" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictLappendCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Tcl_Obj *dictPtr, *valuePtr, *resultPtr; + int i, allocatedDict = 0, allocatedValue = 0; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?value ...?"); + return TCL_ERROR; + } + + dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); + if (dictPtr == NULL) { + allocatedDict = 1; + dictPtr = Tcl_NewDictObj(); + } else if (Tcl_IsShared(dictPtr)) { + allocatedDict = 1; + dictPtr = Tcl_DuplicateObj(dictPtr); + } + + if (Tcl_DictObjGet(interp, dictPtr, objv[2], &valuePtr) != TCL_OK) { + if (allocatedDict) { + TclDecrRefCount(dictPtr); + } + return TCL_ERROR; + } + + if (valuePtr == NULL) { + valuePtr = Tcl_NewListObj(objc-3, objv+3); + allocatedValue = 1; + } else { + if (Tcl_IsShared(valuePtr)) { + allocatedValue = 1; + valuePtr = Tcl_DuplicateObj(valuePtr); + } + + for (i=3 ; ibytes != NULL) { + TclInvalidateStringRep(dictPtr); + } + + resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr, + TCL_LEAVE_ERR_MSG); + if (resultPtr == NULL) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, resultPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * DictAppendCmd -- + * + * This function implements the "dict append" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictAppendCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Tcl_Obj *dictPtr, *valuePtr, *resultPtr; + int allocatedDict = 0; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?value ...?"); + return TCL_ERROR; + } + + dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); + if (dictPtr == NULL) { + allocatedDict = 1; + dictPtr = Tcl_NewDictObj(); + } else if (Tcl_IsShared(dictPtr)) { + allocatedDict = 1; + dictPtr = Tcl_DuplicateObj(dictPtr); + } + + if (Tcl_DictObjGet(interp, dictPtr, objv[2], &valuePtr) != TCL_OK) { + if (allocatedDict) { + TclDecrRefCount(dictPtr); + } + return TCL_ERROR; + } + + if ((objc > 3) || (valuePtr == NULL)) { + /* Only go through append activites when something will change. */ + Tcl_Obj *appendObjPtr = NULL; + + if (objc > 3) { + /* Something to append */ + + if (objc == 4) { + appendObjPtr = objv[3]; + } else if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1, + objc-3, objv+3, &appendObjPtr)) { + return TCL_ERROR; + } + } + + if (appendObjPtr == NULL) { + /* => (objc == 3) => (valuePtr == NULL) */ + TclNewObj(valuePtr); + } else if (valuePtr == NULL) { + valuePtr = appendObjPtr; + appendObjPtr = NULL; + } + + if (appendObjPtr) { + if (Tcl_IsShared(valuePtr)) { + valuePtr = Tcl_DuplicateObj(valuePtr); + } + + Tcl_AppendObjToObj(valuePtr, appendObjPtr); + } + + Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr); + } + + /* + * Even if nothing changed, we still overwrite so that variable + * trace expectations are met. + */ + + resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr, + TCL_LEAVE_ERR_MSG); + if (resultPtr == NULL) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, resultPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * DictForNRCmd -- + * + * These functions implement the "dict for" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictForNRCmd( + ClientData dummy, + 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 = TclStackAlloc(interp, sizeof(Tcl_DictSearch)); + if (Tcl_DictObjFirst(interp, objv[2], searchPtr, &keyObj, &valueObj, + &done) != TCL_OK) { + TclStackFree(interp, searchPtr); + return TCL_ERROR; + } + if (done) { + TclStackFree(interp, searchPtr); + return TCL_OK; + } + TclListObjGetElements(NULL, objv[1], &varc, &varv); + keyVarObj = varv[0]; + valueVarObj = varv[1]; + scriptObj = objv[3]; + + /* + * Make sure that these objects (which we need throughout the body of the + * loop) don't vanish. Note that the dictionary internal rep is locked + * internally so that updates, shimmering, etc are not a problem. + */ + + Tcl_IncrRefCount(keyVarObj); + Tcl_IncrRefCount(valueVarObj); + Tcl_IncrRefCount(scriptObj); + + /* + * Stop the value from getting hit in any way by any traces on the key + * variable. + */ + + Tcl_IncrRefCount(valueObj); + if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj, + TCL_LEAVE_ERR_MSG) == NULL) { + TclDecrRefCount(valueObj); + goto error; + } + TclDecrRefCount(valueObj); + if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj, + TCL_LEAVE_ERR_MSG) == NULL) { + goto error; + } + + /* + * Run the script. + */ + + TclNRAddCallback(interp, DictForLoopCallback, searchPtr, keyVarObj, + valueVarObj, scriptObj); + return TclNREvalObjEx(interp, scriptObj, 0, iPtr->cmdFramePtr, 3); + + /* + * For unwinding everything on error. + */ + + error: + TclDecrRefCount(keyVarObj); + TclDecrRefCount(valueVarObj); + TclDecrRefCount(scriptObj); + 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 = data[0]; + Tcl_Obj *keyVarObj = data[1]; + Tcl_Obj *valueVarObj = data[2]; + Tcl_Obj *scriptObj = data[3]; + Tcl_Obj *keyObj, *valueObj; + int done; + + /* + * Process the result from the previous execution of the script body. + */ + + if (result == TCL_CONTINUE) { + result = TCL_OK; + } else if (result != TCL_OK) { + if (result == TCL_BREAK) { + Tcl_ResetResult(interp); + result = TCL_OK; + } else if (result == TCL_ERROR) { + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (\"dict for\" body line %d)", + Tcl_GetErrorLine(interp))); + } + goto done; + } + + /* + * Get the next mapping from the dictionary. + */ + + Tcl_DictObjNext(searchPtr, &keyObj, &valueObj, &done); + if (done) { + Tcl_ResetResult(interp); + goto done; + } + + /* + * Stop the value from getting hit in any way by any traces on the key + * variable. + */ + + Tcl_IncrRefCount(valueObj); + if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj, + TCL_LEAVE_ERR_MSG) == NULL) { + TclDecrRefCount(valueObj); + result = TCL_ERROR; + goto done; + } + TclDecrRefCount(valueObj); + if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj, + TCL_LEAVE_ERR_MSG) == NULL) { + result = TCL_ERROR; + goto done; + } + + /* + * Run the script. + */ + + TclNRAddCallback(interp, DictForLoopCallback, searchPtr, keyVarObj, + valueVarObj, scriptObj); + return TclNREvalObjEx(interp, scriptObj, 0, iPtr->cmdFramePtr, 3); + + /* + * For unwinding everything once the iterating is done. + */ + + done: + TclDecrRefCount(keyVarObj); + TclDecrRefCount(valueVarObj); + TclDecrRefCount(scriptObj); + Tcl_DictObjDone(searchPtr); + TclStackFree(interp, searchPtr); + return result; +} + +/* + *---------------------------------------------------------------------- + * + * DictMapNRCmd -- + * + * These functions implement the "dict map" Tcl command. See the user + * documentation for details on what it does, and TIP#405 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictMapNRCmd( + ClientData dummy, + 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 = TclStackAlloc(interp, sizeof(DictMapStorage)); + if (Tcl_DictObjFirst(interp, objv[2], &storagePtr->search, &keyObj, + &valueObj, &done) != TCL_OK) { + TclStackFree(interp, storagePtr); + return TCL_ERROR; + } + if (done) { + /* + * Note that this exit leaves an empty value in the result (due to + * command calling conventions) but that is OK since an empty value is + * an empty dictionary. + */ + + TclStackFree(interp, storagePtr); + return TCL_OK; + } + TclNewObj(storagePtr->accumulatorObj); + TclListObjGetElements(NULL, objv[1], &varc, &varv); + storagePtr->keyVarObj = varv[0]; + storagePtr->valueVarObj = varv[1]; + storagePtr->scriptObj = objv[3]; + + /* + * Make sure that these objects (which we need throughout the body of the + * loop) don't vanish. Note that the dictionary internal rep is locked + * internally so that updates, shimmering, etc are not a problem. + */ + + Tcl_IncrRefCount(storagePtr->accumulatorObj); + Tcl_IncrRefCount(storagePtr->keyVarObj); + Tcl_IncrRefCount(storagePtr->valueVarObj); + Tcl_IncrRefCount(storagePtr->scriptObj); + + /* + * Stop the value from getting hit in any way by any traces on the key + * variable. + */ + + Tcl_IncrRefCount(valueObj); + if (Tcl_ObjSetVar2(interp, storagePtr->keyVarObj, NULL, keyObj, + TCL_LEAVE_ERR_MSG) == NULL) { + TclDecrRefCount(valueObj); + goto error; + } + if (Tcl_ObjSetVar2(interp, storagePtr->valueVarObj, NULL, valueObj, + TCL_LEAVE_ERR_MSG) == NULL) { + TclDecrRefCount(valueObj); + goto error; + } + TclDecrRefCount(valueObj); + + /* + * Run the script. + */ + + TclNRAddCallback(interp, DictMapLoopCallback, storagePtr, NULL,NULL,NULL); + return TclNREvalObjEx(interp, storagePtr->scriptObj, 0, + iPtr->cmdFramePtr, 3); + + /* + * For unwinding everything on error. + */ + + error: + TclDecrRefCount(storagePtr->keyVarObj); + TclDecrRefCount(storagePtr->valueVarObj); + TclDecrRefCount(storagePtr->scriptObj); + TclDecrRefCount(storagePtr->accumulatorObj); + 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 = data[0]; + Tcl_Obj *keyObj, *valueObj; + int done; + + /* + * Process the result from the previous execution of the script body. + */ + + if (result == TCL_CONTINUE) { + result = TCL_OK; + } else if (result != TCL_OK) { + if (result == TCL_BREAK) { + Tcl_ResetResult(interp); + result = TCL_OK; + } else if (result == TCL_ERROR) { + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (\"dict map\" body line %d)", + Tcl_GetErrorLine(interp))); + } + goto done; + } else { + keyObj = Tcl_ObjGetVar2(interp, storagePtr->keyVarObj, NULL, + TCL_LEAVE_ERR_MSG); + if (keyObj == NULL) { + result = TCL_ERROR; + goto done; + } + Tcl_DictObjPut(NULL, storagePtr->accumulatorObj, keyObj, + Tcl_GetObjResult(interp)); + } + + /* + * Get the next mapping from the dictionary. + */ + + Tcl_DictObjNext(&storagePtr->search, &keyObj, &valueObj, &done); + if (done) { + Tcl_SetObjResult(interp, storagePtr->accumulatorObj); + goto done; + } + + /* + * Stop the value from getting hit in any way by any traces on the key + * variable. + */ + + Tcl_IncrRefCount(valueObj); + if (Tcl_ObjSetVar2(interp, storagePtr->keyVarObj, NULL, keyObj, + TCL_LEAVE_ERR_MSG) == NULL) { + TclDecrRefCount(valueObj); + result = TCL_ERROR; + goto done; + } + if (Tcl_ObjSetVar2(interp, storagePtr->valueVarObj, NULL, valueObj, + TCL_LEAVE_ERR_MSG) == NULL) { + TclDecrRefCount(valueObj); + result = TCL_ERROR; + goto done; + } + TclDecrRefCount(valueObj); + + /* + * Run the script. + */ + + TclNRAddCallback(interp, DictMapLoopCallback, storagePtr, NULL,NULL,NULL); + return TclNREvalObjEx(interp, storagePtr->scriptObj, 0, + iPtr->cmdFramePtr, 3); + + /* + * For unwinding everything once the iterating is done. + */ + + done: + TclDecrRefCount(storagePtr->keyVarObj); + TclDecrRefCount(storagePtr->valueVarObj); + TclDecrRefCount(storagePtr->scriptObj); + TclDecrRefCount(storagePtr->accumulatorObj); + Tcl_DictObjDone(&storagePtr->search); + TclStackFree(interp, storagePtr); + return result; +} + +/* + *---------------------------------------------------------------------- + * + * DictSetCmd -- + * + * This function implements the "dict set" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictSetCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Tcl_Obj *dictPtr, *resultPtr; + int result, allocatedDict = 0; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?key ...? value"); + return TCL_ERROR; + } + + dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); + if (dictPtr == NULL) { + allocatedDict = 1; + dictPtr = Tcl_NewDictObj(); + } else if (Tcl_IsShared(dictPtr)) { + allocatedDict = 1; + dictPtr = Tcl_DuplicateObj(dictPtr); + } + + result = Tcl_DictObjPutKeyList(interp, dictPtr, objc-3, objv+2, + objv[objc-1]); + if (result != TCL_OK) { + if (allocatedDict) { + TclDecrRefCount(dictPtr); + } + return TCL_ERROR; + } + + resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr, + TCL_LEAVE_ERR_MSG); + if (resultPtr == NULL) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, resultPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * DictUnsetCmd -- + * + * This function implements the "dict unset" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictUnsetCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Tcl_Obj *dictPtr, *resultPtr; + int result, allocatedDict = 0; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?key ...?"); + return TCL_ERROR; + } + + dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); + if (dictPtr == NULL) { + allocatedDict = 1; + dictPtr = Tcl_NewDictObj(); + } else if (Tcl_IsShared(dictPtr)) { + allocatedDict = 1; + dictPtr = Tcl_DuplicateObj(dictPtr); + } + + result = Tcl_DictObjRemoveKeyList(interp, dictPtr, objc-2, objv+2); + if (result != TCL_OK) { + if (allocatedDict) { + TclDecrRefCount(dictPtr); + } + return TCL_ERROR; + } + + resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr, + TCL_LEAVE_ERR_MSG); + if (resultPtr == NULL) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, resultPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * DictFilterCmd -- + * + * This function implements the "dict filter" Tcl command. See the user + * documentation for details on what it does, and TIP#111 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictFilterCmd( + ClientData dummy, + 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_GetIndexFromObjStruct(interp, objv[2], filters, + sizeof(char *), "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) { + return TCL_ERROR; + } + if (objc == 3) { + /* + * Nothing to match, so return nothing (== empty dictionary). + */ + + Tcl_DictObjDone(&search); + return TCL_OK; + } else if (objc == 4) { + pattern = TclGetString(objv[3]); + resultObj = Tcl_NewDictObj(); + if (TclMatchIsTrivial(pattern)) { + /* + * Must release the search lock here to prevent a memory leak + * since we are not exhausing the search. [Bug 1705778, leak + * K05] + */ + + Tcl_DictObjDone(&search); + Tcl_DictObjGet(interp, objv[1], objv[3], &valueObj); + if (valueObj != NULL) { + Tcl_DictObjPut(NULL, resultObj, objv[3], valueObj); + } + } else { + while (!done) { + if (Tcl_StringMatch(TclGetString(keyObj), pattern)) { + Tcl_DictObjPut(NULL, resultObj, keyObj, valueObj); + } + Tcl_DictObjNext(&search, &keyObj, &valueObj, &done); + } + } + } else { + /* + * Can't optimize this match for trivial globbing: would disturb + * order. + */ + + resultObj = Tcl_NewDictObj(); + while (!done) { + int i; + + for (i=3 ; icmdFramePtr, 4); + switch (result) { + case TCL_OK: + boolObj = Tcl_GetObjResult(interp); + Tcl_IncrRefCount(boolObj); + Tcl_ResetResult(interp); + if (Tcl_GetBooleanFromObj(interp, boolObj, + &satisfied) != TCL_OK) { + TclDecrRefCount(boolObj); + result = TCL_ERROR; + goto abnormalResult; + } + TclDecrRefCount(boolObj); + if (satisfied) { + Tcl_DictObjPut(NULL, resultObj, keyObj, valueObj); + } + break; + case TCL_BREAK: + /* + * Force loop termination by calling Tcl_DictObjDone; this + * makes the next Tcl_DictObjNext say there is nothing more to + * do. + */ + + Tcl_ResetResult(interp); + Tcl_DictObjDone(&search); + case TCL_CONTINUE: + result = TCL_OK; + break; + case TCL_ERROR: + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (\"dict filter\" script line %d)", + Tcl_GetErrorLine(interp))); + default: + goto abnormalResult; + } + + TclDecrRefCount(keyObj); + TclDecrRefCount(valueObj); + + Tcl_DictObjNext(&search, &keyObj, &valueObj, &done); + } + + /* + * Stop holding a reference to these objects. + */ + + TclDecrRefCount(keyVarObj); + TclDecrRefCount(valueVarObj); + TclDecrRefCount(scriptObj); + Tcl_DictObjDone(&search); + + if (result == TCL_OK) { + Tcl_SetObjResult(interp, resultObj); + } else { + TclDecrRefCount(resultObj); + } + return result; + + abnormalResult: + Tcl_DictObjDone(&search); + TclDecrRefCount(keyObj); + TclDecrRefCount(valueObj); + TclDecrRefCount(keyVarObj); + TclDecrRefCount(valueVarObj); + TclDecrRefCount(scriptObj); + TclDecrRefCount(resultObj); + return result; + } + Tcl_Panic("unexpected fallthrough"); + /* Control never reaches this point. */ + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * DictUpdateCmd -- + * + * This function implements the "dict update" Tcl command. See the user + * documentation for details on what it does, and TIP#212 for the formal + * specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictUpdateCmd( + ClientData 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; + } + + dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG); + if (dictPtr == NULL) { + return TCL_ERROR; + } + if (Tcl_DictObjSize(interp, dictPtr, &dummy) != TCL_OK) { + return TCL_ERROR; + } + Tcl_IncrRefCount(dictPtr); + for (i=2 ; i+2cmdFramePtr, 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 = data[0]; + Tcl_Obj *argsObj = data[1]; + + /* + * ErrorInfo handling. + */ + + if (result == TCL_ERROR) { + Tcl_AddErrorInfo(interp, "\n (body of \"dict update\")"); + } + + /* + * If the dictionary variable doesn't exist, drop everything silently. + */ + + dictPtr = Tcl_ObjGetVar2(interp, varName, NULL, 0); + if (dictPtr == NULL) { + TclDecrRefCount(varName); + TclDecrRefCount(argsObj); + return result; + } + + /* + * Double-check that it is still a dictionary. + */ + + state = Tcl_SaveInterpState(interp, result); + if (Tcl_DictObjSize(interp, dictPtr, &objc) != TCL_OK) { + Tcl_DiscardInterpState(state); + TclDecrRefCount(varName); + TclDecrRefCount(argsObj); + return TCL_ERROR; + } + + if (Tcl_IsShared(dictPtr)) { + dictPtr = Tcl_DuplicateObj(dictPtr); + } + + /* + * 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 3) { + pathPtr = Tcl_NewListObj(objc-3, objv+2); + Tcl_IncrRefCount(pathPtr); + } + Tcl_IncrRefCount(objv[1]); + TclNRAddCallback(interp, FinalizeDictWith, objv[1], keysPtr, pathPtr, + 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 = data[0]; + Tcl_Obj *keysPtr = data[1]; + Tcl_Obj *pathPtr = 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. + */ + + varPtr = TclObjLookupVarEx(interp, varName, NULL, TCL_LEAVE_ERR_MSG, "set", + /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); + if (varPtr == NULL) { + result = TCL_ERROR; + } else { + result = TclDictWithFinish(interp, varPtr, arrayPtr, varName, NULL, -1, + pathc, pathv, keysPtr); + } + + /* + * Tidy up and return the real result (unless we had an error). + */ + + TclDecrRefCount(varName); + TclDecrRefCount(keysPtr); + if (pathPtr != NULL) { + TclDecrRefCount(pathPtr); + } + if (result != TCL_OK) { + Tcl_DiscardInterpState(state); + return TCL_ERROR; + } + return Tcl_RestoreInterpState(interp, state); +} + +/* + *---------------------------------------------------------------------- + * + * TclDictWithInit -- + * + * Part of the core of [dict with]. Pokes into a dictionary and converts + * the mappings there into assignments to (presumably) local variables. + * Returns a list of all the names that were mapped so that removal of + * either the variable or the dictionary entry won't surprise us when we + * come to stuffing everything back. + * + * Result: + * List of mapped names, or NULL if there was an error. + * + * Side effects: + * Assigns to variables, so potentially legion due to traces. + * + *---------------------------------------------------------------------- + */ + +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) { + dictPtr = TclTraceDictPath(interp, dictPtr, pathc, pathv, + DICT_PATH_READ); + if (dictPtr == NULL) { + return NULL; + } + } + + /* + * Go over the list of keys and write each corresponding value to a + * variable in the current context with the same name. Also keep a copy of + * the keys so we can write back properly later on even if the dictionary + * has been structurally modified. + */ + + if (Tcl_DictObjFirst(interp, dictPtr, &s, &keyPtr, &valPtr, + &done) != TCL_OK) { + return NULL; + } + + TclNewObj(keysPtr); + + for (; !done ; Tcl_DictObjNext(&s, &keyPtr, &valPtr, &done)) { + Tcl_ListObjAppendElement(NULL, keysPtr, keyPtr); + if (Tcl_ObjSetVar2(interp, keyPtr, NULL, valPtr, + TCL_LEAVE_ERR_MSG) == NULL) { + TclDecrRefCount(keysPtr); + Tcl_DictObjDone(&s); + return NULL; + } + } + + return keysPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TclDictWithFinish -- + * + * Part of the core of [dict with]. Reassembles the piece of the dict (in + * varName, location given by pathc/pathv) from the variables named in + * the keysPtr argument. NB, does not try to preserve errors or manage + * argument lifetimes. + * + * Result: + * TCL_OK if we succeeded, or TCL_ERROR if we failed. + * + * Side effects: + * Assigns to a variable, so potentially legion due to traces. Updates + * the dictionary in the named variable. + * + *---------------------------------------------------------------------- + */ + +int +TclDictWithFinish( + Tcl_Interp *interp, /* Command interpreter in which variable + * exists. Used for state management, traces + * and error reporting. */ + Var *varPtr, /* Reference to the variable holding the + * dictionary. */ + Var *arrayPtr, /* Reference to the array containing the + * variable, or NULL if the variable is a + * scalar. */ + Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or + * the name of a variable. NULL if the 'index' + * parameter is >= 0 */ + Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element + * in the array part1. */ + int index, /* Index into the local variable table of the + * variable, or -1. Only used when part1Ptr is + * NULL. */ + 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, + TCL_LEAVE_ERR_MSG, index); + if (dictPtr == NULL) { + return TCL_OK; + } + + /* + * Double-check that it is still a dictionary. + */ + + if (Tcl_DictObjSize(interp, dictPtr, &i) != TCL_OK) { + return TCL_ERROR; + } + + if (Tcl_IsShared(dictPtr)) { + dictPtr = Tcl_DuplicateObj(dictPtr); + allocdict = 1; + } 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) { + if (allocdict) { + TclDecrRefCount(dictPtr); + } + return TCL_ERROR; + } + if (leafPtr == DICT_PATH_NON_EXISTENT) { + if (allocdict) { + TclDecrRefCount(dictPtr); + } + return TCL_OK; + } + } else { + leafPtr = dictPtr; + } + + /* + * Now process our updates on the leaf dictionary. + */ + + TclListObjGetElements(NULL, keysPtr, &keyc, &keyv); + for (i=0 ; i 0) { + InvalidateDictChain(leafPtr); + } + + /* + * Write back the outermost dictionary to the variable. + */ + + if (TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, + dictPtr, TCL_LEAVE_ERR_MSG, index) == NULL) { + if (allocdict) { + TclDecrRefCount(dictPtr); + } + return TCL_ERROR; + } + return TCL_OK; +} +#endif + +/* + *---------------------------------------------------------------------- + * + * TclInitHamtCmd -- + * + * This function creates the "hamt" Tcl command. + * + * Results: + * A Tcl command handle. + * + * Side effects: + * May advance compilation epoch. + * + *---------------------------------------------------------------------- + */ + +Tcl_Command +TclInitHamtCmd( + Tcl_Interp *interp) +{ + return TclMakeEnsemble(interp, "hamt", implementationMap); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ Index: generic/tclHash.c ================================================================== --- generic/tclHash.c +++ generic/tclHash.c @@ -2,12 +2,12 @@ * tclHash.c -- * * Implementation of in-memory hash tables for Tcl and Tcl-based * applications. * - * Copyright (c) 1991-1993 The Regents of the University of California. - * Copyright (c) 1994 Sun Microsystems, Inc. + * Copyright © 1991-1993 The Regents of the University of California. + * Copyright © 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -34,20 +34,20 @@ * Prototypes for the array hash key methods. */ static Tcl_HashEntry * AllocArrayEntry(Tcl_HashTable *tablePtr, void *keyPtr); static int CompareArrayKeys(void *keyPtr, Tcl_HashEntry *hPtr); -static TCL_HASH_TYPE HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr); +static size_t HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr); /* * Prototypes for the string hash key methods. */ static Tcl_HashEntry * AllocStringEntry(Tcl_HashTable *tablePtr, void *keyPtr); static int CompareStringKeys(void *keyPtr, Tcl_HashEntry *hPtr); -static TCL_HASH_TYPE HashStringKey(Tcl_HashTable *tablePtr, void *keyPtr); +static size_t HashStringKey(Tcl_HashTable *tablePtr, void *keyPtr); /* * Function prototypes for static functions in this file: */ @@ -266,11 +266,11 @@ index = RANDOM_INDEX(tablePtr, hash); } else { index = hash & tablePtr->mask; } } else { - hash = (size_t) key; + hash = PTR2UINT(key); index = RANDOM_INDEX(tablePtr, hash); } /* * Search all of the entries in the appropriate bucket. @@ -436,11 +436,11 @@ Tcl_DeleteHashTable( Tcl_HashTable *tablePtr) /* Table to delete. */ { Tcl_HashEntry *hPtr, *nextPtr; const Tcl_HashKeyType *typePtr; - size_t i; + Tcl_Size i; if (tablePtr->keyType == TCL_STRING_KEYS) { typePtr = &tclStringHashKeyType; } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) { typePtr = &tclOneWordHashKeyType; @@ -585,11 +585,12 @@ char * Tcl_HashStats( Tcl_HashTable *tablePtr) /* Table for which to produce stats. */ { #define NUM_COUNTERS 10 - size_t count[NUM_COUNTERS], overflow, i, j; + Tcl_Size i; + size_t count[NUM_COUNTERS], overflow, j; double average, tmp; Tcl_HashEntry *hPtr; char *result, *p; /* @@ -620,22 +621,22 @@ /* * Print out the histogram and a few other pieces of information. */ result = (char *)Tcl_Alloc((NUM_COUNTERS * 60) + 300); - sprintf(result, "%" TCL_Z_MODIFIER "u entries in table, %" TCL_Z_MODIFIER "u buckets\n", + snprintf(result, 60, "%" TCL_Z_MODIFIER "u entries in table, %" TCL_Z_MODIFIER "u buckets\n", tablePtr->numEntries, tablePtr->numBuckets); p = result + strlen(result); for (i = 0; i < NUM_COUNTERS; i++) { - sprintf(p, "number of buckets with %" TCL_Z_MODIFIER "u entries: %" TCL_Z_MODIFIER "u\n", + snprintf(p, 60, "number of buckets with %" TCL_Z_MODIFIER "u entries: %" TCL_Z_MODIFIER "u\n", i, count[i]); p += strlen(p); } - sprintf(p, "number of buckets with %d or more entries: %" TCL_Z_MODIFIER "u\n", + snprintf(p, 60, "number of buckets with %d or more entries: %" TCL_Z_MODIFIER "u\n", NUM_COUNTERS, overflow); p += strlen(p); - sprintf(p, "average search distance for entry: %.1f", average); + snprintf(p, 60, "average search distance for entry: %.1f", average); return result; } /* *---------------------------------------------------------------------- @@ -656,28 +657,20 @@ 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; + size_t count = tablePtr->keyType * sizeof(int); + size_t size = offsetof(Tcl_HashEntry, key) + count; - count = tablePtr->keyType; - - size = sizeof(Tcl_HashEntry) + (count*sizeof(int)) - sizeof(hPtr->key); if (size < sizeof(Tcl_HashEntry)) { size = sizeof(Tcl_HashEntry); } hPtr = (Tcl_HashEntry *)Tcl_Alloc(size); - for (iPtr1 = array, iPtr2 = hPtr->key.words; - count > 0; count--, iPtr1++, iPtr2++) { - *iPtr2 = *iPtr1; - } + memcpy(hPtr->key.string, keyPtr, count); Tcl_SetHashValue(hPtr, NULL); return hPtr; } @@ -701,24 +694,13 @@ 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; + size_t count = hPtr->tablePtr->keyType * sizeof(int); + + return !memcmp(keyPtr, hPtr->key.string, count); } /* *---------------------------------------------------------------------- * @@ -735,17 +717,17 @@ * None. * *---------------------------------------------------------------------- */ -static TCL_HASH_TYPE +static size_t 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; + size_t result; int count; for (result = 0, count = tablePtr->keyType; count > 0; count--, array++) { result += *array; @@ -781,11 +763,11 @@ allocsize = size = strlen(string) + 1; if (size < sizeof(hPtr->key)) { allocsize = sizeof(hPtr->key); } hPtr = (Tcl_HashEntry *)Tcl_Alloc(offsetof(Tcl_HashEntry, key) + allocsize); - memset(hPtr, 0, sizeof(Tcl_HashEntry) + allocsize - sizeof(hPtr->key)); + memset(hPtr, 0, offsetof(Tcl_HashEntry, key) + allocsize); memcpy(hPtr->key.string, string, size); Tcl_SetHashValue(hPtr, NULL); return hPtr; } @@ -829,17 +811,17 @@ * None. * *---------------------------------------------------------------------- */ -static TCL_HASH_TYPE +static size_t HashStringKey( TCL_UNUSED(Tcl_HashTable *), void *keyPtr) /* Key from which to compute hash value. */ { const char *string = (const char *)keyPtr; - TCL_HASH_TYPE result; + size_t result; char c; /* * I tried a zillion different hash functions and asked many other people * for advice. Many people had their own favorite functions, all Index: generic/tclHistory.c ================================================================== --- generic/tclHistory.c +++ generic/tclHistory.c @@ -4,12 +4,12 @@ * This module and the Tcl library file history.tcl together implement * Tcl command history. Tcl_RecordAndEval(Obj) can be called to record * commands ("events") before they are executed. Commands defined in * history.tcl may be used to perform history substitutions. * - * Copyright (c) 1990-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1993 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -201,11 +201,11 @@ *---------------------------------------------------------------------- */ static void DeleteHistoryObjs( - ClientData clientData, + void *clientData, TCL_UNUSED(Tcl_Interp *)) { HistoryObjs *histObjsPtr = (HistoryObjs *)clientData; TclDecrRefCount(histObjsPtr->historyObj); Index: generic/tclIO.c ================================================================== --- generic/tclIO.c +++ generic/tclIO.c @@ -2,12 +2,12 @@ * tclIO.c -- * * This file provides the generic portions (those that are the same on * all platforms and for all channel types) of Tcl's IO facilities. * - * Copyright (c) 1998-2000 Ajuba Solutions - * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Ajuba Solutions + * Copyright © 1995-1997 Sun Microsystems, Inc. * Contributions from Don Porter, NIST, 2014. (not subject to US copyright) * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -26,11 +26,11 @@ typedef struct ChannelHandler { Channel *chanPtr; /* The channel structure for this channel. */ int mask; /* Mask of desired events. */ Tcl_ChannelProc *proc; /* Procedure to call in the type of * Tcl_CreateChannelHandler. */ - ClientData clientData; /* Argument to pass to procedure. */ + void *clientData; /* Argument to pass to procedure. */ struct ChannelHandler *nextPtr; /* Next one in list of registered handlers. */ } ChannelHandler; /* @@ -100,12 +100,12 @@ 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 + 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 @@ -123,16 +123,16 @@ ChannelState *firstCSPtr; /* List of all channels currently open, * indexed by ChannelState, as only one * ChannelState exists per set of stacked * channels. */ Tcl_Channel stdinChannel; /* Static variable for the stdin channel. */ - int stdinInitialized; Tcl_Channel stdoutChannel; /* Static variable for the stdout channel. */ - int stdoutInitialized; Tcl_Channel stderrChannel; /* Static variable for the stderr channel. */ - int stderrInitialized; Tcl_Encoding binaryEncoding; + int stdinInitialized; + int stdoutInitialized; + int stderrInitialized; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* @@ -140,70 +140,74 @@ * 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 + void *clientData; /* Arbitrary one-word data to pass * to the callback. */ struct CloseCallback *nextPtr; /* For chaining close callbacks. */ } CloseCallback; /* * Static functions in this file: */ -static ChannelBuffer * AllocChannelBuffer(int length); +static ChannelBuffer * AllocChannelBuffer(Tcl_Size length); static void PreserveChannelBuffer(ChannelBuffer *bufPtr); static void ReleaseChannelBuffer(ChannelBuffer *bufPtr); static int IsShared(ChannelBuffer *bufPtr); static void ChannelFree(Channel *chanPtr); -static void ChannelTimerProc(ClientData clientData); +static void ChannelTimerProc(void *clientData); static int ChanRead(Channel *chanPtr, char *dst, int dstSize); static int CheckChannelErrors(ChannelState *statePtr, int direction); static int CheckForDeadChannel(Tcl_Interp *interp, ChannelState *statePtr); static void CheckForStdChannelsBeingClosed(Tcl_Channel chan); static void CleanupChannelHandlers(Tcl_Interp *interp, Channel *chanPtr); +static 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); +int Lossless(ChannelState *inStatePtr, + ChannelState *outStatePtr, long long toRead); static int MoveBytes(CopyState *csPtr); static void MBCallback(CopyState *csPtr, Tcl_Obj *errObj); static void MBError(CopyState *csPtr, int mask, int errorCode); static int MBRead(CopyState *csPtr); static int MBWrite(CopyState *csPtr); -static void MBEvent(ClientData clientData, int mask); +static void MBEvent(void *clientData, int mask); -static void CopyEventProc(ClientData clientData, int mask); +static void CopyEventProc(void *clientData, int mask); static void CreateScriptRecord(Tcl_Interp *interp, Channel *chanPtr, int mask, Tcl_Obj *scriptPtr); -static void DeleteChannelTable(ClientData clientData, +static void DeleteChannelTable(void *clientData, Tcl_Interp *interp); static void DeleteScriptRecord(Tcl_Interp *interp, Channel *chanPtr, int mask); static int DetachChannel(Tcl_Interp *interp, Tcl_Channel chan); static void DiscardInputQueued(ChannelState *statePtr, int discardSavedBuffers); static void DiscardOutputQueued(ChannelState *chanPtr); -static int DoRead(Channel *chanPtr, char *dst, size_t bytesToRead, +static Tcl_Size DoRead(Channel *chanPtr, char *dst, Tcl_Size bytesToRead, int allowShortReads); -static int DoReadChars(Channel *chan, Tcl_Obj *objPtr, size_t toRead, - int appendFlag); +static Tcl_Size DoReadChars(Channel *chan, Tcl_Obj *objPtr, Tcl_Size toRead, + int allowShortReads, int appendFlag); static int FilterInputBytes(Channel *chanPtr, GetsState *statePtr); static int FlushChannel(Tcl_Interp *interp, Channel *chanPtr, int calledFromAsyncFlush); static int TclGetsObjBinary(Tcl_Channel chan, Tcl_Obj *objPtr); static Tcl_Encoding GetBinaryEncoding(void); -static Tcl_ExitProc FreeBinaryEncoding; +static void FreeBinaryEncoding(void); static Tcl_HashTable * GetChannelTable(Tcl_Interp *interp); static int GetInput(Channel *chanPtr); static void PeekAhead(Channel *chanPtr, char **dstEndPtr, GetsState *gsPtr); static int ReadBytes(ChannelState *statePtr, Tcl_Obj *objPtr, @@ -217,12 +221,12 @@ 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_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); @@ -235,11 +239,11 @@ * Simplifying helper macros. All may use their argument(s) multiple times. * The ANSI C "prototypes" for the macros are listed below, together with a * short description of what the macro does. * * -------------------------------------------------------------------------- - * size_t BytesLeft(ChannelBuffer *bufPtr) + * Tcl_Size BytesLeft(ChannelBuffer *bufPtr) * * Returns the number of bytes of data remaining in the buffer. * * int SpaceLeft(ChannelBuffer *bufPtr) * @@ -273,13 +277,13 @@ * Returns a pointer to where characters should be removed from the * buffer. * -------------------------------------------------------------------------- */ -#define BytesLeft(bufPtr) ((size_t)((bufPtr)->nextAdded - (bufPtr)->nextRemoved)) +#define BytesLeft(bufPtr) ((bufPtr)->nextAdded - (bufPtr)->nextRemoved) -#define SpaceLeft(bufPtr) ((size_t)((bufPtr)->bufLength - (bufPtr)->nextAdded)) +#define SpaceLeft(bufPtr) ((bufPtr)->bufLength - (bufPtr)->nextAdded) #define IsBufferReady(bufPtr) ((bufPtr)->nextAdded > (bufPtr)->nextRemoved) #define IsBufferEmpty(bufPtr) ((bufPtr)->nextAdded == (bufPtr)->nextRemoved) @@ -322,34 +326,38 @@ 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 void DupChannelInternalRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); +static void FreeChannelInternalRep(Tcl_Obj *objPtr); static const Tcl_ObjType chanObjType = { "channel", /* name for this type */ - FreeChannelIntRep, /* freeIntRepProc */ - DupChannelIntRep, /* dupIntRepProc */ + FreeChannelInternalRep, /* freeIntRepProc */ + DupChannelInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - NULL /* setFromAnyProc */ + NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; -#define ChanSetIntRep(objPtr, resPtr) \ +#define GetIso88591() \ + (binaryEncoding ? Tcl_GetEncoding(NULL, "iso8859-1") : binaryEncoding) + +#define ChanSetInternalRep(objPtr, resPtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ (resPtr)->refCount++; \ ir.twoPtrValue.ptr1 = (resPtr); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreIntRep((objPtr), &chanObjType, &ir); \ + Tcl_StoreInternalRep((objPtr), &chanObjType, &ir); \ } while (0) -#define ChanGetIntRep(objPtr, resPtr) \ +#define ChanGetInternalRep(objPtr, resPtr) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), &chanObjType); \ + const Tcl_ObjInternalRep *irPtr; \ + irPtr = TclFetchInternalRep((objPtr), &chanObjType); \ (resPtr) = irPtr ? (ResolvedChanName *)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) #define BUSY_STATE(st, fl) \ ((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \ @@ -390,13 +398,13 @@ * - number of bytes stored at dst, ot * - -1 on error, with a Posix error code available to the caller by * calling Tcl_GetErrno(). * * Side effects: - * The CHANNEL_BLOCKED and CHANNEL_EOF flags of the channel state are set - * as appropriate. On EOF, the inputEncodingFlags are set to perform - * ending operations on decoding. + * The CHANNEL_ENCODING_ERROR, CHANNEL_BLOCKED and CHANNEL_EOF flags + * of the channel state are set as appropriate. On EOF, the + * inputEncodingFlags are set to perform ending operations on decoding. * * TODO - Is this really the right place for that? * *--------------------------------------------------------------------------- */ @@ -477,11 +485,11 @@ * type and non-NULL. */ if (Tcl_ChannelWideSeekProc(chanPtr->typePtr) == NULL) { *errnoPtr = EINVAL; - return -1; + return TCL_INDEX_NONE; } return Tcl_ChannelWideSeekProc(chanPtr->typePtr)(chanPtr->instanceData, offset, mode, errnoPtr); } @@ -649,11 +657,11 @@ */ statePtr->refCount--; } - if (statePtr->refCount + 1 <= 1) { + if (statePtr->refCount <= 0) { /* * Close it only if the refcount indicates that the channel is * not referenced from any interpreter. If it is, that * interpreter will close the channel when it gets destroyed. */ @@ -685,10 +693,11 @@ } TclChannelRelease((Tcl_Channel)chanPtr); } } + FreeBinaryEncoding(); TclpFinalizeSockets(); TclpFinalizePipes(); } /* @@ -830,11 +839,11 @@ Tcl_CreateCloseHandler( Tcl_Channel chan, /* The channel for which to create the close * callback. */ Tcl_CloseProc *proc, /* The callback routine to call when the * channel will be closed. */ - ClientData clientData) /* Arbitrary data to pass to the close + void *clientData) /* Arbitrary data to pass to the close * callback. */ { ChannelState *statePtr = ((Channel *) chan)->state; CloseCallback *cbPtr; @@ -868,11 +877,11 @@ Tcl_DeleteCloseHandler( Tcl_Channel chan, /* The channel for which to cancel the close * callback. */ Tcl_CloseProc *proc, /* The procedure for the callback to * remove. */ - ClientData clientData) /* The callback data for the callback to + void *clientData) /* The callback data for the callback to * remove. */ { ChannelState *statePtr = ((Channel *) chan)->state; CloseCallback *cbPtr, *cbPrevPtr; @@ -959,19 +968,19 @@ * Results: * None. * * Side effects: * Deletes the hash table of channels. May close channels. May flush - * output on closed channels. Removes any channeEvent handlers that were + * output on closed channels. Removes any channelEvent handlers that were * registered in this interpreter. * *---------------------------------------------------------------------- */ static void DeleteChannelTable( - ClientData clientData, /* The per-interpreter data structure. */ + void *clientData, /* The per-interpreter data structure. */ Tcl_Interp *interp) /* The interpreter being deleted. */ { Tcl_HashTable *hTblPtr; /* The hash table. */ Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ @@ -992,11 +1001,11 @@ hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch)) { chanPtr = (Channel *)Tcl_GetHashValue(hPtr); statePtr = chanPtr->state; /* - * Remove any fileevents registered in this interpreter. + * Remove any file events registered in this interpreter. */ for (sPtr = statePtr->scriptRecordPtr, prevPtr = NULL; sPtr != NULL; sPtr = nextPtr) { nextPtr = sPtr->nextPtr; @@ -1067,27 +1076,27 @@ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->stdinInitialized == 1 && tsdPtr->stdinChannel != NULL && statePtr == ((Channel *)tsdPtr->stdinChannel)->state) { - if (statePtr->refCount + 1 < 3) { + if (statePtr->refCount < 2) { statePtr->refCount = 0; tsdPtr->stdinChannel = NULL; return; } } else if (tsdPtr->stdoutInitialized == 1 && tsdPtr->stdoutChannel != NULL && statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) { - if (statePtr->refCount + 1 < 3) { + if (statePtr->refCount < 2) { statePtr->refCount = 0; tsdPtr->stdoutChannel = NULL; return; } } else if (tsdPtr->stderrInitialized == 1 && tsdPtr->stderrChannel != NULL && statePtr == ((Channel *)tsdPtr->stderrChannel)->state) { - if (statePtr->refCount + 1 < 3) { + if (statePtr->refCount < 2) { statePtr->refCount = 0; tsdPtr->stderrChannel = NULL; return; } } @@ -1245,11 +1254,11 @@ /* * If the refCount reached zero, close the actual channel. */ - if (statePtr->refCount + 1 <= 1) { + if (statePtr->refCount <= 0) { Tcl_Preserve(statePtr); if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { /* * We don't want to re-enter Tcl_CloseEx(). */ @@ -1411,11 +1420,11 @@ Tcl_GetChannel( Tcl_Interp *interp, /* Interpreter in which to find or create the * channel. */ const char *chanName, /* The name of the channel. */ int *modePtr) /* Where to store the mode in which the - * channel was opened? Will contain an ORed + * channel was opened? Will contain an OR'ed * combination of TCL_READABLE and * TCL_WRITABLE, if non-NULL. */ { Channel *chanPtr; /* The actual channel. */ Tcl_HashTable *hTblPtr; /* Hash table of channels. */ @@ -1448,11 +1457,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanName, (void *)NULL); return NULL; } /* * Always return bottom-most channel in the stack. This one lives the @@ -1461,11 +1470,11 @@ */ chanPtr = (Channel *)Tcl_GetHashValue(hPtr); chanPtr = chanPtr->state->bottomChanPtr; if (modePtr != NULL) { - *modePtr = chanPtr->state->flags & (TCL_READABLE|TCL_WRITABLE); + *modePtr = GotFlag(chanPtr->state, TCL_READABLE|TCL_WRITABLE); } return (Tcl_Channel) chanPtr; } @@ -1494,11 +1503,11 @@ Tcl_Interp *interp, /* Interpreter in which to find or create the * channel. */ Tcl_Obj *objPtr, Tcl_Channel *channelPtr, int *modePtr, /* Where to store the mode in which the - * channel was opened? Will contain an ORed + * channel was opened? Will contain an OR'ed * combination of TCL_READABLE and * TCL_WRITABLE, if non-NULL. */ TCL_UNUSED(int) /*flags*/) { ChannelState *statePtr; @@ -1507,11 +1516,11 @@ if (interp == NULL) { return TCL_ERROR; } - ChanGetIntRep(objPtr, resPtr); + ChanGetInternalRep(objPtr, resPtr); if (resPtr) { /* * Confirm validity of saved lookup results. */ @@ -1529,11 +1538,11 @@ chan = Tcl_GetChannel(interp, TclGetString(objPtr), NULL); if (chan == NULL) { if (resPtr) { - Tcl_StoreIntRep(objPtr, &chanObjType, NULL); + Tcl_StoreInternalRep(objPtr, &chanObjType, NULL); } return TCL_ERROR; } if (resPtr && resPtr->refCount == 1) { @@ -1543,11 +1552,11 @@ Tcl_Release(resPtr->statePtr); } else { resPtr = (ResolvedChanName *) Tcl_Alloc(sizeof(ResolvedChanName)); resPtr->refCount = 0; - ChanSetIntRep(objPtr, resPtr); /* Overwrites, if needed */ + ChanSetInternalRep(objPtr, resPtr); /* Overwrites, if needed */ } statePtr = ((Channel *)chan)->state; resPtr->statePtr = statePtr; Tcl_Preserve(statePtr); resPtr->interp = interp; @@ -1555,11 +1564,11 @@ valid: *channelPtr = (Tcl_Channel) statePtr->bottomChanPtr; if (modePtr != NULL) { - *modePtr = statePtr->flags & (TCL_READABLE|TCL_WRITABLE); + *modePtr = GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE); } return TCL_OK; } @@ -1581,11 +1590,11 @@ Tcl_Channel Tcl_CreateChannel( const Tcl_ChannelType *typePtr, /* The channel type record. */ const char *chanName, /* Name of channel to record. */ - ClientData instanceData, /* Instance specific data. */ + void *instanceData, /* Instance specific data. */ int mask) /* TCL_READABLE & TCL_WRITABLE to indicate if * the channel is readable, writable. */ { Channel *chanPtr; /* The channel structure newly created. */ ChannelState *statePtr; /* The stack-level independent state info for @@ -1653,10 +1662,11 @@ 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 @@ -1664,19 +1674,20 @@ * happening. Tcl provides no "binary" encoding, so someone else has * provided one. We ignore it so as not to interfere with the "magic" * interpretation that Tcl_Channels give to the "-encoding binary" option. */ - statePtr->encoding = NULL; name = Tcl_GetEncodingName(NULL); - if (strcmp(name, "binary") != 0) { - statePtr->encoding = Tcl_GetEncoding(NULL, name); - } + statePtr->encoding = Tcl_GetEncoding(NULL, name); statePtr->inputEncodingState = NULL; statePtr->inputEncodingFlags = TCL_ENCODING_START; + ENCODING_PROFILE_SET(statePtr->inputEncodingFlags, + TCL_ENCODING_PROFILE_DEFAULT); statePtr->outputEncodingState = NULL; statePtr->outputEncodingFlags = TCL_ENCODING_START; + ENCODING_PROFILE_SET(statePtr->outputEncodingFlags, + TCL_ENCODING_PROFILE_DEFAULT); /* * 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 @@ -1685,11 +1696,10 @@ */ 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; @@ -1701,10 +1711,11 @@ 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; /* @@ -1802,11 +1813,11 @@ Tcl_StackChannel( Tcl_Interp *interp, /* The interpreter we are working in */ const Tcl_ChannelType *typePtr, /* The channel type record for the new * channel. */ - ClientData instanceData, /* Instance specific data for the new + void *instanceData, /* Instance specific data for the new * channel. */ int mask, /* TCL_READABLE & TCL_WRITABLE to indicate if * the channel is readable, writable. */ Tcl_Channel prevChan) /* The channel structure to replace */ { @@ -1848,11 +1859,11 @@ * W | | | + | + | the capabilities of the superceded one! * RW| | + | + | + | * --+---+---+---+----+ */ - if ((mask & (statePtr->flags & (TCL_READABLE | TCL_WRITABLE))) == 0) { + if ((mask & GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE)) == 0) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "reading and writing both disallowed for channel \"%s\"", Tcl_GetChannelName(prevChan))); } @@ -1901,11 +1912,11 @@ * To preserve the information without having to read them again and to * avoid problems with the location in the channel (seeking might be * impossible) we move the buffers from the common state structure into * the channel itself. We use the buffers in the channel below the new * transformation to hold the data. In the future this allows us to write - * transformations which pre-read data and push the unused part back when + * transformations which preread data and push the unused part back when * they are going away. */ if (((mask & TCL_READABLE) != 0) && (statePtr->inQueueHead != NULL)) { /* @@ -1991,11 +2002,11 @@ static void ChannelFree( Channel *chanPtr) { - if (!chanPtr->refCount) { + if (chanPtr->refCount == 0) { Tcl_Free(chanPtr); return; } chanPtr->typePtr = NULL; } @@ -2010,11 +2021,11 @@ * * Results: * A standard Tcl result. * * Side effects: - * If TCL_ERROR is returned, the posix error code will be set with + * If TCL_ERROR is returned, the Posix error code will be set with * Tcl_SetErrno. May leave a message in interp result as well. * *---------------------------------------------------------------------- */ @@ -2033,11 +2044,11 @@ chanPtr = statePtr->topChanPtr; if (chanPtr->downChanPtr != NULL) { /* - * Instead of manipulating the per-thread / per-interp list/hashtable + * Instead of manipulating the per-thread / per-interp list/hash table * of registered channels we wind down the state of the * transformation, and then restore the state of underlying channel * into the old structure. * * TODO: Figure out how to handle the situation where the chan @@ -2138,12 +2149,15 @@ * 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); @@ -2163,11 +2177,11 @@ /* * This channel does not cover another one. Simply do a close, if * necessary. */ - if (statePtr->refCount + 1 <= 1) { + if (statePtr->refCount <= 0) { if (Tcl_CloseEx(interp, chan, 0) != TCL_OK) { /* * TIP #219, Tcl Channel Reflection API. * "TclChanCaughtErrorBypass" is not required here, it was * done already by "Tcl_Close". @@ -2258,11 +2272,11 @@ * None. * *---------------------------------------------------------------------- */ -ClientData +void * Tcl_GetChannelInstanceData( Tcl_Channel chan) /* Channel for which to return client data. */ { Channel *chanPtr = (Channel *) chan; /* The actual channel. */ @@ -2346,11 +2360,11 @@ * computed. */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of actual channel. */ - return (statePtr->flags & (TCL_READABLE | TCL_WRITABLE)); + return GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE); } /* *---------------------------------------------------------------------- * @@ -2397,14 +2411,14 @@ int Tcl_GetChannelHandle( Tcl_Channel chan, /* The channel to get file from. */ int direction, /* TCL_WRITABLE or TCL_READABLE. */ - ClientData *handlePtr) /* Where to store handle */ + void **handlePtr) /* Where to store handle */ { Channel *chanPtr; /* The actual channel. */ - ClientData handle; + void *handle; int result; chanPtr = ((Channel *) chan)->state->bottomChanPtr; if (!chanPtr->typePtr->getHandleProc) { Tcl_SetChannelError(chan, Tcl_ObjPrintf( @@ -2417,10 +2431,58 @@ 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 -- @@ -2444,14 +2506,14 @@ *--------------------------------------------------------------------------- */ static ChannelBuffer * AllocChannelBuffer( - int length) /* Desired length of channel buffer. */ + Tcl_Size length) /* Desired length of channel buffer. */ { ChannelBuffer *bufPtr; - int n; + Tcl_Size n; n = length + CHANNELBUFFER_HEADER_SIZE + BUFFER_PADDING + BUFFER_PADDING; bufPtr = (ChannelBuffer *)Tcl_Alloc(n); bufPtr->nextAdded = BUFFER_PADDING; bufPtr->nextRemoved = BUFFER_PADDING; @@ -2483,11 +2545,11 @@ static int IsShared( ChannelBuffer *bufPtr) { - return bufPtr->refCount + 1 > 2; + return bufPtr->refCount > 1; } /* *---------------------------------------------------------------------- * @@ -2526,15 +2588,15 @@ ReleaseChannelBuffer(bufPtr); return; } /* - * Only save buffers which have the requested buffersize for the channel. - * This is to honor dynamic changes of the buffersize made by the user. + * Only save buffers which have the requested buffer size for the channel. + * This is to honor dynamic changes of the buffe rsize made by the user. */ - if ((bufPtr->bufLength - BUFFER_PADDING) != statePtr->bufSize) { + if ((bufPtr->bufLength) != statePtr->bufSize + BUFFER_PADDING) { ReleaseChannelBuffer(bufPtr); return; } /* @@ -2683,14 +2745,15 @@ int errorCode = 0; /* Stores POSIX error codes from channel * driver operations. */ int wroteSome = 0; /* Set to one if any data was written to the * driver. */ + int bufExists; /* * Prevent writing on a dead channel -- a channel that has been closed but * not yet deallocated. This can occur if the exit handler for the channel - * deallocation runs before all channels are deregistered in all + * deallocation runs before all channels are unregistered in all * interpreters. */ if (CheckForDeadChannel(interp, statePtr)) { return -1; @@ -2801,13 +2864,13 @@ */ if (calledFromAsyncFlush) { /* * TIP #219, Tcl Channel Reflection API. - * When defering the error copy a message from the bypass into + * When deferring the error copy a message from the bypass into * the unreported area. Or discard it if the new error is to - * be ignored in favor of an earlier defered error. + * be ignored in favor of an earlier deferred error. */ Tcl_Obj *msg = statePtr->chanMsg; if (statePtr->unreportedError == 0) { @@ -2851,12 +2914,12 @@ /* * When we get an error we throw away all the output currently * queued. */ - DiscardOutputQueued(statePtr); ReleaseChannelBuffer(bufPtr); + DiscardOutputQueued(statePtr); break; } else { /* * TODO: Consider detecting and reacting to short writes on * blocking channels. Ought not happen. See iocmd-24.2. @@ -2863,24 +2926,36 @@ */ 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); - } + 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 @@ -2919,11 +2994,11 @@ * If the channel is flagged as closed, delete it when the refCount drops * to zero, the output queue is empty and there is no output in the * current output buffer. */ - if (GotFlag(statePtr, CHANNEL_CLOSED) && (statePtr->refCount + 1 <= 1) && + if (GotFlag(statePtr, CHANNEL_CLOSED) && (statePtr->refCount <= 0) && (statePtr->outQueueHead == NULL) && ((statePtr->curOutPtr == NULL) || IsBufferEmpty(statePtr->curOutPtr))) { errorCode = CloseChannel(interp, chanPtr, errorCode); goto done; @@ -3009,22 +3084,10 @@ 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. */ @@ -3094,12 +3157,12 @@ } /* * Cancel any outstanding timer. */ + DeleteTimerHandler(statePtr); - Tcl_DeleteTimerHandler(statePtr->timer); /* * Mark the channel as deleted by clearing the type structure. */ @@ -3147,12 +3210,12 @@ * * NOTE: * The channel to cut out of the list must not be referenced in any * interpreter. This is something this procedure cannot check (despite * the refcount) because the caller usually wants fiddle with the channel - * (like transfering it to a different thread) and thus keeps the - * refcount artifically high to prevent its destruction. + * (like transferring it to a different thread) and thus keeps the + * refcount artificially high to prevent its destruction. * *---------------------------------------------------------------------- */ static void @@ -3262,13 +3325,13 @@ * Nothing. * * NOTE: * The channel to splice into the list must not be referenced in any * interpreter. This is something this procedure cannot check (despite - * the refcount) because the caller usually wants figgle with the channel - * (like transfering it to a different thread) and thus keeps the - * refcount artifically high to prevent its destruction. + * the refcount) because the caller usually wants fiddle with the channel + * (like transferring it to a different thread) and thus keeps the + * refcount artificially high to prevent its destruction. * *---------------------------------------------------------------------- */ static void @@ -3359,11 +3422,12 @@ int TclClose( Tcl_Interp *interp, /* Interpreter for errors. */ Tcl_Channel chan) /* The channel being closed. Must not be - * referenced in any interpreter. */ + * referenced in any interpreter. May be NULL, + * in which case this is a no-op. */ { CloseCallback *cbPtr; /* Iterate over close callbacks for this * channel. */ Channel *chanPtr; /* The real IO channel. */ ChannelState *statePtr; /* State of real IO channel. */ @@ -3391,11 +3455,11 @@ chanPtr = (Channel *) chan; statePtr = chanPtr->state; chanPtr = statePtr->topChanPtr; - if (statePtr->refCount + 1 > 1) { + if (statePtr->refCount > 0) { Tcl_Panic("called Tcl_Close on channel with refCount > 0"); } if (GotFlag(statePtr, CHANNEL_INCLOSE)) { if (interp) { @@ -3412,11 +3476,12 @@ * iso2022, the terminated escape sequence must write to the buffer. */ stickyError = 0; - if (GotFlag(statePtr, TCL_WRITABLE) && (statePtr->encoding != NULL) + if (GotFlag(statePtr, TCL_WRITABLE) + && (statePtr->encoding != GetBinaryEncoding()) && !(statePtr->outputEncodingFlags & TCL_ENCODING_START)) { int code = CheckChannelErrors(statePtr, TCL_WRITABLE); if (code == 0) { statePtr->outputEncodingFlags |= TCL_ENCODING_END; @@ -3446,11 +3511,11 @@ Tcl_ClearChannelHandlers(chan); /* * Cancel any outstanding timer. */ - Tcl_DeleteTimerHandler(statePtr->timer); + DeleteTimerHandler(statePtr); /* * Invoke the registered close callbacks and delete their records. */ @@ -3602,11 +3667,11 @@ * Check direction against channel mode. It is an error if we try to close * a direction not supported by the channel (already closed, or never * opened for that direction). */ - if (!(statePtr->flags & (TCL_READABLE | TCL_WRITABLE) & flags)) { + if (!(GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE) & flags)) { const char *msg; if (flags & TCL_CLOSE_READ) { msg = "read"; } else { @@ -3621,11 +3686,11 @@ /* * A user may try to call half-close from within a channel close handler. * That won't do. */ - if (statePtr->flags & CHANNEL_INCLOSE) { + if (GotFlag(statePtr, CHANNEL_INCLOSE)) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal recursive call to close through close-handler" " of channel", -1)); } @@ -3674,11 +3739,11 @@ * Side effects: * Closes the write side of the channel. * * NOTE: * CloseWrite removes the channel as far as the user is concerned. - * However, the ooutput data structures may continue to exist for a while + * However, the output data structures may continue to exist for a while * longer if it has a background flush scheduled. The device itself is * eventually closed and the channel structures modified, in * CloseChannelPart, below. * *---------------------------------------------------------------------- @@ -3784,22 +3849,10 @@ 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. */ @@ -3911,12 +3964,11 @@ chanPtr = statePtr->topChanPtr; /* * Cancel any outstanding timer. */ - - Tcl_DeleteTimerHandler(statePtr->timer); + DeleteTimerHandler(statePtr); /* * Remove any references to channel handlers for this channel that may be * about to be invoked. */ @@ -3979,25 +4031,25 @@ * the specified channel to the topmost channel in a stack. * * No encoding conversions are applied to the bytes being read. * * Results: - * The number of bytes written or TCL_IO_FAILURE in case of error. If - * TCL_IO_FAILURE, Tcl_GetErrno will return the error code. + * The number of bytes written or TCL_INDEX_NONE in case of error. If + * TCL_INDEX_NONE, Tcl_GetErrno will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_Write( Tcl_Channel chan, /* The channel to buffer output for. */ const char *src, /* Data to queue in output buffer. */ - size_t srcLen) /* Length of data in bytes, or -1 for + Tcl_Size srcLen) /* Length of data in bytes, or TCL_INDEX_NONE for * strlen(). */ { /* * Always use the topmost channel of the stack */ @@ -4007,18 +4059,18 @@ statePtr = ((Channel *) chan)->state; chanPtr = statePtr->topChanPtr; if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { - return TCL_IO_FAILURE; + return TCL_INDEX_NONE; } if (srcLen == TCL_INDEX_NONE) { srcLen = strlen(src); } if (WriteBytes(chanPtr, src, srcLen) == -1) { - return TCL_IO_FAILURE; + return TCL_INDEX_NONE; } return srcLen; } /* @@ -4033,35 +4085,35 @@ * compensate for stacking. * * No encoding conversions are applied to the bytes being read. * * Results: - * The number of bytes written or TCL_IO_FAILURE in case of error. If - * TCL_IO_FAILURE, Tcl_GetErrno will return the error code. + * The number of bytes written or TCL_INDEX_NONE in case of error. If + * TCL_INDEX_NONE, Tcl_GetErrno will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_WriteRaw( Tcl_Channel chan, /* The channel to buffer output for. */ const char *src, /* Data to queue in output buffer. */ - size_t srcLen) /* Length of data in bytes, or -1 for + Tcl_Size srcLen) /* Length of data in bytes, or TCL_INDEX_NONE for * strlen(). */ { Channel *chanPtr = ((Channel *) chan); ChannelState *statePtr = chanPtr->state; /* State info for channel */ int errorCode; - size_t written; + Tcl_Size written; if (CheckChannelErrors(statePtr, TCL_WRITABLE | CHANNEL_RAW_MODE) != 0) { - return TCL_IO_FAILURE; + return TCL_INDEX_NONE; } if (srcLen == TCL_INDEX_NONE) { srcLen = strlen(src); } @@ -4070,11 +4122,11 @@ * Go immediately to the driver, do all the error handling by ourselves. * The code was stolen from 'FlushChannel'. */ written = ChanWrite(chanPtr, src, srcLen, &errorCode); - if (written == TCL_IO_FAILURE) { + if (written == TCL_INDEX_NONE) { Tcl_SetErrno(errorCode); } return written; } @@ -4090,35 +4142,35 @@ * ready e.g. if it contains a newline and we are in line buffering * mode. Compensates stacking, i.e. will redirect the data from the * specified channel to the topmost channel in a stack. * * Results: - * The number of bytes written or TCL_IO_FAILURE in case of error. If - * TCL_IO_FAILURE, Tcl_GetErrno will return the error code. + * The number of bytes written or TCL_INDEX_NONE in case of error. If + * TCL_INDEX_NONE, Tcl_GetErrno will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_WriteChars( Tcl_Channel chan, /* The channel to buffer output for. */ const char *src, /* UTF-8 characters to queue in output * buffer. */ - size_t len) /* Length of string in bytes, or -1 for + Tcl_Size len) /* Length of string in bytes, or TCL_INDEX_NONE for * strlen(). */ { Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ - int result; + Tcl_Size result; Tcl_Obj *objPtr; if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { - return TCL_IO_FAILURE; + return TCL_INDEX_NONE; } chanPtr = statePtr->topChanPtr; if (len == TCL_INDEX_NONE) { @@ -4129,21 +4181,26 @@ } /* * Inefficient way to convert UTF-8 to byte-array, but the code * parallels the way it is done for objects. Special case for 1-byte - * (used by eg [puts] for the \n) could be extended to more efficient + * (used by e.g. [puts] for the \n) could be extended to more efficient * translation of the src string. */ if ((len == 1) && (UCHAR(*src) < 0xC0)) { return WriteBytes(chanPtr, src, len); } objPtr = Tcl_NewStringObj(src, len); - src = (char *) TclGetByteArrayFromObj(objPtr, &len); - result = WriteBytes(chanPtr, src, len); + src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len); + if (src == NULL) { + Tcl_SetErrno(EILSEQ); + result = TCL_INDEX_NONE; + } else { + result = WriteBytes(chanPtr, src, len); + } TclDecrRefCount(objPtr); return result; } /* @@ -4159,21 +4216,21 @@ * flush internal buffers to output if one becomes full or is ready for * some other reason, e.g. if it contains a newline and the channel is in * line buffering mode. * * Results: - * The number of bytes written or -1 in case of error. If -1, - * Tcl_GetErrno() will return the error code. + * The number of bytes written or TCL_INDEX_NONE in case of error. If + * TCL_INDEX_NONE, Tcl_GetErrno() will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_WriteObj( Tcl_Channel chan, /* The channel to buffer output for. */ Tcl_Obj *objPtr) /* The object to write. */ { /* @@ -4181,23 +4238,31 @@ */ Channel *chanPtr; ChannelState *statePtr; /* State info for channel */ const char *src; - size_t srcLen = 0; + Tcl_Size srcLen = 0; statePtr = ((Channel *) chan)->state; chanPtr = statePtr->topChanPtr; if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { - return TCL_IO_FAILURE; + return TCL_INDEX_NONE; } if (statePtr->encoding == NULL) { - src = (char *) TclGetByteArrayFromObj(objPtr, &srcLen); - return WriteBytes(chanPtr, src, srcLen); + Tcl_Size result; + + src = (char *) Tcl_GetByteArrayFromObj(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); + src = Tcl_GetStringFromObj(objPtr, &srcLen); return WriteChars(chanPtr, src, srcLen); } } static void @@ -4256,31 +4321,34 @@ * produced bytes into an output buffer, may queue the buffer for output * if it gets full, and also remembers whether the current buffer is * ready e.g. if it contains a newline and we are in line buffering mode. * * Results: - * The number of bytes written or -1 in case of error. If -1, + * The number of bytes written or TCL_INDEX_NONE in case of error. If TCL_INDEX_NONE, * Tcl_GetErrno will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ -static int +static Tcl_Size Write( Channel *chanPtr, /* The channel to buffer output for. */ const char *src, /* UTF-8 string to write. */ - int srcLen, /* Length of UTF-8 string in bytes. */ + Tcl_Size srcLen, /* Length of UTF-8 string in bytes. */ Tcl_Encoding encoding) { ChannelState *statePtr = chanPtr->state; /* State info for channel */ char *nextNewLine = NULL; - int endEncoding, saved = 0, total = 0, flushed = 0, needNlFlush = 0; + int endEncoding, needNlFlush = 0; + Tcl_Size saved = 0, total = 0, flushed = 0; + char safe[BUFFER_PADDING]; + int encodingError = 0; if (srcLen) { WillWrite(chanPtr); } @@ -4287,20 +4355,20 @@ /* * Write the terminated escape sequence even if srcLen is 0. */ endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0); - if (GotFlag(statePtr, CHANNEL_LINEBUFFERED) || (statePtr->outputTranslation != TCL_TRANSLATE_LF)) { nextNewLine = (char *)memchr(src, '\n', srcLen); } - while (srcLen + saved + endEncoding > 0) { + while (srcLen + saved + endEncoding > 0 && !encodingError) { ChannelBuffer *bufPtr; - char *dst, safe[BUFFER_PADDING]; - int result, srcRead, dstLen, dstWrote, srcLimit = srcLen; + char *dst; + int result, srcRead, dstLen, dstWrote; + Tcl_Size srcLimit = srcLen; if (nextNewLine) { srcLimit = nextNewLine - src; } @@ -4318,11 +4386,10 @@ 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, @@ -4333,21 +4400,28 @@ * See chan-io-1.[89]. Tcl Bug 506297. */ statePtr->outputEncodingFlags &= ~TCL_ENCODING_START; - if ((result != TCL_OK) && (srcRead + dstWrote == 0)) { + /* + * 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. */ - - ReleaseChannelBuffer(bufPtr); - if (total == 0) { - Tcl_SetErrno(EINVAL); - return -1; - } - break; + ((result != TCL_OK) && (srcRead + dstWrote == 0)) + ) { + encodingError = 1; + result = TCL_OK; } bufPtr->nextAdded += dstWrote; src += srcRead; srcLen -= srcRead; @@ -4401,11 +4475,11 @@ * the output buffer, so that we would get a completely full * buffer before flushing it. The extra bytes will be moved to the * beginning of the next buffer. */ - saved = 1 + ~SpaceLeft(bufPtr); + saved = -SpaceLeft(bufPtr); memcpy(safe, dst + dstLen, saved); bufPtr->nextAdded = bufPtr->bufLength; } if ((srcLen + saved == 0) && (result == TCL_OK)) { @@ -4412,18 +4486,17 @@ 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 + * 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 @@ -4432,21 +4505,24 @@ if (needNlFlush && (saved == 0 || src[-1] != '\n')) { needNlFlush = 0; } } - ReleaseChannelBuffer(bufPtr); } - if ((flushed < total) && (GotFlag(statePtr, CHANNEL_UNBUFFERED) || - (needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED)))) { + if (((flushed < total) && GotFlag(statePtr, CHANNEL_UNBUFFERED)) || + (needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED))) { if (FlushChannel(NULL, chanPtr, 0) != 0) { return -1; } } UpdateInterest(chanPtr); + if (encodingError) { + Tcl_SetErrno(EILSEQ); + return -1; + } return total; } /* *--------------------------------------------------------------------------- @@ -4454,35 +4530,35 @@ * Tcl_Gets -- * * Reads a complete line of input from the channel into a Tcl_DString. * * Results: - * Length of line read (in characters) or -1 if error, EOF, or blocked. - * If -1, use Tcl_GetErrno() to retrieve the POSIX error code for the + * Length of line read (in characters) or TCL_INDEX_NONE if error, EOF, or blocked. + * If TCL_INDEX_NONE, use Tcl_GetErrno() to retrieve the POSIX error code for the * error or condition that occurred. * * Side effects: * May flush output on the channel. May cause input to be consumed from * the channel. * *--------------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_Gets( Tcl_Channel chan, /* Channel from which to read. */ Tcl_DString *lineRead) /* The line read will be appended to this * DString as UTF-8 characters. The caller * must have initialized it and is responsible * for managing the storage. */ { Tcl_Obj *objPtr; - size_t charsStored; + Tcl_Size charsStored; TclNewObj(objPtr); charsStored = Tcl_GetsObj(chan, objPtr); - if (charsStored + 1 > 1) { + if (charsStored > 0) { TclDStringAppendObj(lineRead, objPtr); } TclDecrRefCount(objPtr); return charsStored; } @@ -4495,12 +4571,12 @@ * Accumulate input from the input channel until end-of-line or * end-of-file has been seen. Bytes read from the input channel are * converted to UTF-8 using the encoding specified by the channel. * * Results: - * Number of characters accumulated in the object or -1 if error, - * blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the POSIX error + * Number of characters accumulated in the object or TCL_INDEX_NONE if error, + * blocked, or EOF. If TCL_INDEX_NONE, use Tcl_GetErrno() to retrieve the POSIX error * code for the error or condition that occurred. * * Side effects: * Consumes input from the channel. * @@ -4508,11 +4584,11 @@ * leave channel pointing after EOL, but don't return EOL in dst buffer. * *--------------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_GetsObj( Tcl_Channel chan, /* Channel from which to read. */ Tcl_Obj *objPtr) /* The line read will be appended to this * object as UTF-8 characters. */ { @@ -4520,17 +4596,24 @@ Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; int inEofChar, skip, copiedTotal, oldFlags, oldRemoved; - size_t oldLength; + Tcl_Size oldLength; Tcl_Encoding encoding; char *dst, *dstEnd, *eol, *eof; Tcl_EncodingState oldState; + + if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) { + UpdateInterest(chanPtr); + ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_ENCODING_ERROR); + Tcl_SetErrno(EILSEQ); + return TCL_INDEX_NONE; + } if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { - return TCL_IO_FAILURE; + return TCL_INDEX_NONE; } /* * If we're sitting ready to read the eofchar, there's no need to * do it. @@ -4541,22 +4624,23 @@ assert(statePtr->inputEncodingFlags & TCL_ENCODING_END); assert(!GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR)); /* TODO: Do we need this? */ UpdateInterest(chanPtr); - return TCL_IO_FAILURE; + return TCL_INDEX_NONE; } /* * A binary version of Tcl_GetsObj. This could also handle encodings that * are ascii-7 pure (iso8859, utf-8, ...) with a final encoding conversion * done on objPtr. */ - if ((statePtr->encoding == NULL) + if (statePtr->encoding == GetBinaryEncoding() && ((statePtr->inputTranslation == TCL_TRANSLATE_LF) - || (statePtr->inputTranslation == TCL_TRANSLATE_CR))) { + || (statePtr->inputTranslation == TCL_TRANSLATE_CR)) + && Tcl_GetByteArrayFromObj(objPtr, (Tcl_Size *)NULL) != NULL) { return TclGetsObjBinary(chan, objPtr); } /* * This operation should occur at the top of a channel stack. @@ -4571,27 +4655,18 @@ /* * Preserved so we can restore the channel's state in case we don't find a * newline in the available input. */ - (void)TclGetStringFromObj(objPtr, &oldLength); + (void)Tcl_GetStringFromObj(objPtr, &oldLength); 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. */ @@ -4663,16 +4738,16 @@ if (*eol == '\r') { eol++; /* * If a CR is at the end of the buffer, then check for a - * LF at the begining of the next buffer, unless EOF char + * LF at the beginning of the next buffer, unless EOF char * was found already. */ if (eol >= dstEnd) { - size_t offset; + Tcl_Size offset; if (eol != eof) { offset = eol - objPtr->bytes; dst = dstEnd; if (FilterInputBytes(chanPtr, &gs) != 0) { @@ -4696,11 +4771,10 @@ 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'. */ @@ -4746,12 +4820,14 @@ } 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) { @@ -4776,13 +4852,26 @@ */ Tcl_SetObjLength(objPtr, oldLength); CommonGetsCleanup(chanPtr); copiedTotal = -1; - ResetFlag(statePtr, CHANNEL_BLOCKED); + ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR); goto done; } + goto gotEOL; + } else if (gs.bytesWrote == 0 + && GotFlag(statePtr, CHANNEL_ENCODING_ERROR) + && !GotFlag(statePtr, CHANNEL_NONBLOCKING)) { + /* 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; } @@ -4879,10 +4968,11 @@ */ 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))); /* @@ -4895,10 +4985,16 @@ 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; } /* *--------------------------------------------------------------------------- @@ -4912,12 +5008,12 @@ * WARNING! The notion of "binary" used here is different from notions * of "binary" used in other places. In particular, this "binary" routine * may be called when an -eofchar is set on the channel. * * Results: - * Number of characters accumulated in the object or -1 if error, - * blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the POSIX error + * Number of characters accumulated in the object or TCL_INDEX_NONE if error, + * blocked, or EOF. If TCL_INDEX_NONE, use Tcl_GetErrno() to retrieve the POSIX error * code for the error or condition that occurred. * * Side effects: * Consumes input from the channel. * @@ -4936,11 +5032,11 @@ Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; int inEofChar, skip, copiedTotal, oldFlags, oldRemoved; - size_t rawLen, byteLen = 0, oldLength; + Tcl_Size rawLen, byteLen = 0, oldLength; int eolChar; unsigned char *dst, *dstEnd, *eol, *eof, *byteArray; /* * This operation should occur at the top of a channel stack. @@ -4954,11 +5050,15 @@ /* * 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); + byteArray = Tcl_GetByteArrayFromObj(objPtr, &byteLen); + if (byteArray == NULL) { + Tcl_SetErrno(EILSEQ); + return -1; + } oldFlags = statePtr->inputEncodingFlags; oldRemoved = BUFFER_PADDING; oldLength = byteLen; if (bufPtr != NULL) { oldRemoved = bufPtr->nextRemoved; @@ -5061,11 +5161,11 @@ skip = 0; eol = dstEnd; if ((dst == dstEnd) && (byteLen == oldLength)) { /* * If we didn't append any bytes before encountering EOF, - * caller needs to see -1. + * caller needs to see TCL_INDEX_NONE. */ byteArray = Tcl_SetByteArrayLength(objPtr, oldLength); CommonGetsCleanup(chanPtr); copiedTotal = -1; @@ -5110,11 +5210,11 @@ /* * Convert the buffer if there was an encoding. * XXX - unimplemented. */ - if (statePtr->encoding != NULL) { + if (statePtr->encoding != GetBinaryEncoding()) { } /* * Recycle all the emptied buffers. */ @@ -5188,12 +5288,11 @@ * *--------------------------------------------------------------------------- */ static void -FreeBinaryEncoding( - TCL_UNUSED(ClientData)) +FreeBinaryEncoding(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->binaryEncoding != NULL) { Tcl_FreeEncoding(tsdPtr->binaryEncoding); @@ -5200,17 +5299,16 @@ tsdPtr->binaryEncoding = NULL; } } static Tcl_Encoding -GetBinaryEncoding() +GetBinaryEncoding(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->binaryEncoding == NULL) { tsdPtr->binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1"); - Tcl_CreateThreadExitHandler(FreeBinaryEncoding, NULL); } if (tsdPtr->binaryEncoding == NULL) { Tcl_Panic("binary encoding is not available"); } return tsdPtr->binaryEncoding; @@ -5344,14 +5442,22 @@ 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] */ @@ -5568,24 +5674,24 @@ * destination buffer. * * No encoding conversions are applied to the bytes being read. * * Results: - * The number of bytes read, or -1 on error. Use Tcl_GetErrno() to + * The number of bytes read, or TCL_INDEX_NONE on error. Use Tcl_GetErrno() to * retrieve the error code for the error that occurred. * * Side effects: * May cause input to be buffered. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_Read( Tcl_Channel chan, /* The channel from which to read. */ char *dst, /* Where to store input read. */ - size_t bytesToRead) /* Maximum number of bytes to read. */ + Tcl_Size bytesToRead) /* Maximum number of bytes to read. */ { Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ @@ -5594,11 +5700,11 @@ */ chanPtr = statePtr->topChanPtr; if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { - return TCL_IO_FAILURE; + return TCL_INDEX_NONE; } return DoRead(chanPtr, dst, bytesToRead, 0); } @@ -5613,33 +5719,33 @@ * destination buffer. * * No encoding conversions are applied to the bytes being read. * * Results: - * The number of bytes read, or -1 on error. Use Tcl_GetErrno() to + * The number of bytes read, or TCL_INDEX_NONE on error. Use Tcl_GetErrno() to * retrieve the error code for the error that occurred. * * Side effects: * May cause input to be buffered. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_ReadRaw( Tcl_Channel chan, /* The channel from which to read. */ char *readBuf, /* Where to store input read. */ - size_t bytesToRead) /* Maximum number of bytes to read. */ + Tcl_Size bytesToRead) /* Maximum number of bytes to read. */ { Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ int copied = 0; assert(bytesToRead > 0); if (CheckChannelErrors(statePtr, TCL_READABLE | CHANNEL_RAW_MODE) != 0) { - return TCL_IO_FAILURE; + return TCL_INDEX_NONE; } /* * First read bytes from the push-back buffers. */ @@ -5673,11 +5779,11 @@ } } /* * Go to the driver only if we got nothing from pushback. Have to do it - * this way to avoid EOF mis-timings when we consider the ability that EOF + * this way to avoid EOF mistimings when we consider the ability that EOF * may not be a permanent condition in the driver, and in that case we * have to synchronize. */ if (copied) { @@ -5705,12 +5811,12 @@ if (!GotFlag(statePtr, CHANNEL_BLOCKED) || copied == 0) { copied = -1; } } else if (nread > 0) { /* - * Successful read (short is OK) - add to bytes copied. - */ + * Successful read (short is OK) - add to bytes copied. + */ copied += nread; } else { /* * nread == 0. Driver is at EOF. Let that state filter up. @@ -5731,25 +5837,25 @@ * in a Tcl byte array object. Otherwise, the raw bytes are converted to * UTF-8 using the channel's current encoding and stored in a Tcl string * object. * * Results: - * The number of characters read, or -1 on error. Use Tcl_GetErrno() to + * The number of characters read, or TCL_INDEX_NONE on error. Use Tcl_GetErrno() to * retrieve the error code for the error that occurred. * * Side effects: * May cause input to be buffered. * *--------------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_ReadChars( Tcl_Channel chan, /* The channel to read. */ Tcl_Obj *objPtr, /* Input data is stored in this object. */ - size_t toRead, /* Maximum number of characters to store, or - * -1 to read all available data (up to EOF or + Tcl_Size toRead, /* Maximum number of characters to store, or + * TCL_INDEX_NONE to read all available data (up to EOF or * when channel blocks). */ int appendFlag) /* If non-zero, data read from the channel * will be appended to the object. Otherwise, * the data will replace the existing contents * of the object. */ @@ -5769,14 +5875,14 @@ * Update the notifier state so we don't block while there is still * data in the buffers. */ UpdateInterest(chanPtr); - return -1; + return TCL_INDEX_NONE; } - return DoReadChars(chanPtr, objPtr, toRead, appendFlag); + return DoReadChars(chanPtr, objPtr, toRead, 0, appendFlag); } /* *--------------------------------------------------------------------------- * * DoReadChars -- @@ -5787,66 +5893,49 @@ * in a Tcl byte array object. Otherwise, the raw bytes are converted to * UTF-8 using the channel's current encoding and stored in a Tcl string * object. * * Results: - * The number of characters read, or -1 on error. Use Tcl_GetErrno() to + * The number of characters read, or TCL_INDEX_NONE on error. Use Tcl_GetErrno() to * retrieve the error code for the error that occurred. * * Side effects: * May cause input to be buffered. * *--------------------------------------------------------------------------- */ -static int +static Tcl_Size DoReadChars( Channel *chanPtr, /* The channel to read. */ Tcl_Obj *objPtr, /* Input data is stored in this object. */ - size_t toRead, /* Maximum number of characters to store, or - * -1 to read all available data (up to EOF or + Tcl_Size toRead, /* Maximum number of characters to store, or + * TCL_INDEX_NONE to read all available data (up to EOF or * when channel blocks). */ + int allowShortReads, /* Allow half-blocking (pipes,sockets) */ int appendFlag) /* If non-zero, data read from the channel * will be appended to the object. Otherwise, * the data will replace the existing contents * of the object. */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; - int copied, copiedNow, result; + Tcl_Size copied; + int result; Tcl_Encoding encoding = statePtr->encoding; int binaryMode; #define UTF_EXPANSION_FACTOR 1024 int factor = UTF_EXPANSION_FACTOR; - binaryMode = (encoding == NULL) - && (statePtr->inputTranslation == TCL_TRANSLATE_LF) - && (statePtr->inEofChar == '\0'); - - if (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); - } - } - + 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. @@ -5855,11 +5944,11 @@ if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) { SetFlag(statePtr, CHANNEL_EOF); assert(statePtr->inputEncodingFlags & TCL_ENCODING_END); assert(!GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR)); - /* TODO: We don't need this call? */ + /* TODO: UpdateInterest not needed here? */ UpdateInterest(chanPtr); return 0; } /* @@ -5869,11 +5958,11 @@ if (GotFlag(statePtr, CHANNEL_EOF)) { statePtr->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF); statePtr->inputEncodingFlags &= ~TCL_ENCODING_END; - /* TODO: We don't need this call? */ + /* TODO: UpdateInterest not needed here? */ UpdateInterest(chanPtr); return 0; } /* @@ -5880,10 +5969,26 @@ * 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_GetByteArrayFromObj(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. */ @@ -5890,21 +5995,21 @@ if (GotFlag(statePtr, CHANNEL_EOF)) { statePtr->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF); statePtr->inputEncodingFlags &= ~TCL_ENCODING_END; - for (copied = 0; toRead > 0; ) { - copiedNow = -1; + for (copied = 0; toRead != 0 ; ) { + int copiedNow = -1; if (statePtr->inQueueHead != NULL) { if (binaryMode) { copiedNow = ReadBytes(statePtr, objPtr, toRead); } else { copiedNow = ReadChars(statePtr, objPtr, toRead, &factor); } /* - * If the current buffer is empty recycle it. + * Recycle current buffer if empty. */ bufPtr = statePtr->inQueueHead; if (IsBufferEmpty(bufPtr)) { ChannelBuffer *nextPtr = bufPtr->nextPtr; @@ -5913,18 +6018,31 @@ statePtr->inQueueHead = nextPtr; if (nextPtr == NULL) { statePtr->inQueueTail = NULL; } } + + /* + * If CHANNEL_ENCODING_ERROR and CHANNEL_STICKY_EOF are both set, + * then CHANNEL_ENCODING_ERROR was caused by data that occurred + * after the EOF character was encountered, so it doesn't count as + * a real error. + */ + + if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR) + && !GotFlag(statePtr, CHANNEL_STICKY_EOF) + && (!GotFlag(statePtr, CHANNEL_NONBLOCKING))) { + goto finish; + } } if (copiedNow < 0) { if (GotFlag(statePtr, CHANNEL_EOF)) { break; } - if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_BLOCKED) - == (CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)) { + if ((GotFlag(statePtr, CHANNEL_NONBLOCKING) || allowShortReads) + && GotFlag(statePtr, CHANNEL_BLOCKED)) { break; } result = GetInput(chanPtr); if (chanPtr != statePtr->topChanPtr) { TclChannelRelease((Tcl_Channel)chanPtr); @@ -5937,14 +6055,17 @@ } break; } } else { copied += copiedNow; - toRead -= 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. */ @@ -5952,11 +6073,11 @@ if (toRead == 0) { ResetFlag(statePtr, CHANNEL_BLOCKED); } /* - * Regenerate the top channel, in case it was changed due to + * Regenerate chanPtr in case it was changed due to * self-modifying reflected transforms. */ if (chanPtr != statePtr->topChanPtr) { TclChannelRelease((Tcl_Channel)chanPtr); @@ -5969,14 +6090,27 @@ * 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; } /* @@ -5992,11 +6126,11 @@ * 'bytesToRead' can safely be a very large number because space is only * allocated to hold data read from the channel as needed. * * Results: * The return value is the number of bytes appended to the object, or - * -1 to indicate that zero bytes were read due to an EOF. + * TCL_INDEX_NONE to indicate that zero bytes were read due to an EOF. * * Side effects: * The storage of bytes in objPtr can cause (re-)allocation of memory. * *--------------------------------------------------------------------------- @@ -6061,17 +6195,17 @@ Tcl_Obj *objPtr, /* Input data is appended to this object. * objPtr->length is how much space has been * allocated to hold data, not how many bytes * of data have been stored in the object. */ int charsToRead, /* Maximum number of characters to store, or - * -1 to get all available characters. + * TCL_INDEX_NONE to get all available characters. * Characters are obtained from the first * buffer in the queue -- even if this number * is larger than the number of characters * available in the first buffer, only the * characters from the first buffer are - * returned. The execption is when there is + * returned. The exception is when there is * not any complete character in the first * buffer. In that case, a recursive call * effectively obtains chars from the * second buffer. */ int *factorPtr) /* On input, contains a guess of how many @@ -6078,18 +6212,17 @@ * 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_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); - size_t numBytes; + Tcl_Size numBytes; int srcLen = BytesLeft(bufPtr); /* * One src byte can yield at most one character. So when the number of * src bytes we plan to read is less than the limit on character count to @@ -6106,17 +6239,17 @@ */ int factor = *factorPtr; int dstLimit = TCL_UTF_MAX - 1 + toRead * factor / UTF_EXPANSION_FACTOR; - (void) TclGetStringFromObj(objPtr, &numBytes); + (void) Tcl_GetStringFromObj(objPtr, &numBytes); Tcl_AppendToObj(objPtr, NULL, dstLimit); if (toRead == srcLen) { - size_t size; + Tcl_Size size; dst = TclGetStringStorage(objPtr, &size) + numBytes; - dstLimit = size - numBytes; + dstLimit = (size - numBytes) > INT_MAX ? INT_MAX : (size - numBytes); } else { dst = TclGetString(objPtr) + numBytes; } /* @@ -6161,10 +6294,20 @@ || (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 @@ -6189,16 +6332,16 @@ * NOTE the bizarre spec of TranslateInputEOL in this case. * Clearly the eof char had to be read in order to account for * the stopping, but the value of dstRead does not include it. * * Also rather bizarre, our caller can only notice an EOF - * condition if we return the value -1 as the number of chars + * condition if we return the value TCL_INDEX_NONE as the number of chars * read. This forces us to perform a 2-call dance where the * first call can read all the chars up to the eof char, and * the second call is solely for consuming the encoded eof * char then pointed at by src so that we can return that - * magic -1 value. This seems really wasteful, especially + * magic TCL_INDEX_NONE value. This seems really wasteful, especially * since the first decoding pass of each call is likely to * decode many bytes beyond that eof char that's all we care * about. */ @@ -6297,11 +6440,11 @@ Tcl_SetObjLength(objPtr, numBytes + 1); return 1; } - } else if (statePtr->flags & CHANNEL_EOF) { + } else if (GotFlag(statePtr, CHANNEL_EOF)) { /* * The bare \r is the only char and we will never read a * subsequent char to make the determination. */ @@ -6400,11 +6543,11 @@ * to prevent exactly this situation. I.e. it should never happen. * Therefore it is ok to panic should it happen despite the * precautions. */ - if (nextPtr->nextRemoved - srcLen < 0) { + if (nextPtr->nextRemoved < srcLen) { Tcl_Panic("Buffer Underflow, BUFFER_PADDING not enough"); } nextPtr->nextRemoved -= srcLen; memcpy(RemovePoint(nextPtr), src, srcLen); @@ -6563,11 +6706,11 @@ case TCL_TRANSLATE_AUTO: { const char *crFound, *src = srcStart; char *dst = dstStart; int lesser; - if ((statePtr->flags & INPUT_SAW_CR) && srcLen) { + if (GotFlag(statePtr, INPUT_SAW_CR) && srcLen) { if (*src == '\n') { src++; srcLen--; } ResetFlag(statePtr, INPUT_SAW_CR); } lesser = (dstLen < srcLen) ? dstLen : srcLen; while ((crFound = (const char *)memchr(src, '\r', lesser))) { @@ -6598,15 +6741,18 @@ if (srcStart + srcLen == eof) { /* * EOF character was seen in EOL translated range. Leave current file * position pointing at the EOF character, but don't store the EOF * character in the output string. + * + * If CHANNEL_ENCODING_ERROR is set, it can only be because of data + * encountered after the EOF character, so it is nonsense. Unset it. */ SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF); statePtr->inputEncodingFlags |= TCL_ENCODING_END; - ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR); + ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR|CHANNEL_ENCODING_ERROR); } } /* *---------------------------------------------------------------------- @@ -6615,23 +6761,23 @@ * * Causes the supplied string to be added to the input queue of the * channel, at either the head or tail of the queue. * * Results: - * The number of bytes stored in the channel, or TCL_IO_FAILURE on error. + * The number of bytes stored in the channel, or TCL_INDEX_NONE on error. * * Side effects: * Adds input to the input queue of a channel. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_Ungets( Tcl_Channel chan, /* The channel for which to add the input. */ const char *str, /* The input itself. */ - size_t len, /* The length of the input. */ + Tcl_Size len, /* The length of the input. */ int atEnd) /* If non-zero, add at end of queue; otherwise * add at head of queue. */ { Channel *chanPtr; /* The real IO channel. */ ChannelState *statePtr; /* State of actual channel. */ @@ -6651,11 +6797,11 @@ * CheckChannelErrors clears too many flag bits in this one case. */ flags = statePtr->flags; if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { - len = TCL_IO_FAILURE; + len = TCL_INDEX_NONE; goto done; } statePtr->flags = flags; /* @@ -6894,11 +7040,11 @@ * * TODO: Tests to cover this. */ if ((bufPtr != NULL) - && (bufPtr->bufLength - BUFFER_PADDING != statePtr->bufSize)) { + && (bufPtr->bufLength != statePtr->bufSize + BUFFER_PADDING)) { ReleaseChannelBuffer(bufPtr); bufPtr = NULL; } if (bufPtr == NULL) { @@ -6905,11 +7051,11 @@ bufPtr = AllocChannelBuffer(statePtr->bufSize); } bufPtr->nextPtr = NULL; toRead = SpaceLeft(bufPtr); - assert(toRead == statePtr->bufSize); + assert((Tcl_Size)toRead == statePtr->bufSize); if (statePtr->inQueueTail == NULL) { statePtr->inQueueHead = bufPtr; } else { statePtr->inQueueTail->nextPtr = bufPtr; @@ -6919,19 +7065,21 @@ toRead = SpaceLeft(bufPtr); } PreserveChannelBuffer(bufPtr); nread = ChanRead(chanPtr, InsertPoint(bufPtr), toRead); + ReleaseChannelBuffer(bufPtr); if (nread < 0) { result = Tcl_GetErrno(); } else { result = 0; - bufPtr->nextAdded += nread; + if (statePtr->inQueueTail != NULL) { + statePtr->inQueueTail->nextAdded += nread; + } } - ReleaseChannelBuffer(bufPtr); return result; } /* *---------------------------------------------------------------------- @@ -6949,24 +7097,24 @@ * May flush output on the channel. May discard queued input. * *---------------------------------------------------------------------- */ -Tcl_WideInt +long long Tcl_Seek( Tcl_Channel chan, /* The channel on which to seek. */ - Tcl_WideInt offset, /* Offset to seek to. */ + long long offset, /* Offset to seek to. */ int mode) /* Relative to which location to seek? */ { Channel *chanPtr = (Channel *) chan; /* The real IO channel. */ ChannelState *statePtr = chanPtr->state; /* State info for channel */ int inputBuffered, outputBuffered; /* # bytes held in buffers. */ int result; /* Of device driver operations. */ - Tcl_WideInt curPos; /* Position on the device. */ + long long curPos; /* Position on the device. */ int wasAsync; /* Was the channel nonblocking before the seek * operation? If so, must restore to * non-blocking mode after the seek. */ if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) { @@ -7119,11 +7267,11 @@ * None. * *---------------------------------------------------------------------- */ -Tcl_WideInt +long long Tcl_Tell( Tcl_Channel chan) /* The channel to return pos for. */ { Channel *chanPtr = (Channel *) chan; /* The real IO channel. */ @@ -7130,11 +7278,11 @@ ChannelState *statePtr = chanPtr->state; /* State info for channel */ int inputBuffered, outputBuffered; /* # bytes held in buffers. */ int result; /* Of calling device driver. */ - Tcl_WideInt curPos; /* Position on device. */ + long long curPos; /* Position on device. */ if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) { return -1; } @@ -7211,11 +7359,11 @@ */ int Tcl_TruncateChannel( Tcl_Channel chan, /* Channel to truncate. */ - Tcl_WideInt length) /* Length to truncate it to. */ + long long length) /* Length to truncate it to. */ { Channel *chanPtr = (Channel *) chan; Tcl_DriverTruncateProc *truncateProc = Tcl_ChannelTruncateProc(chanPtr->typePtr); int result; @@ -7240,11 +7388,11 @@ return TCL_ERROR; } /* * Seek first to force a total flush of all pending buffers and ditch any - * pre-read input data. + * preread input data. */ WillWrite(chanPtr); if (WillRead(chanPtr) == -1) { @@ -7300,11 +7448,11 @@ Tcl_SetErrno(statePtr->unreportedError); statePtr->unreportedError = 0; /* * TIP #219, Tcl Channel Reflection API. - * Move a defered error message back into the channel bypass. + * Move a deferred error message back into the channel bypass. */ if (statePtr->chanMsg != NULL) { TclDecrRefCount(statePtr->chanMsg); } @@ -7325,11 +7473,11 @@ /* * Fail if the channel is not opened for desired operation. */ - if ((statePtr->flags & direction) == 0) { + if (GotFlag(statePtr, direction) == 0) { Tcl_SetErrno(EACCES); return -1; } /* @@ -7373,10 +7521,13 @@ 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; } /* *---------------------------------------------------------------------- @@ -7435,11 +7586,11 @@ bufPtr = bufPtr->nextPtr) { bytesBuffered += BytesLeft(bufPtr); } /* - * Don't forget the bytes in the topmost pushback area. + * Remember the bytes in the topmost pushback area. */ for (bufPtr = statePtr->topChanPtr->inQueueHead; bufPtr != NULL; bufPtr = bufPtr->nextPtr) { bytesBuffered += BytesLeft(bufPtr); @@ -7543,11 +7694,11 @@ */ void Tcl_SetChannelBufferSize( Tcl_Channel chan, /* The channel whose buffer size to set. */ - int sz) /* The size to set. */ + Tcl_Size sz) /* The size to set. */ { ChannelState *statePtr; /* State of real channel structure. */ /* * Clip the buffer size to force it into the [1,1M] range @@ -7597,11 +7748,11 @@ * None. * *---------------------------------------------------------------------- */ -int +Tcl_Size Tcl_GetChannelBufferSize( Tcl_Channel chan) /* The channel for which to find the buffer * size. */ { ChannelState *statePtr = ((Channel *) chan)->state; @@ -7625,11 +7776,11 @@ * TCL_ERROR. * * Side effects: * An error message is generated in interp's result object to indicate - * that a command was invoked with the a bad option. The message has the + * that a command was invoked with a bad option. The message has the * form: * bad option "blah": should be one of * <...generic options...>+<...specific options...> * "blah" is the optionName argument and "" is a space * separated list of specific option words. The function takes good care @@ -7647,13 +7798,13 @@ * standard generic options. Can be NULL for * generic options only. */ { if (interp != NULL) { const char *genericopt = - "blocking buffering buffersize encoding eofchar translation"; + "blocking buffering buffersize encoding eofchar profile translation"; const char **argv; - int argc, i; + Tcl_Size argc, i; Tcl_DString ds; Tcl_Obj *errObj; Tcl_DStringInit(&ds); Tcl_DStringAppend(&ds, genericopt, -1); @@ -7707,11 +7858,11 @@ Tcl_Channel chan, /* Channel on which to get option. */ const char *optionName, /* Option to get. */ Tcl_DString *dsPtr) /* Where to store value(s). */ { size_t len; /* Length of optionName string. */ - char optionVal[128]; /* Buffer for sprintf. */ + char optionVal[128]; /* Buffer for snprintf. */ Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ int flags; @@ -7792,59 +7943,43 @@ } if (len == 0 || HaveOpt(2, "-encoding")) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-encoding"); } - if (statePtr->encoding == NULL) { - Tcl_DStringAppendElement(dsPtr, "binary"); - } else { - Tcl_DStringAppendElement(dsPtr, - Tcl_GetEncodingName(statePtr->encoding)); - } + Tcl_DStringAppendElement(dsPtr, + Tcl_GetEncodingName(statePtr->encoding)); if (len > 0) { return TCL_OK; } } if (len == 0 || HaveOpt(2, "-eofchar")) { + char buf[4] = ""; if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-eofchar"); } - if (((flags & (TCL_READABLE|TCL_WRITABLE)) == - (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 ((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")) { @@ -7940,12 +8075,12 @@ Channel *chanPtr = (Channel *) chan; /* The real IO channel. */ ChannelState *statePtr = chanPtr->state; /* State info for channel */ size_t len; /* Length of optionName string. */ - int argc; - const char **argv; + Tcl_Size argc; + const char **argv = NULL; /* * If the channel is in the middle of a background copy, fail. */ @@ -8007,22 +8142,39 @@ " full, line, or none", -1)); return TCL_ERROR; } return TCL_OK; } else if (HaveOpt(7, "-buffersize")) { - int newBufferSize; + Tcl_WideInt newBufferSize; + Tcl_Obj obj; + int code; - if (Tcl_GetInt(interp, newValue, &newBufferSize) == TCL_ERROR) { + 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 = NULL; + encoding = Tcl_GetEncoding(NULL, "iso8859-1"); + ENCODING_PROFILE_SET(statePtr->inputEncodingFlags + ,ENCODING_PROFILE_GET(statePtr->inputEncodingFlags) + |TCL_ENCODING_PROFILE_STRICT); + ENCODING_PROFILE_SET(statePtr->outputEncodingFlags + ,ENCODING_PROFILE_GET(statePtr->outputEncodingFlags) + |TCL_ENCODING_PROFILE_STRICT); } else { encoding = Tcl_GetEncoding(interp, newValue); if (encoding == NULL) { return TCL_ERROR; } @@ -8031,57 +8183,42 @@ /* * When the channel has an escape sequence driven encoding such as * iso2022, the terminated escape sequence must write to the buffer. */ - if ((statePtr->encoding != NULL) + if ((statePtr->encoding != GetBinaryEncoding()) && !(statePtr->outputEncodingFlags & TCL_ENCODING_START) && (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) { statePtr->outputEncodingFlags |= TCL_ENCODING_END; WriteChars(chanPtr, "", 0); } Tcl_FreeEncoding(statePtr->encoding); statePtr->encoding = encoding; statePtr->inputEncodingState = NULL; + profile = ENCODING_PROFILE_GET(statePtr->inputEncodingFlags); statePtr->inputEncodingFlags = TCL_ENCODING_START; + ENCODING_PROFILE_SET(statePtr->inputEncodingFlags, profile); statePtr->outputEncodingState = NULL; statePtr->outputEncodingFlags = TCL_ENCODING_START; - ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA); + 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 (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 (!newValue[0] || (!(newValue[0] & 0x80) && (!newValue[1] +#ifndef TCL_NO_DEPRECATED + || !strcmp(newValue+1, " {}") +#endif + ))) { if (GotFlag(statePtr, TCL_READABLE)) { - statePtr->inEofChar = inValue; - } - if (GotFlag(statePtr, TCL_WRITABLE)) { - statePtr->outEofChar = outValue; + statePtr->inEofChar = newValue[0]; } } else { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "bad value for -eofchar: should be a list of zero," - " one, or two elements", -1)); + "bad value for -eofchar: must be non-NUL ASCII" + " character", TCL_INDEX_NONE)); } Tcl_Free((void *)argv); return TCL_ERROR; } if (argv != NULL) { @@ -8098,10 +8235,19 @@ 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; @@ -8132,11 +8278,17 @@ translation = TCL_TRANSLATE_AUTO; } else if (strcmp(readMode, "binary") == 0) { translation = TCL_TRANSLATE_LF; statePtr->inEofChar = 0; Tcl_FreeEncoding(statePtr->encoding); - statePtr->encoding = NULL; + statePtr->encoding = Tcl_GetEncoding(NULL, "iso8859-1"); + ENCODING_PROFILE_SET(statePtr->inputEncodingFlags + ,ENCODING_PROFILE_GET(statePtr->inputEncodingFlags) + |TCL_ENCODING_PROFILE_STRICT); + ENCODING_PROFILE_SET(statePtr->outputEncodingFlags + ,ENCODING_PROFILE_GET(statePtr->outputEncodingFlags) + |TCL_ENCODING_PROFILE_STRICT); } 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) { @@ -8179,14 +8331,19 @@ statePtr->outputTranslation = TCL_TRANSLATE_CRLF; } else { statePtr->outputTranslation = TCL_PLATFORM_TRANSLATION; } } else if (strcmp(writeMode, "binary") == 0) { - statePtr->outEofChar = 0; statePtr->outputTranslation = TCL_TRANSLATE_LF; Tcl_FreeEncoding(statePtr->encoding); - statePtr->encoding = NULL; + statePtr->encoding = Tcl_GetEncoding(NULL, "iso8859-1"); + ENCODING_PROFILE_SET(statePtr->inputEncodingFlags + ,ENCODING_PROFILE_GET(statePtr->inputEncodingFlags) + |TCL_ENCODING_PROFILE_STRICT); + ENCODING_PROFILE_SET(statePtr->outputEncodingFlags + ,ENCODING_PROFILE_GET(statePtr->outputEncodingFlags) + |TCL_ENCODING_PROFILE_STRICT); } 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) { @@ -8518,20 +8675,24 @@ */ mask &= ~TCL_EXCEPTION; if (!statePtr->timer) { + TclChannelPreserve((Tcl_Channel)chanPtr); + statePtr->timerChanPtr = chanPtr; statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, - ChannelTimerProc, chanPtr); + ChannelTimerProc, chanPtr); } } } if (!statePtr->timer && mask & TCL_WRITABLE && GotFlag(statePtr, CHANNEL_NONBLOCKING)) { + TclChannelPreserve((Tcl_Channel)chanPtr); + statePtr->timerChanPtr = chanPtr; statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc,chanPtr); } @@ -8555,47 +8716,82 @@ *---------------------------------------------------------------------- */ static void ChannelTimerProc( - ClientData clientData) + void *clientData) { Channel *chanPtr = (Channel *)clientData; + /* State info for channel */ ChannelState *statePtr = chanPtr->state; - /* State info for channel */ - Tcl_Preserve(statePtr); + /* 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; - 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); + statePtr->timerChanPtr = NULL; } /* *---------------------------------------------------------------------- * @@ -8625,11 +8821,11 @@ * conditions under which proc should be * called. Use 0 to disable a registered * handler. */ Tcl_ChannelProc *proc, /* Procedure to call for each selected * event. */ - ClientData clientData) /* Arbitrary data to pass to proc. */ + void *clientData) /* Arbitrary data to pass to proc. */ { ChannelHandler *chPtr; Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ @@ -8656,11 +8852,11 @@ statePtr->chPtr = chPtr; } /* * The remainder of the initialization below is done regardless of whether - * or not this is a new record or a modification of an old one. + * this is a new record or a modification of an old one. */ chPtr->mask = mask; /* @@ -8697,11 +8893,11 @@ void Tcl_DeleteChannelHandler( Tcl_Channel chan, /* The channel for which to remove the * callback. */ Tcl_ChannelProc *proc, /* The procedure in the callback to delete. */ - ClientData clientData) /* The client data in the callback to + void *clientData) /* The client data in the callback to * delete. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelHandler *chPtr, *prevChPtr; Channel *chanPtr = (Channel *) chan; @@ -8903,11 +9099,11 @@ *---------------------------------------------------------------------- */ void TclChannelEventScriptInvoker( - ClientData clientData, /* The script+interp record. */ + void *clientData, /* The script+interp record. */ TCL_UNUSED(int) /*mask*/) { EventScriptRecord *esPtr = (EventScriptRecord *)clientData; /* The event script + interpreter to eval it * in. */ @@ -8971,11 +9167,11 @@ *---------------------------------------------------------------------- */ int Tcl_FileEventObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter in which the channel for which * to create the handler is found. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { @@ -9003,11 +9199,11 @@ if (chan == NULL) { return TCL_ERROR; } chanPtr = (Channel *) chan; statePtr = chanPtr->state; - if ((statePtr->flags & mask) == 0) { + if (GotFlag(statePtr, mask) == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("channel is not %s", (mask == TCL_READABLE) ? "readable" : "writable")); return TCL_ERROR; } @@ -9065,11 +9261,11 @@ *---------------------------------------------------------------------- */ static void ZeroTransferTimerProc( - ClientData clientData) + void *clientData) { /* calling CopyData with mask==0 still implies immediate invocation of the * -command callback, and completion of the fcopy. */ CopyData((CopyState *)clientData, 0); @@ -9099,11 +9295,11 @@ int TclCopyChannel( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Channel inChan, /* Channel to read from. */ Tcl_Channel outChan, /* Channel to write to. */ - Tcl_WideInt toRead, /* Amount of data to copy, or -1 for all. */ + long long toRead, /* Amount of data to copy, or -1 for all. */ Tcl_Obj *cmdPtr) /* Pointer to script to execute or NULL. */ { Channel *inPtr = (Channel *) inChan; Channel *outPtr = (Channel *) outChan; ChannelState *inStatePtr, *outStatePtr; @@ -9156,31 +9352,22 @@ /* * 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; + 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(sizeof(CopyState) + !moveBytes * inStatePtr->bufSize); + csPtr = (CopyState *)Tcl_Alloc(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize); csPtr->bufSize = !moveBytes * inStatePtr->bufSize; csPtr->readPtr = inPtr; csPtr->writePtr = outPtr; csPtr->readFlags = readFlags; csPtr->writeFlags = writeFlags; @@ -9287,11 +9474,11 @@ } } static void MBEvent( - ClientData clientData, + void *clientData, int mask) { CopyState *csPtr = (CopyState *) clientData; Tcl_Channel inChan = (Tcl_Channel) csPtr->readPtr; Tcl_Channel outChan = (Tcl_Channel) csPtr->writePtr; @@ -9366,17 +9553,17 @@ } if (bufPtr) { /* Split the overflowing buffer in two */ int extra = (int) (inBytes - csPtr->toRead); - /* Note that going with int for extra assumes that inBytes is not too - * much over toRead to require a wide itself. If that gets violated - * then the calculations involving extra must be made wide too. - * - * Noted with Win32/MSVC debug build treating the warning (possible of - * data in __int64 to int conversion) as error. - */ + /* Note that going with int for extra assumes that inBytes is not too + * much over toRead to require a wide itself. If that gets violated + * then the calculations involving extra must be made wide too. + * + * Noted with Win32/MSVC debug build treating the warning (possible of + * data in long long to int conversion) as error. + */ bufPtr = AllocChannelBuffer(extra); tail->nextAdded -= extra; memcpy(InsertPoint(bufPtr), InsertPoint(tail), extra); @@ -9470,16 +9657,16 @@ { Tcl_Interp *interp; Tcl_Obj *cmdPtr, *errObj = NULL, *bufObj = NULL, *msg = NULL; Tcl_Channel inChan, outChan; ChannelState *inStatePtr, *outStatePtr; - int result = TCL_OK, size; - size_t sizeb; + int result = TCL_OK; + Tcl_Size sizeb; Tcl_WideInt total; + Tcl_WideInt size; const char *buffer; - int inBinary, outBinary, sameEncoding; - /* Encoding control */ + int moveBytes; int underflow; /* Input underflow */ inChan = (Tcl_Channel) csPtr->readPtr; outChan = (Tcl_Channel) csPtr->writePtr; inStatePtr = csPtr->readPtr->state; @@ -9493,15 +9680,13 @@ * 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); + moveBytes = Lossless(inStatePtr, outStatePtr, csPtr->toRead); - if (!(inBinary || sameEncoding)) { + if (!moveBytes) { TclNewObj(bufObj); Tcl_IncrRefCount(bufObj); } while (csPtr->toRead != (Tcl_WideInt) 0) { @@ -9512,15 +9697,23 @@ 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)) { /* @@ -9530,41 +9723,42 @@ size = 0; underflow = 1; } else { /* - * Read up to bufSize bytes. + * Read up to bufSize characters. */ if ((csPtr->toRead == (Tcl_WideInt) -1) || (csPtr->toRead > (Tcl_WideInt) csPtr->bufSize)) { sizeb = csPtr->bufSize; } else { sizeb = csPtr->toRead; } - if (inBinary || sameEncoding) { + if (moveBytes) { size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb, !GotFlag(inStatePtr, CHANNEL_NONBLOCKING)); } else { size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb, - 0 /* No append */); + !GotFlag(inStatePtr, CHANNEL_NONBLOCKING) + ,0 /* No append */); } - underflow = (size >= 0) && ((size_t)size < sizeb); /* Input underflow */ + underflow = (size >= 0) && (size < sizeb); /* Input underflow */ } if (size < 0) { readError: if (interp) { TclNewObj(errObj); Tcl_AppendStringsToObj(errObj, "error reading \"", - Tcl_GetChannelName(inChan), "\": ", NULL); + Tcl_GetChannelName(inChan), "\": ", (void *)NULL); if (msg != NULL) { Tcl_AppendObjToObj(errObj, msg); } else { Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp), - NULL); + (void *)NULL); } } if (msg != NULL) { Tcl_DecrRefCount(msg); } @@ -9606,59 +9800,54 @@ /* * 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 { + if (moveBytes) { + buffer = csPtr->buffer; + sizeb = WriteBytes(outStatePtr->topChanPtr, buffer, size); + } else { + buffer = Tcl_GetStringFromObj(bufObj, &sizeb); sizeb = WriteChars(outStatePtr->topChanPtr, buffer, sizeb); } /* * [Bug 2895565]. At this point 'size' still contains the number of - * bytes or characters which have been read. We keep this to later to + * characters which have been read. We keep this to later to * update the totals and toRead information, see marker (UP) below. We * must not overwrite it with 'sizeb', which is the number of written - * bytes or characters, and both EOL translation and encoding + * characters, and both EOL translation and encoding * conversion may have changed this number unpredictably in relation * to 'size' (It can be smaller or larger, in the latter case able to * drive toRead below -1, causing infinite looping). Completely * unsuitable for updating totals and toRead. */ - if (sizeb == TCL_INDEX_NONE) { + if (sizeb < 0) { writeError: if (interp) { TclNewObj(errObj); Tcl_AppendStringsToObj(errObj, "error writing \"", - Tcl_GetChannelName(outChan), "\": ", NULL); + Tcl_GetChannelName(outChan), "\": ", (void *)NULL); if (msg != NULL) { Tcl_AppendObjToObj(errObj, msg); } else { Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp), - NULL); + (void *)NULL); } } if (msg != NULL) { Tcl_DecrRefCount(msg); } break; } /* - * Update the current byte count. Do it now so the count is valid + * Update the current character count. Do it now so the count is valid * before a return or break takes us out of the loop. The invariant at * the top of the loop should be that csPtr->toRead holds the number - * of bytes left to copy. + * of characters left to copy. */ if (csPtr->toRead != -1) { csPtr->toRead -= size; } @@ -9721,12 +9910,12 @@ TclDecrRefCount(bufObj); bufObj = NULL; } /* - * Make the callback or return the number of bytes transferred. The local - * total is used because StopCopy frees csPtr. + * Make the callback or return the number of characters transferred. The + * local total is used because StopCopy frees csPtr. */ total = csPtr->total; if (cmdPtr && interp) { int code; @@ -9778,32 +9967,32 @@ * 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 + * 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 -1) + * - a channel reading error occurs (and we return TCL_INDEX_NONE) * * Side effects: * May cause input to be buffered. * *---------------------------------------------------------------------- */ -static int +static Tcl_Size DoRead( Channel *chanPtr, /* The channel from which to read. */ char *dst, /* Where to store input read. */ - size_t bytesToRead, /* Maximum number of bytes to read. */ + Tcl_Size bytesToRead, /* Maximum number of bytes to read. */ int allowShortReads) /* Allow half-blocking (pipes,sockets) */ { ChannelState *statePtr = chanPtr->state; char *p = dst; @@ -9817,10 +10006,15 @@ * 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)); @@ -9858,11 +10052,11 @@ * 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))) { + ((Tcl_Size) BytesLeft(bufPtr) < bytesToRead))) { /* Not enough bytes in it yet * to fill the dst */ int code; moreData: @@ -9914,14 +10108,14 @@ if (bytesToRead == 0) { break; } /* - * 1) We're @EOF because we saw eof char. + * 1) We're @EOF because we saw eof char, or there was an encoding error. */ - if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) { + if (GotFlag(statePtr, CHANNEL_STICKY_EOF|CHANNEL_ENCODING_ERROR)) { break; } /* * 2) The buffer holds a \r while in CRLF translation, followed by @@ -9935,19 +10129,19 @@ if (bufPtr->nextPtr == NULL) { /* * There's no more buffered data... */ - if (statePtr->flags & CHANNEL_EOF) { + if (GotFlag(statePtr, CHANNEL_EOF)) { /* * ...and there never will be. */ *p++ = '\r'; bytesToRead--; bufPtr->nextRemoved++; - } else if (statePtr->flags & CHANNEL_BLOCKED) { + } else if (GotFlag(statePtr, CHANNEL_BLOCKED)) { /* * ...and we cannot get more now. */ SetFlag(statePtr, CHANNEL_NEED_MORE_DATA); @@ -10002,16 +10196,17 @@ 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 (int)(p - dst); + return (Tcl_Size)(p - dst); } /* *---------------------------------------------------------------------- * @@ -10030,15 +10225,55 @@ *---------------------------------------------------------------------- */ static void CopyEventProc( - ClientData clientData, + void *clientData, int mask) { (void) CopyData((CopyState *)clientData, mask); } + +/* + *---------------------------------------------------------------------- + * + * Lossless -- + * + * Determines whether copying characters between two channel states would + * be lossless, i.e. whether one byte corresponds to one character, every + * character appears in the Unicode character set, there are no + * translations to be performed, and no inline signals to respond to. + * + * Result: + * True if copying would be lossless. + * + *---------------------------------------------------------------------- + */ +int +Lossless( + ChannelState *inStatePtr, + ChannelState *outStatePtr, + long long toRead) +{ + return inStatePtr->inEofChar == '\0' /* No eofChar to stop input */ + && inStatePtr->inputTranslation == TCL_TRANSLATE_LF + && outStatePtr->outputTranslation == TCL_TRANSLATE_LF + && ( + ( + inStatePtr->encoding == GetBinaryEncoding() + && + outStatePtr->encoding == GetBinaryEncoding() + ) + || + ( + toRead == -1 + && inStatePtr->encoding == outStatePtr->encoding + && ENCODING_PROFILE_GET(inStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8 + && ENCODING_PROFILE_GET(outStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8 + ) + ); +} /* *---------------------------------------------------------------------- * * StopCopy -- @@ -10076,24 +10311,24 @@ /* * Restore the old blocking mode and output buffering mode. */ nonBlocking = csPtr->readFlags & CHANNEL_NONBLOCKING; - if (nonBlocking != (inStatePtr->flags & CHANNEL_NONBLOCKING)) { + if (nonBlocking != GotFlag(inStatePtr, CHANNEL_NONBLOCKING)) { SetBlockMode(NULL, csPtr->readPtr, nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); } if (csPtr->readPtr != csPtr->writePtr) { nonBlocking = csPtr->writeFlags & CHANNEL_NONBLOCKING; - if (nonBlocking != (outStatePtr->flags & CHANNEL_NONBLOCKING)) { + if (nonBlocking != GotFlag(outStatePtr, CHANNEL_NONBLOCKING)) { SetBlockMode(NULL, csPtr->writePtr, nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); } } ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED); - outStatePtr->flags |= - csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED); + SetFlag(outStatePtr, + csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED)); if (csPtr->cmdPtr) { Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr); if (inChan != outChan) { Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr); @@ -10404,11 +10639,11 @@ Tcl_Channel chan) /* The channel to query */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ - return ((statePtr->refCount + 1 > 2) ? 1 : 0); + return ((statePtr->refCount > 1) ? 1 : 0); } /* *---------------------------------------------------------------------- * @@ -10814,19 +11049,21 @@ Tcl_SetChannelErrorInterp( Tcl_Interp *interp, /* Interp to store the data into. */ Tcl_Obj *msg) /* Error message to store. */ { Interp *iPtr = (Interp *) interp; - - if (iPtr->chanMsg != NULL) { - TclDecrRefCount(iPtr->chanMsg); - iPtr->chanMsg = NULL; - } + Tcl_Obj *disposePtr = iPtr->chanMsg; if (msg != NULL) { iPtr->chanMsg = FixLevelCode(msg); Tcl_IncrRefCount(iPtr->chanMsg); + } else { + iPtr->chanMsg = NULL; + } + + if (disposePtr != NULL) { + TclDecrRefCount(disposePtr); } return; } /* @@ -10850,19 +11087,21 @@ 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; - } + 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; } /* @@ -10886,11 +11125,12 @@ static Tcl_Obj * FixLevelCode( Tcl_Obj *msg) { - int explicitResult, numOptions, lc, lcn; + int explicitResult, numOptions, lcn; + Tcl_Size lc; Tcl_Obj **lv, **lvn; int res, i, j, val, lignore, cignore; int newlevel = -1, newcode = -1; /* ASSERT msg != NULL */ @@ -10899,15 +11139,15 @@ * Process the caught message. * * Syntax = (option value)... ?message? * * Bad message syntax causes a panic, because the other side uses - * Tcl_GetReturnOptions and list construction functions to marshall the + * Tcl_GetReturnOptions and list construction functions to marshal the * information. Hence an error means that we've got serious breakage. */ - res = Tcl_ListObjGetElements(NULL, msg, &lc, &lv); + res = TclListObjGetElementsM(NULL, msg, &lc, &lv); if (res != TCL_OK) { Tcl_Panic("Tcl_SetChannelError: bad syntax of message"); } explicitResult = (1 == (lc % 2)); @@ -10968,12 +11208,12 @@ } lvn = (Tcl_Obj **)Tcl_Alloc(lcn * sizeof(Tcl_Obj *)); /* - * New level/code information is spliced into the first occurence of - * -level, -code, further occurences are ignored. The options cannot be + * New level/code information is spliced into the first occurrence of + * -level, -code, further occurrences are ignored. The options cannot be * not present, we would not come here. Options which are ok are simply * copied over. */ lignore = cignore = 0; @@ -11106,11 +11346,11 @@ } /* *---------------------------------------------------------------------- * - * DupChannelIntRep -- + * DupChannelInternalRep -- * * Initialize the internal representation of a new Tcl_Obj to a copy of * the internal representation of an existing string object. * * Results: @@ -11122,27 +11362,27 @@ * *---------------------------------------------------------------------- */ static void -DupChannelIntRep( +DupChannelInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. Must have * an internal rep of type "Channel". */ Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not * currently have an internal rep.*/ { ResolvedChanName *resPtr; - ChanGetIntRep(srcPtr, resPtr); + ChanGetInternalRep(srcPtr, resPtr); assert(resPtr); - ChanSetIntRep(copyPtr, resPtr); + ChanSetInternalRep(copyPtr, resPtr); } /* *---------------------------------------------------------------------- * - * FreeChannelIntRep -- + * FreeChannelInternalRep -- * * Release statePtr storage. * * Results: * None. @@ -11152,16 +11392,16 @@ * *---------------------------------------------------------------------- */ static void -FreeChannelIntRep( +FreeChannelInternalRep( Tcl_Obj *objPtr) /* Object with internal rep to free. */ { ResolvedChanName *resPtr; - ChanGetIntRep(objPtr, resPtr); + ChanGetInternalRep(objPtr, resPtr); assert(resPtr); if (resPtr->refCount-- > 1) { return; } Tcl_Release(resPtr->statePtr); @@ -11177,12 +11417,12 @@ static int DumpFlags( char *str, int flags) { - char buf[20]; int i = 0; + char buf[24]; #define ChanFlag(chr, bit) (buf[i++] = ((flags & (bit)) ? (chr) : '_')) ChanFlag('r', TCL_READABLE); ChanFlag('w', TCL_WRITABLE); @@ -11191,10 +11431,11 @@ 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); Index: generic/tclIO.h ================================================================== --- generic/tclIO.h +++ generic/tclIO.h @@ -34,20 +34,20 @@ * * Buffers data being sent to or from a channel. */ typedef struct ChannelBuffer { - size_t refCount; /* Current uses count */ - int nextAdded; /* The next position into which a character + Tcl_Size refCount; /* Current uses count */ + Tcl_Size nextAdded; /* The next position into which a character * will be put in the buffer. */ - int nextRemoved; /* Position of next byte to be removed from + Tcl_Size nextRemoved; /* Position of next byte to be removed from * the buffer. */ - int bufLength; /* How big is the buffer? */ + Tcl_Size bufLength; /* How big is the buffer? */ struct ChannelBuffer *nextPtr; /* Next buffer in chain. */ char buf[TCLFLEXARRAY]; /* Placeholder for real buffer. The real - * buffer occuppies this space + bufSize-1 + * buffer occupies this space + bufSize-1 * bytes. This must be the last field in the * structure. */ } ChannelBuffer; #define CHANNELBUFFER_HEADER_SIZE offsetof(ChannelBuffer, buf) @@ -111,11 +111,11 @@ */ ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */ ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */ - size_t refCount; + Tcl_Size refCount; } Channel; /* * struct ChannelState: * @@ -127,11 +127,11 @@ typedef struct ChannelState { char *channelName; /* The name of the channel instance in Tcl * commands. Storage is owned by the generic * IO code, is dynamically allocated. */ - int flags; /* ORed combination of the flags defined + int flags; /* OR'ed combination of the flags defined * below. */ Tcl_Encoding encoding; /* Encoding to apply when reading or writing * data on this channel. NULL means no * encoding is applied to data. */ Tcl_EncodingState inputEncodingState; @@ -156,16 +156,18 @@ TclEolTranslation outputTranslation; /* What translation to use for generating end * of line sequences in output? */ int inEofChar; /* If nonzero, use this as a signal of EOF on * input. */ +#if TCL_MAJOR_VERSION < 9 int outEofChar; /* If nonzero, append this to the channel when - * it is closed if it is open for writing. */ + * it is closed if it is open for writing. For Tcl 8.x only */ +#endif int unreportedError; /* Non-zero if an error report was deferred * because it happened in the background. The * value is the POSIX error code. */ - size_t refCount; /* How many interpreters hold references to + Tcl_Size refCount; /* How many interpreters hold references to * this IO channel? */ struct CloseCallback *closeCbPtr; /* Callbacks registered to be called when the * channel is closed. */ char *outputStage; /* Temporary staging buffer used when @@ -184,12 +186,15 @@ int interestMask; /* Mask of all events this channel has * handlers for. */ EventScriptRecord *scriptRecordPtr; /* Chain of all scripts registered for event * handlers ("fileevent") on this channel. */ - int bufSize; /* What size buffers to allocate? */ + Tcl_Size bufSize; /* What size buffers to allocate? */ Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */ + Channel *timerChanPtr; /* Needed in order to decrement the refCount of + the right channel when the timer is + deleted. */ struct CopyState *csPtrR; /* State of background copy for which channel * is input, or NULL. */ struct CopyState *csPtrW; /* State of background copy for which channel * is output, or NULL. */ Channel *topChanPtr; /* Refers to topmost channel in a stack. Never @@ -204,35 +209,33 @@ /* * TIP #219 ... Info for the I/O system ... * Error message set by channel drivers, for the propagation of arbitrary * Tcl errors. This information, if present (chanMsg not NULL), takes - * precedence over a posix error code returned by a channel operation. + * precedence over a Posix error code returned by a channel operation. */ Tcl_Obj* chanMsg; Tcl_Obj* unreportedMsg; /* Non-NULL if an error report was deferred * 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 ORed combination of the + * Values for the flags field in Channel. Any OR'ed combination of the * following flags can be stored in the field. These flags record various * options and state bits about the channel. In addition to the flags below, * the channel can also have TCL_READABLE (1<<1) and TCL_WRITABLE (1<<2) set. */ -#define CHANNEL_NONBLOCKING (1<<3) /* Channel is currently in nonblocking +#define CHANNEL_NONBLOCKING (1<<6) /* Channel is currently in nonblocking * mode. */ -#define CHANNEL_LINEBUFFERED (1<<4) /* Output to the channel must be - * flushed after every newline. */ -#define CHANNEL_UNBUFFERED (1<<5) /* Output to the channel must always - * be flushed immediately. */ #define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the queued * output buffers has been * scheduled. */ #define CHANNEL_CLOSED (1<<8) /* Channel has been closed. No further * Tcl-level IO on the channel is @@ -267,13 +270,18 @@ * 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. */ Index: generic/tclIOCmd.c ================================================================== --- generic/tclIOCmd.c +++ generic/tclIOCmd.c @@ -1,17 +1,18 @@ /* * tclIOCmd.c -- * * Contains the definitions of most of the Tcl commands relating to IO. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright © 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" +#include "tclTomMath.h" /* * Callback structure for accept callback in a TCP server. */ @@ -42,11 +43,11 @@ static Tcl_ObjCmdProc ChanTruncateObjCmd; static void RegisterTcpServerInterpCleanup( Tcl_Interp *interp, AcceptCallback *acceptCallbackPtr); static Tcl_InterpDeleteProc TcpAcceptCallbacksDeleteProc; -static void TcpServerCloseProc(ClientData callbackData); +static void TcpServerCloseProc(void *callbackData); static void UnregisterTcpServerInterpCleanupProc( Tcl_Interp *interp, AcceptCallback *acceptCallbackPtr); /* @@ -65,11 +66,11 @@ *---------------------------------------------------------------------- */ static void FinalizeIOCmdTSD( - TCL_UNUSED(ClientData)) + TCL_UNUSED(void *)) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->stdoutObjPtr != NULL) { Tcl_DecrRefCount(tsdPtr->stdoutObjPtr); @@ -95,20 +96,20 @@ *---------------------------------------------------------------------- */ int Tcl_PutsObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to puts on. */ Tcl_Obj *string; /* String to write. */ Tcl_Obj *chanObjPtr = NULL; /* channel object. */ int newline; /* Add a newline at end? */ - int result; /* Result of puts operation. */ + Tcl_Size result; /* Result of puts operation. */ int mode; /* Mode in which channel is opened. */ switch (objc) { case 2: /* [puts $x] */ string = objv[1]; @@ -161,16 +162,16 @@ return TCL_ERROR; } TclChannelPreserve(chan); result = Tcl_WriteObj(chan, string); - if (result == -1) { + if (result == TCL_INDEX_NONE) { goto error; } if (newline != 0) { result = Tcl_WriteChars(chan, "\n", 1); - if (result == -1) { + if (result == TCL_INDEX_NONE) { goto error; } } TclChannelRelease(chan); return TCL_OK; @@ -208,11 +209,11 @@ *---------------------------------------------------------------------- */ int Tcl_FlushObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *chanObjPtr; @@ -272,17 +273,17 @@ *---------------------------------------------------------------------- */ int Tcl_GetsObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to read from. */ - int lineLen; /* Length of line just read. */ + Tcl_Size lineLen; /* Length of line just read. */ int mode; /* Mode in which channel is opened. */ Tcl_Obj *linePtr, *chanObjPtr; int code = TCL_OK; if ((objc != 2) && (objc != 3)) { @@ -301,11 +302,11 @@ } TclChannelPreserve(chan); TclNewObj(linePtr); lineLen = Tcl_GetsObj(chan, linePtr); - if (lineLen < 0) { + if (lineLen == TCL_IO_FAILURE) { if (!Tcl_Eof(chan) && !Tcl_InputBlocked(chan)) { Tcl_DecrRefCount(linePtr); /* * TIP #219. @@ -320,19 +321,21 @@ TclGetString(chanObjPtr), Tcl_PosixError(interp))); } code = TCL_ERROR; goto done; } - lineLen = -1; + lineLen = TCL_IO_FAILURE; } if (objc == 3) { if (Tcl_ObjSetVar2(interp, objv[2], NULL, linePtr, TCL_LEAVE_ERR_MSG) == NULL) { code = TCL_ERROR; goto done; } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(lineLen)); + Tcl_Obj *lineLenObj; + TclNewIndexObj(lineLenObj, lineLen); + Tcl_SetObjResult(interp, lineLenObj); } else { Tcl_SetObjResult(interp, linePtr); } done: TclChannelRelease(chan); @@ -356,19 +359,19 @@ *---------------------------------------------------------------------- */ int Tcl_ReadObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to read from. */ int newline, i; /* Discard newline at end? */ - int toRead; /* How many bytes to read? */ - int charactersRead; /* How many characters were read? */ + Tcl_WideInt toRead; /* How many bytes to read? */ + Tcl_Size charactersRead; /* How many characters were read? */ int mode; /* Mode in which channel is opened. */ Tcl_Obj *resultPtr, *chanObjPtr; if ((objc != 2) && (objc != 3)) { Interp *iPtr; @@ -414,25 +417,25 @@ * Compute how many bytes to read. */ toRead = -1; if (i < objc) { - if ((TclGetIntFromObj(interp, objv[i], &toRead) != TCL_OK) + if ((TclGetWideIntFromObj(NULL, objv[i], &toRead) != TCL_OK) || (toRead < 0)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected non-negative integer but got \"%s\"", TclGetString(objv[i]))); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", (void *)NULL); return TCL_ERROR; } } TclNewObj(resultPtr); - Tcl_IncrRefCount(resultPtr); TclChannelPreserve(chan); charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0); - if (charactersRead < 0) { + if (charactersRead == TCL_IO_FAILURE) { + Tcl_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. @@ -442,30 +445,28 @@ 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; + Tcl_Size length; - result = TclGetStringFromObj(resultPtr, &length); + result = Tcl_GetStringFromObj(resultPtr, &length); if (result[length - 1] == '\n') { Tcl_SetObjLength(resultPtr, length - 1); } } Tcl_SetObjResult(interp, resultPtr); TclChannelRelease(chan); - Tcl_DecrRefCount(resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -485,11 +486,11 @@ *---------------------------------------------------------------------- */ int Tcl_SeekObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to tell on. */ @@ -560,11 +561,11 @@ *---------------------------------------------------------------------- */ int Tcl_TellObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to tell on. */ @@ -622,11 +623,11 @@ *---------------------------------------------------------------------- */ int Tcl_CloseObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to close. */ @@ -695,17 +696,17 @@ * a terminating newline. */ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); const char *string; - size_t len; + Tcl_Size len; if (Tcl_IsShared(resultPtr)) { resultPtr = Tcl_DuplicateObj(resultPtr); Tcl_SetObjResult(interp, resultPtr); } - string = TclGetStringFromObj(resultPtr, &len); + string = Tcl_GetStringFromObj(resultPtr, &len); if ((len > 0) && (string[len - 1] == '\n')) { Tcl_SetObjLength(resultPtr, len - 1); } return TCL_ERROR; } @@ -730,11 +731,11 @@ *---------------------------------------------------------------------- */ int Tcl_FconfigureObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *optionName, *valueName; @@ -805,11 +806,11 @@ *--------------------------------------------------------------------------- */ int Tcl_EofObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; @@ -844,11 +845,11 @@ *---------------------------------------------------------------------- */ int Tcl_ExecObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *resultPtr; @@ -855,11 +856,11 @@ const char **argv; /* An array for the string arguments. Stored * on the _Tcl_ stack. */ const char *string; Tcl_Channel chan; int argc, background, i, index, keepNewline, result, skip, ignoreStderr; - size_t length; + Tcl_Size length; static const char *const options[] = { "-ignorestderr", "-keepnewline", "--", NULL }; enum execOptionsEnum { EXEC_IGNORESTDERR, EXEC_KEEPNEWLINE, EXEC_LAST @@ -981,11 +982,11 @@ * If the last character of the result is a newline, then remove the * newline character. */ if (keepNewline == 0) { - string = TclGetStringFromObj(resultPtr, &length); + string = Tcl_GetStringFromObj(resultPtr, &length); if ((length > 0) && (string[length - 1] == '\n')) { Tcl_SetObjLength(resultPtr, length - 1); } } Tcl_SetObjResult(interp, resultPtr); @@ -1004,18 +1005,18 @@ * Results: * A standard Tcl result. * * Side effects: * Sets interp's result to boolean true or false depending on whether the - * preceeding input operation on the channel would have blocked. + * preceding input operation on the channel would have blocked. * *--------------------------------------------------------------------------- */ int Tcl_FblockedObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; @@ -1057,11 +1058,11 @@ *---------------------------------------------------------------------- */ int Tcl_OpenObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int pipeline, prot; @@ -1115,11 +1116,12 @@ */ if (!pipeline) { chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot); } else { - int mode, seekFlag, cmdObjc, binary; + int mode, seekFlag, binary; + Tcl_Size cmdObjc; const char **cmdArgv; if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) { return TCL_ERROR; } @@ -1180,11 +1182,11 @@ *---------------------------------------------------------------------- */ static void TcpAcceptCallbacksDeleteProc( - ClientData clientData, /* Data which was passed when the assocdata + void *clientData, /* Data which was passed when the assocdata * was registered. */ TCL_UNUSED(Tcl_Interp *)) { Tcl_HashTable *hTblPtr = (Tcl_HashTable *)clientData; Tcl_HashEntry *hPtr; @@ -1283,11 +1285,11 @@ hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL); if (hTblPtr == NULL) { return; } - hPtr = Tcl_FindHashEntry(hTblPtr, (char *) acceptCallbackPtr); + hPtr = Tcl_FindHashEntry(hTblPtr, acceptCallbackPtr); if (hPtr != NULL) { Tcl_DeleteHashEntry(hPtr); } } @@ -1308,11 +1310,11 @@ *---------------------------------------------------------------------- */ static void AcceptCallbackProc( - ClientData callbackData, /* The data stored when the callback was + void *callbackData, /* The data stored when the callback was * created in the call to * Tcl_OpenTcpServer. */ Tcl_Channel chan, /* Channel for the newly accepted * connection. */ char *address, /* Address of client that was accepted. */ @@ -1399,11 +1401,11 @@ *---------------------------------------------------------------------- */ static void TcpServerCloseProc( - ClientData callbackData) /* The data passed in the call to + void *callbackData) /* The data passed in the call to * Tcl_CreateCloseHandler. */ { AcceptCallback *acceptCallbackPtr = (AcceptCallback *)callbackData; /* The actual data. */ @@ -1432,33 +1434,31 @@ *---------------------------------------------------------------------- */ int Tcl_SocketObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const socketOptions[] = { - "-async", "-myaddr", "-myport", "-reuseaddr", "-reuseport", "-server", - NULL + "-async", "-backlog", "-myaddr", "-myport", "-reuseaddr", + "-reuseport", "-server", NULL }; enum socketOptionsEnum { - SKT_ASYNC, SKT_MYADDR, SKT_MYPORT, SKT_REUSEADDR, SKT_REUSEPORT, - SKT_SERVER - }; - int optionIndex, a, server = 0, myport = 0, async = 0, reusep = -1, - reusea = -1; + SKT_ASYNC, SKT_BACKLOG, SKT_MYADDR, SKT_MYPORT, SKT_REUSEADDR, + SKT_REUSEPORT, SKT_SERVER + } optionIndex; + int a, server = 0, myport = 0, async = 0, reusep = -1, + reusea = -1, backlog = -1; unsigned int flags = 0; const char *host, *port, *myaddr = NULL; Tcl_Obj *script = NULL; Tcl_Channel chan; - if (TclpHasSockets(interp) != TCL_OK) { - return TCL_ERROR; - } + TclInitSockets(); for (a = 1; a < objc; a++) { const char *arg = TclGetString(objv[a]); if (arg[0] != '-') { @@ -1466,11 +1466,11 @@ } if (Tcl_GetIndexFromObj(interp, objv[a], socketOptions, "option", TCL_EXACT, &optionIndex) != TCL_OK) { return TCL_ERROR; } - switch ((enum socketOptionsEnum) optionIndex) { + switch (optionIndex) { case SKT_ASYNC: if (server == 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot set -async option for server sockets", -1)); return TCL_ERROR; @@ -1535,10 +1535,21 @@ 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"); } } @@ -1556,22 +1567,22 @@ Interp *iPtr; wrongNumArgs: iPtr = (Interp *) interp; Tcl_WrongNumArgs(interp, 1, objv, - "?-myaddr addr? ?-myport myport? ?-async? host port"); + "?-async? ?-myaddr addr? ?-myport myport? host port"); iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS; Tcl_WrongNumArgs(interp, 1, objv, - "-server command ?-reuseaddr boolean? ?-reuseport boolean? " - "?-myaddr addr? port"); + "-server command ?-backlog count? ?-myaddr addr? " + "?-reuseaddr boolean? ?-reuseport boolean? port"); return TCL_ERROR; } - if (!server && (reusea != -1 || reusep != -1)) { + if (!server && (reusea != -1 || reusep != -1 || backlog != -1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "options -reuseaddr and -reuseport are only valid for servers", - -1)); + "options -backlog, -reuseaddr, and -reuseport are only valid " + "for servers", -1)); return TCL_ERROR; } /* * Set the options to their default value if the user didn't override @@ -1612,11 +1623,11 @@ Tcl_IncrRefCount(script); acceptCallbackPtr->script = script; acceptCallbackPtr->interp = interp; - chan = Tcl_OpenTcpServerEx(interp, port, host, flags, + chan = Tcl_OpenTcpServerEx(interp, port, host, flags, backlog, AcceptCallbackProc, acceptCallbackPtr); if (chan == NULL) { Tcl_DecrRefCount(script); Tcl_Free(acceptCallbackPtr); return TCL_ERROR; @@ -1674,11 +1685,11 @@ *---------------------------------------------------------------------- */ int Tcl_FcopyObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel inChan, outChan; @@ -1769,19 +1780,19 @@ *--------------------------------------------------------------------------- */ static int ChanPendingObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; - int index, mode; static const char *const options[] = {"input", "output", NULL}; - enum pendingOptionsEnum {PENDING_INPUT, PENDING_OUTPUT}; + enum pendingOptionsEnum {PENDING_INPUT, PENDING_OUTPUT} index; + int mode; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "mode channelId"); return TCL_ERROR; } @@ -1793,11 +1804,11 @@ if (TclGetChannelFromObj(interp, objv[2], &chan, &mode, 0) != TCL_OK) { return TCL_ERROR; } - switch ((enum pendingOptionsEnum) index) { + switch (index) { case PENDING_INPUT: if (!(mode & TCL_READABLE)) { Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-1)); } else { Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_InputBuffered(chan))); @@ -1831,11 +1842,11 @@ *---------------------------------------------------------------------- */ static int ChanTruncateObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; @@ -1904,11 +1915,11 @@ *---------------------------------------------------------------------- */ static int ChanPipeObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel rchan, wchan; @@ -1955,11 +1966,11 @@ *---------------------------------------------------------------------- */ int TclChannelNamesCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc < 1 || objc > 2) { Index: generic/tclIOGT.c ================================================================== --- generic/tclIOGT.c +++ generic/tclIOGT.c @@ -2,12 +2,12 @@ * tclIOGT.c -- * * Implements a generic transformation exposing the underlying API at the * script level. Contributed by Andreas Kupries. * - * Copyright (c) 2000 Ajuba Solutions - * Copyright (c) 1999-2000 Andreas Kupries (a.kupries@westend.com) + * Copyright © 2000 Ajuba Solutions + * Copyright © 1999-2000 Andreas Kupries (a.kupries@westend.com) * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -17,37 +17,37 @@ /* * Forward declarations of internal procedures. First the driver procedures of * the transformation. */ -static int TransformBlockModeProc(ClientData instanceData, +static int TransformBlockModeProc(void *instanceData, int mode); -static int TransformCloseProc(ClientData instanceData, +static int TransformCloseProc(void *instanceData, Tcl_Interp *interp, int flags); -static int TransformInputProc(ClientData instanceData, char *buf, +static int TransformInputProc(void *instanceData, char *buf, int toRead, int *errorCodePtr); -static int TransformOutputProc(ClientData instanceData, +static int TransformOutputProc(void *instanceData, const char *buf, int toWrite, int *errorCodePtr); -static int TransformSetOptionProc(ClientData instanceData, +static int TransformSetOptionProc(void *instanceData, Tcl_Interp *interp, const char *optionName, const char *value); -static int TransformGetOptionProc(ClientData instanceData, +static int TransformGetOptionProc(void *instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); -static void TransformWatchProc(ClientData instanceData, int mask); -static int TransformGetFileHandleProc(ClientData instanceData, - int direction, ClientData *handlePtr); -static int TransformNotifyProc(ClientData instanceData, int mask); -static Tcl_WideInt TransformWideSeekProc(ClientData instanceData, - Tcl_WideInt offset, int mode, int *errorCodePtr); +static void TransformWatchProc(void *instanceData, int mask); +static int TransformGetFileHandleProc(void *instanceData, + int direction, void **handlePtr); +static int TransformNotifyProc(void *instanceData, int mask); +static long long TransformWideSeekProc(void *instanceData, + long long offset, int mode, int *errorCodePtr); /* * Forward declarations of internal procedures. Secondly the procedures for * handling and generating fileeevents. */ -static void TransformChannelHandlerTimer(ClientData clientData); +static void TransformChannelHandlerTimer(void *clientData); /* * Forward declarations of internal procedures. Third, helper procedures * encapsulating essential tasks. */ @@ -102,11 +102,11 @@ typedef struct ResultBuffer ResultBuffer; static inline void ResultClear(ResultBuffer *r); static inline void ResultInit(ResultBuffer *r); static inline int ResultEmpty(ResultBuffer *r); -static inline int ResultCopy(ResultBuffer *r, unsigned char *buf, +static inline size_t ResultCopy(ResultBuffer *r, unsigned char *buf, size_t toRead); static inline void ResultAdd(ResultBuffer *r, unsigned char *buf, size_t toWrite); /* @@ -256,19 +256,19 @@ Tcl_Obj *cmdObjPtr) /* Script to use for transform. */ { Channel *chanPtr; /* The actual channel. */ ChannelState *statePtr; /* State info for channel. */ int mode; /* Read/write mode of the channel. */ - int objc; + Tcl_Size objc; TransformChannelData *dataPtr; Tcl_DString ds; if (chan == NULL) { return TCL_ERROR; } - if (TCL_OK != Tcl_ListObjLength(interp, cmdObjPtr, &objc)) { + if (TCL_OK != TclListObjLengthM(interp, cmdObjPtr, &objc)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("-command value is not a list", -1)); return TCL_ERROR; } @@ -373,11 +373,11 @@ int preserve) /* Flag. If true the procedure will preserve * the result state of all accessed * interpreters. */ { Tcl_Obj *resObj; /* See below, switch (transmit). */ - size_t resLen = 0; + Tcl_Size resLen = 0; unsigned char *resBuf; Tcl_InterpState state = NULL; int res = TCL_OK; Tcl_Obj *command = TclListObjCopy(NULL, dataPtr->command); Tcl_Interp *eval = dataPtr->interp; @@ -395,23 +395,28 @@ if (preserve == P_PRESERVE) { state = Tcl_SaveInterpState(eval, res); } Tcl_IncrRefCount(command); - Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1)); + res = Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1)); + if (res != TCL_OK) { + Tcl_DecrRefCount(command); + Tcl_Release(eval); + return res; + } /* * Use a byte-array to prevent the misinterpretation of binary data coming - * through as UTF while at the tcl level. + * through as Utf while at the tcl level. */ Tcl_ListObjAppendElement(NULL, command, Tcl_NewByteArrayObj(buf, bufLen)); /* * Step 2, execute the command at the global level of the interpreter used * to create the transformation. Destroy the command afterward. If an - * error occured and the current interpreter is defined and not equal to + * error occurred and the current interpreter is defined and not equal to * the interpreter for the callback, then copy the error message into * current interpreter. Don't copy if in preservation mode. */ res = Tcl_EvalObjEx(eval, command, TCL_EVAL_GLOBAL); @@ -438,29 +443,42 @@ case TRANSMIT_DOWN: if (dataPtr->self == NULL) { break; } resObj = Tcl_GetObjResult(eval); - resBuf = TclGetByteArrayFromObj(resObj, &resLen); - Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), (char *) resBuf, - resLen); - break; + resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); + if (resBuf) { + Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), + (char *) resBuf, resLen); + break; + } + goto nonBytes; case TRANSMIT_SELF: if (dataPtr->self == NULL) { break; } resObj = Tcl_GetObjResult(eval); - resBuf = TclGetByteArrayFromObj(resObj, &resLen); - Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen); - break; + resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); + if (resBuf) { + Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen); + break; + } + goto nonBytes; case TRANSMIT_IBUF: resObj = Tcl_GetObjResult(eval); - resBuf = TclGetByteArrayFromObj(resObj, &resLen); - ResultAdd(&dataPtr->result, resBuf, resLen); - break; + resBuf = Tcl_GetByteArrayFromObj(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. */ @@ -495,11 +513,11 @@ *---------------------------------------------------------------------- */ static int TransformBlockModeProc( - ClientData instanceData, /* State of transformation. */ + void *instanceData, /* State of transformation. */ int mode) /* New blocking mode. */ { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; if (mode == TCL_MODE_NONBLOCKING) { @@ -527,11 +545,11 @@ *---------------------------------------------------------------------- */ static int TransformCloseProc( - ClientData instanceData, + void *instanceData, Tcl_Interp *interp, int flags) { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; @@ -558,11 +576,11 @@ /* * Now flush data waiting in internal buffers to output and input. The * input must be done despite the fact that there is no real receiver for * it anymore. But the scripts might have sideeffects other parts of the - * system rely on (f.e. signaling the close to interested parties). + * system rely on (f.e. signalling the close to interested parties). */ PreserveData(dataPtr); if (dataPtr->mode & TCL_WRITABLE) { ExecuteCallback(dataPtr, interp, A_FLUSH_WRITE, NULL, 0, @@ -611,11 +629,11 @@ *---------------------------------------------------------------------- */ static int TransformInputProc( - ClientData instanceData, + void *instanceData, char *buf, int toRead, int *errorCodePtr) { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; @@ -778,11 +796,11 @@ *---------------------------------------------------------------------- */ static int TransformOutputProc( - ClientData instanceData, + void *instanceData, const char *buf, int toWrite, int *errorCodePtr) { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; @@ -828,23 +846,23 @@ * contains the POSIX error code if an error occurred, or zero. * *---------------------------------------------------------------------- */ -static Tcl_WideInt +static long long TransformWideSeekProc( - ClientData instanceData, /* The channel to manipulate. */ - Tcl_WideInt offset, /* Size of movement. */ + void *instanceData, /* The channel to manipulate. */ + long long offset, /* Size of movement. */ int mode, /* How to move. */ int *errorCodePtr) /* Location of error flag. */ { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self); const Tcl_ChannelType *parentType = Tcl_GetChannelType(parent); Tcl_DriverWideSeekProc *parentWideSeekProc = Tcl_ChannelWideSeekProc(parentType); - ClientData parentData = Tcl_GetChannelInstanceData(parent); + void *parentData = Tcl_GetChannelInstanceData(parent); if ((offset == 0) && (mode == SEEK_CUR)) { /* * This is no seek but a request to tell the caller the current * location. Simply pass the request down. @@ -908,11 +926,11 @@ *---------------------------------------------------------------------- */ static int TransformSetOptionProc( - ClientData instanceData, + void *instanceData, Tcl_Interp *interp, const char *optionName, const char *value) { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; @@ -946,11 +964,11 @@ *---------------------------------------------------------------------- */ static int TransformGetOptionProc( - ClientData instanceData, + void *instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr) { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; @@ -993,18 +1011,18 @@ *---------------------------------------------------------------------- */ static void TransformWatchProc( - ClientData instanceData, /* Channel to watch. */ + void *instanceData, /* Channel to watch. */ int mask) /* Events of interest. */ { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; Tcl_Channel downChan; /* - * The caller expressed interest in events occuring for this channel. We + * The caller expressed interest in events occurring for this channel. We * are forwarding the call to the underlying channel now. */ dataPtr->watchMask = mask; @@ -1071,13 +1089,13 @@ *---------------------------------------------------------------------- */ static int TransformGetFileHandleProc( - ClientData instanceData, /* Channel to query. */ + void *instanceData, /* Channel to query. */ int direction, /* Direction of interest. */ - ClientData *handlePtr) /* Place to store the handle into. */ + void **handlePtr) /* Place to store the handle into. */ { TransformChannelData *dataPtr = (TransformChannelData *)instanceData; /* * Return the handle belonging to parent channel. IOW, pass the request @@ -1105,18 +1123,18 @@ *---------------------------------------------------------------------- */ static int TransformNotifyProc( - ClientData clientData, /* The state of the notified + void *clientData, /* The state of the notified * transformation. */ - int mask) /* The mask of occuring events. */ + int mask) /* The mask of occurring events. */ { TransformChannelData *dataPtr = (TransformChannelData *)clientData; /* - * An event occured in the underlying channel. This transformation doesn't + * An event occurred in the underlying channel. This transformation doesn't * process such events thus returns the incoming mask unchanged. */ if (dataPtr->timer != NULL) { /* @@ -1150,11 +1168,11 @@ *---------------------------------------------------------------------- */ static void TransformChannelHandlerTimer( - ClientData clientData) /* Transformation to query. */ + void *clientData) /* Transformation to query. */ { TransformChannelData *dataPtr = (TransformChannelData *)clientData; dataPtr->timer = NULL; if (!(dataPtr->watchMask&TCL_READABLE) || ResultEmpty(&dataPtr->result)) { @@ -1202,11 +1220,11 @@ *---------------------------------------------------------------------- * * ResultInit -- * * Initializes the specified buffer structure. The structure will contain - * valid information for an emtpy buffer. + * valid information for an empty buffer. * * Side effects: * See above. * * Result: @@ -1264,17 +1282,17 @@ * The number of actually copied bytes, possibly less than 'toRead'. * *---------------------------------------------------------------------- */ -static inline int +static inline size_t ResultCopy( ResultBuffer *r, /* The buffer to read from. */ unsigned char *buf, /* The buffer to copy into. */ size_t toRead) /* Number of requested bytes. */ { - if (r->used == 0) { + if (ResultEmpty(r)) { /* * Nothing to copy in the case of an empty buffer. */ return 0; @@ -1327,11 +1345,11 @@ ResultAdd( ResultBuffer *r, /* The buffer to extend. */ unsigned char *buf, /* The buffer to read from. */ size_t toWrite) /* The number of bytes in 'buf'. */ { - if (r->used + toWrite > r->allocated) { + if ((r->used + toWrite + 1) > r->allocated) { /* * Extension of the internal buffer is required. */ if (r->allocated == 0) { Index: generic/tclIORChan.c ================================================================== --- generic/tclIORChan.c +++ generic/tclIORChan.c @@ -8,11 +8,11 @@ * Parts of this file are based on code contributed by Jean-Claude * Wippler. * * See TIP #219 for the specification of this functionality. * - * Copyright (c) 2004-2005 ActiveState, a divison of Sophos + * Copyright © 2004-2005 ActiveState, a division of Sophos * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -29,37 +29,38 @@ /* * Signatures of all functions used in the C layer of the reflection. */ -static int ReflectClose(ClientData clientData, +static int ReflectClose(void *clientData, Tcl_Interp *interp, int flags); -static int ReflectInput(ClientData clientData, char *buf, +static int ReflectInput(void *clientData, char *buf, int toRead, int *errorCodePtr); -static int ReflectOutput(ClientData clientData, const char *buf, +static int ReflectOutput(void *clientData, const char *buf, int toWrite, int *errorCodePtr); -static void ReflectWatch(ClientData clientData, int mask); -static int ReflectBlock(ClientData clientData, int mode); +static void ReflectWatch(void *clientData, int mask); +static int ReflectBlock(void *clientData, int mode); #if TCL_THREADS -static void ReflectThread(ClientData clientData, int action); +static void ReflectThread(void *clientData, int action); static int ReflectEventRun(Tcl_Event *ev, int flags); -static int ReflectEventDelete(Tcl_Event *ev, ClientData cd); +static int ReflectEventDelete(Tcl_Event *ev, void *cd); #endif -static Tcl_WideInt ReflectSeekWide(ClientData clientData, - Tcl_WideInt offset, int mode, int *errorCodePtr); -static int ReflectGetOption(ClientData clientData, +static long long ReflectSeekWide(void *clientData, + long long offset, int mode, int *errorCodePtr); +static int ReflectGetOption(void *clientData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); -static int ReflectSetOption(ClientData clientData, +static int ReflectSetOption(void *clientData, Tcl_Interp *interp, const char *optionName, const char *newValue); -static void TimerRunRead(ClientData clientData); -static void TimerRunWrite(ClientData clientData); +static int ReflectTruncate(void *clientData, + long long length); +static void TimerRunRead(void *clientData); +static void TimerRunWrite(void *clientData); /* - * The C layer channel type/driver definition used by the reflection. This is - * a version 3 structure. + * 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 */ @@ -69,21 +70,21 @@ 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 */ + 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 */ + ReflectTruncate /* Truncate. NULL'able */ }; /* * Instance data for a reflected channel. =========================== */ @@ -128,20 +129,20 @@ * * Most channel implementations need a timer in the C level to ensure that * data in buffers is flushed out through the generation of fake file * events. * - * See 'rechan', 'memchan', etc. + * See 'refchan', 'memchan', etc. * * 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 + * 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. * @@ -177,10 +178,11 @@ "configure", /* OPT */ "finalize", /* */ "initialize", /* */ "read", /* OPT */ "seek", /* OPT */ + "truncate", /* OPT */ "watch", /* */ "write", /* OPT */ NULL }; typedef enum { @@ -190,27 +192,29 @@ METH_CONFIGURE, METH_FINAL, METH_INIT, METH_READ, METH_SEEK, + METH_TRUNCATE, METH_WATCH, METH_WRITE } MethodName; #define FLAG(m) (1 << (m)) #define REQUIRED_METHODS \ (FLAG(METH_INIT) | FLAG(METH_FINAL) | FLAG(METH_WATCH)) #define NULLABLE_METHODS \ (FLAG(METH_BLOCKING) | FLAG(METH_SEEK) | \ - FLAG(METH_CONFIGURE) | FLAG(METH_CGET) | FLAG(METH_CGETALL)) + FLAG(METH_CONFIGURE) | FLAG(METH_CGET) | \ + FLAG(METH_CGETALL) | FLAG(METH_TRUNCATE)) #define RANDW \ (TCL_READABLE | TCL_WRITABLE) #define IMPLIES(a,b) ((!(a)) || (b)) #define NEGIMPL(a,b) -#define HAS(x,f) (x & FLAG(f)) +#define HAS(x,f) ((x) & FLAG(f)) #if TCL_THREADS /* * Thread specific types and structures. * @@ -229,11 +233,12 @@ ForwardedSeek, ForwardedWatch, ForwardedBlock, ForwardedSetOpt, ForwardedGetOpt, - ForwardedGetOptAll + ForwardedGetOptAll, + ForwardedTruncate } ForwardedOperation; /* * Event used to forward driver invocations to the thread actually managing * the channel. We cannot construct the command to execute and forward that. @@ -259,17 +264,17 @@ */ struct ForwardParamInput { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ char *buf; /* O: Where to store the read bytes */ - size_t toRead; /* I: #bytes to read, + Tcl_Size toRead; /* I: #bytes to read, * O: #bytes actually read */ }; struct ForwardParamOutput { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ const char *buf; /* I: Where the bytes to write come from */ - int toWrite; /* I: #bytes to write, + Tcl_Size toWrite; /* I: #bytes to write, * O: #bytes actually written */ }; struct ForwardParamSeek { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ int seekMode; /* I: How to seek */ @@ -292,10 +297,14 @@ 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. */ @@ -306,10 +315,11 @@ struct ForwardParamSeek seek; struct ForwardParamWatch watch; struct ForwardParamBlock block; struct ForwardParamSetOpt setOpt; struct ForwardParamGetOpt getOpt; + struct ForwardParamTruncate truncate; } ForwardParam; /* * Forward declaration. */ @@ -388,11 +398,11 @@ */ static void ForwardOpToHandlerThread(ReflectedChannel *rcPtr, ForwardedOperation op, const void *param); static int ForwardProc(Tcl_Event *evPtr, int mask); -static void SrcExitProc(ClientData clientData); +static void SrcExitProc(void *clientData); #define FreeReceivedError(p) \ if ((p)->base.mustFree) { \ Tcl_Free((p)->base.msgStr); \ } @@ -436,11 +446,11 @@ const char *objName, Tcl_Obj *obj, int *mask); static Tcl_Obj * DecodeEventMask(int mask); static ReflectedChannel * NewReflectedChannel(Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj); static Tcl_Obj * NextHandle(void); -static void FreeReflectedChannel(ReflectedChannel *rcPtr); +static Tcl_FreeProc FreeReflectedChannel; static int InvokeTclMethod(ReflectedChannel *rcPtr, MethodName method, Tcl_Obj *argOneObj, Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr); static ReflectedChannelMap * GetReflectedChannelMap(Tcl_Interp *interp); @@ -454,10 +464,11 @@ * 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}"; @@ -487,11 +498,11 @@ *---------------------------------------------------------------------- */ int TclChanCreateObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { ReflectedChannel *rcPtr; /* Instance data of the new channel */ @@ -500,11 +511,11 @@ * abilities of handler commands */ Tcl_Obj *cmdObj; /* Command prefix, list of words */ Tcl_Obj *cmdNameObj; /* Command name */ Tcl_Channel chan; /* Token for the new channel */ Tcl_Obj *modeObj; /* mode in obj form for method call */ - int listc; /* Result of 'initialize', and of */ + Tcl_Size listc; /* Result of 'initialize', and of */ Tcl_Obj **listv; /* its sublist in the 2nd element */ int methIndex; /* Encoded method name */ int result; /* Result code for 'initialize' */ Tcl_Obj *resObj; /* Result data for 'initialize' */ int methods; /* Bitmask for supported methods. */ @@ -536,11 +547,11 @@ return TCL_ERROR; } /* * First argument is a list of modes. Allowed entries are "read", "write". - * Expect at least one list element. Abbreviations are ok. + * Empty list is uncommon, but allowed. Abbreviations are ok. */ modeObj = objv[MODE]; if (EncodeEventMask(interp, "mode", objv[MODE], &mode) != TCL_OK) { return TCL_ERROR; @@ -567,10 +578,13 @@ * 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. * @@ -596,11 +610,11 @@ * - 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) { + if (TclListObjGetElementsM(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; @@ -693,10 +707,13 @@ clonePtr->blockModeProc = NULL; } if (!(methods & FLAG(METH_SEEK))) { clonePtr->wideSeekProc = NULL; } + if (!(methods & FLAG(METH_TRUNCATE))) { + clonePtr->truncateProc = NULL; + } chanPtr->typePtr = clonePtr; } /* @@ -783,11 +800,11 @@ } static int ReflectEventDelete( Tcl_Event *ev, - ClientData cd) + void *cd) { /* OWNER thread * * Invoked by DeleteThreadReflectedChannelMap() and ReflectClose(). The * latter ensures that no pending events of this type are run on an @@ -803,11 +820,11 @@ } #endif int TclChanPostEventObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { /* @@ -855,11 +872,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanId, (void *)NULL); return TCL_ERROR; } /* * Note that the search above subsumes several of the older checks, @@ -871,12 +888,12 @@ * * A successful search answers yes to both. Because the map holds only * handles of reflected channels, and only of such whose handler is * defined in this interpreter. * - * We keep the old checks for both, for paranioa, but abort now instead of - * throwing errors, as failure now means that our internal datastructures + * We keep the old checks for both, for paranoia, but abort now instead of + * throwing errors, as failure now means that our internal data structures * have gone seriously haywire. */ chan = (Tcl_Channel)Tcl_GetHashValue(hPtr); chanTypePtr = Tcl_GetChannelType(chan); @@ -905,10 +922,15 @@ * "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. */ @@ -968,12 +990,12 @@ * XXX (Delayed postevent executed after channel got removed). * XXX Can we detect this ? (check the validity of the owner threadid ?) * XXX Actually, in that case the channel should be dead also ! */ - Tcl_ThreadQueueEvent(rcPtr->owner, (Tcl_Event *) ev, TCL_QUEUE_TAIL); - Tcl_ThreadAlert(rcPtr->owner); + Tcl_ThreadQueueEvent(rcPtr->owner, (Tcl_Event *) ev, + TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY); } #endif /* * Squash interp results left by the event script. @@ -986,20 +1008,20 @@ #undef EVENT } static void TimerRunRead( - ClientData clientData) + void *clientData) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; rcPtr->readTimer = NULL; Tcl_NotifyChannel(rcPtr->chan, TCL_READABLE); } static void TimerRunWrite( - ClientData clientData) + void *clientData) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; rcPtr->writeTimer = NULL; Tcl_NotifyChannel(rcPtr->chan, TCL_WRITABLE); } @@ -1031,26 +1053,26 @@ static void UnmarshallErrorResult( Tcl_Interp *interp, Tcl_Obj *msgObj) { - int lc; + Tcl_Size lc; Tcl_Obj **lv; int explicitResult; - int numOptions; + Tcl_Size numOptions; /* * Process the caught message. * * Syntax = (option value)... ?message? * * Bad syntax causes a panic. This is OK because the other side uses - * Tcl_GetReturnOptions and list construction functions to marshall the + * Tcl_GetReturnOptions and list construction functions to marshal the * information; if we panic here, something has gone badly wrong already. */ - if (Tcl_ListObjGetElements(interp, msgObj, &lc, &lv) != TCL_OK) { + if (TclListObjGetElementsM(interp, msgObj, &lc, &lv) != TCL_OK) { Tcl_Panic("TclChanCaughtErrorBypass: Bad syntax of caught result"); } if (interp == NULL) { return; } @@ -1130,24 +1152,24 @@ *---------------------------------------------------------------------- * * ReflectClose -- * * This function is invoked when the channel is closed, to delete the - * driver specific instance data. + * driver-specific instance data. * * Results: - * A posix error. + * A Posix error. * * Side effects: * Releases memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectClose( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int flags) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; int result; /* Result code for 'close' */ @@ -1163,12 +1185,12 @@ if (TclInThreadExit()) { /* * This call comes from TclFinalizeIOSystem. There are no * interpreters, and therefore we cannot call upon the handler command - * anymore. Threading is irrelevant as well. We simply clean up all - * our C level data structures and leave the Tcl level to the other + * anymore. Threading is irrelevant as well. Simply clean up all + * the C level data structures and leave the Tcl level to the other * finalization functions. */ /* * THREADED => Forward this to the origin thread @@ -1206,11 +1228,11 @@ Tcl_DeleteTimerHandler(rcPtr->readTimer); } if (rcPtr->writeTimer != NULL) { Tcl_DeleteTimerHandler(rcPtr->writeTimer); } - Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel); + Tcl_EventuallyFree(rcPtr, FreeReflectedChannel); return EOK; } /* * Are we in the correct thread? @@ -1281,11 +1303,11 @@ Tcl_DeleteTimerHandler(rcPtr->readTimer); } if (rcPtr->writeTimer != NULL) { Tcl_DeleteTimerHandler(rcPtr->writeTimer); } - Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel); + Tcl_EventuallyFree(rcPtr, FreeReflectedChannel); return (result == TCL_OK) ? EOK : EINVAL; } /* *---------------------------------------------------------------------- @@ -1303,18 +1325,18 @@ *---------------------------------------------------------------------- */ static int ReflectInput( - ClientData clientData, + void *clientData, char *buf, int toRead, int *errorCodePtr) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; Tcl_Obj *toReadObj; - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ Tcl_Obj *resObj; /* Result data for 'read' */ /* * Are we in the correct thread? @@ -1367,20 +1389,23 @@ Tcl_SetChannelError(rcPtr->chan, resObj); goto invalid; } - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); - if ((size_t)toRead < 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 + 1 > 1) { + if (bytec > 0) { memcpy(buf, bytev, bytec); } stop: Tcl_DecrRefCount(toReadObj); @@ -1410,11 +1435,11 @@ *---------------------------------------------------------------------- */ static int ReflectOutput( - ClientData clientData, + void *clientData, const char *buf, int toWrite, int *errorCodePtr) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; @@ -1537,14 +1562,14 @@ * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ -static Tcl_WideInt +static long long ReflectSeekWide( - ClientData clientData, - Tcl_WideInt offset, + void *clientData, + long long offset, int seekMode, int *errorCodePtr) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; Tcl_Obj *offObj, *baseObj; @@ -1632,11 +1657,11 @@ *---------------------------------------------------------------------- */ static void ReflectWatch( - ClientData clientData, + void *clientData, int mask) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; Tcl_Obj *maskObj; @@ -1694,21 +1719,21 @@ * * This function is invoked to tell the channel which blocking behaviour * is required of it. * * Results: - * A posix error number. + * A Posix error number. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectBlock( - ClientData clientData, + void *clientData, int nonblocking) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; Tcl_Obj *blockObj; int errorNum; /* EINVAL or EOK (success). */ @@ -1771,11 +1796,11 @@ *---------------------------------------------------------------------- */ static void ReflectThread( - ClientData clientData, + void *clientData, int action) { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; switch (action) { @@ -1808,11 +1833,11 @@ *---------------------------------------------------------------------- */ static int ReflectSetOption( - ClientData clientData, /* Channel to query */ + void *clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ const char *optionName, /* Name of requested option */ const char *newValue) /* The new value */ { ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; @@ -1880,11 +1905,11 @@ *---------------------------------------------------------------------- */ static int ReflectGetOption( - ClientData clientData, /* Channel to query */ + void *clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ const char *optionName, /* Name of reuqested option */ Tcl_DString *dsPtr) /* String to place the result into */ { /* @@ -1893,11 +1918,12 @@ */ ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; Tcl_Obj *optionObj; Tcl_Obj *resObj; /* Result data for 'configure' */ - int listc, result = TCL_OK; + Tcl_Size listc; + int result = TCL_OK; Tcl_Obj **listv; MethodName method; /* * Are we in the correct thread? @@ -1974,11 +2000,11 @@ * 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) { + if (TclListObjGetElementsM(interp, resObj, &listc, &listv) != TCL_OK) { goto error; } if ((listc % 2) == 1) { /* @@ -1986,16 +2012,16 @@ */ Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "Expected list with even number of " - "elements, got %d element%s instead", listc, + "elements, got %" TCL_SIZE_MODIFIER "u element%s instead", listc, (listc == 1 ? "" : "s"))); goto error; } else { - size_t len; - const char *str = TclGetStringFromObj(resObj, &len); + Tcl_Size len; + const char *str = Tcl_GetStringFromObj(resObj, &len); if (len) { TclDStringAppendLiteral(dsPtr, " "); Tcl_DStringAppend(dsPtr, str, len); } @@ -2013,10 +2039,77 @@ 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. ========================================================= */ @@ -2024,14 +2117,14 @@ *---------------------------------------------------------------------- * * EncodeEventMask -- * * This function takes a list of event items and constructs the - * equivalent internal bitmask. The list must contain at least one - * element. Elements are "read", "write", or any unique abbreviation of - * them. Note that the bitmask is not changed if problems are - * encountered. + * equivalent internal bitmask. The list may be empty but will usually + * contain at least one element. Valid elements are "read", "write", or + * any unique abbreviation of them. Note that the bitmask is not changed + * if problems are encountered. * * Results: * A standard Tcl error code. A bitmask where TCL_READABLE and/or * TCL_WRITABLE can be set. * @@ -2048,22 +2141,16 @@ const char *objName, Tcl_Obj *obj, int *mask) { int events; /* Mask of events to post */ - int listc; /* #elements in eventspec list */ + Tcl_Size listc; /* #elements in eventspec list */ Tcl_Obj **listv; /* Elements of eventspec list */ int evIndex; /* Id of event for an element of the eventspec * list. */ - if (Tcl_ListObjGetElements(interp, obj, &listc, &listv) != TCL_OK) { - return TCL_ERROR; - } - - if (listc < 1) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad %s list: is empty", objName)); + if (TclListObjGetElementsM(interp, obj, &listc, &listv) != TCL_OK) { return TCL_ERROR; } events = 0; while (listc > 0) { @@ -2172,11 +2259,10 @@ 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, @@ -2199,11 +2285,11 @@ * Results: * A Tcl_Obj containing the string of the new channel handle. The * refcount of the returned object is -- zero --. * * Side effects: - * May allocate memory. Mutex protected critical section locks out other + * May allocate memory. Mutex-protected critical section locks out other * threads for a short time. * *---------------------------------------------------------------------- */ @@ -2230,12 +2316,13 @@ return resObj; } static void FreeReflectedChannel( - ReflectedChannel *rcPtr) + void *blockPtr) { + ReflectedChannel *rcPtr = (ReflectedChannel *) blockPtr; Channel *chanPtr = (Channel *) rcPtr->chan; TclChannelRelease((Tcl_Channel)chanPtr); if (rcPtr->name) { Tcl_DecrRefCount(rcPtr->name); @@ -2253,11 +2340,11 @@ *---------------------------------------------------------------------- * * InvokeTclMethod -- * * This function is used to invoke the Tcl level of a reflected channel. - * It handles all the command assembly, invokation, and generic state and + * It handles all the command assembly, invocation, and generic state and * result mgmt. It does *not* handle thread redirection; that is the * responsibility of clients of this function. * * Results: * Result code and data as returned by the method. @@ -2281,12 +2368,12 @@ Tcl_Obj *argTwoObj, /* NULL'able */ Tcl_Obj **resultObjPtr) /* NULL'able */ { Tcl_Obj *methObj = NULL; /* Method name in object form */ Tcl_InterpState sr; /* State of handler interp */ - int result; /* Result code of method invokation */ - Tcl_Obj *resObj = NULL; /* Result of method invokation. */ + int result; /* Result code of method invocation */ + Tcl_Obj *resObj = NULL; /* Result of method invocation. */ Tcl_Obj *cmd; if (rcPtr->dead) { /* * The channel is marked as dead. Bail out immediately, with an @@ -2311,11 +2398,10 @@ * 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); /* @@ -2365,12 +2451,12 @@ * 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_Size cmdLen; + const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen); Tcl_IncrRefCount(cmd); Tcl_ResetResult(rcPtr->interp); Tcl_SetObjResult(rcPtr->interp, Tcl_ObjPrintf( "chan handler returned bad code: %d", result)); @@ -2501,11 +2587,11 @@ * Results: * None. * * Side effects: * Deletes the hash table of channels. May close channels. May flush - * output on closed channels. Removes any channeEvent handlers that were + * output on closed channels. Removes any channelEvent handlers that were * registered in this interpreter. * *---------------------------------------------------------------------- */ @@ -2531,11 +2617,11 @@ rcPtr->dead = 1; } static void DeleteReflectedChannelMap( - ClientData clientData, /* The per-interpreter data structure. */ + void *clientData, /* The per-interpreter data structure. */ Tcl_Interp *interp) /* The interpreter being deleted. */ { ReflectedChannelMap *rcmPtr = (ReflectedChannelMap *)clientData; /* The map */ Tcl_HashSearch hSearch; /* Search variable. */ @@ -2653,10 +2739,12 @@ } MarkDead(rcPtr); Tcl_DeleteHashEntry(hPtr); } +#else + (void)interp; #endif } #if TCL_THREADS /* @@ -2708,17 +2796,18 @@ *---------------------------------------------------------------------- */ static void DeleteThreadReflectedChannelMap( - TCL_UNUSED(ClientData)) + TCL_UNUSED(void *)) { Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ Tcl_ThreadId self = Tcl_GetCurrentThread(); ReflectedChannelMap *rcmPtr; /* The map */ ForwardingResult *resultPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * The origin thread for one or more reflected channels is gone. * NOTE: If this function is called due to a thread getting killed the * per-interp DeleteReflectedChannelMap is apparently not called. @@ -2794,10 +2883,11 @@ * 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); @@ -2883,12 +2973,12 @@ /* * Queue the event and poke the other thread's notifier. */ - Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr, TCL_QUEUE_TAIL); - Tcl_ThreadAlert(dst); + Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr, + TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY); /* * (*) Block until the handler thread has either processed the transfer or * rejected it. */ @@ -3034,20 +3124,23 @@ } else { /* * Process a regular result. */ - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); - if (paramPtr->input.toRead < 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 + 1 > 1) { + if (bytec > 0) { memcpy(paramPtr->input.buf, bytev, bytec); } paramPtr->input.toRead = bytec; } } @@ -3213,14 +3306,14 @@ /* * Extract list, validate that it is a list, and #elements. See * NOTE (4) as well. */ - int listc; + Tcl_Size listc; Tcl_Obj **listv; - if (Tcl_ListObjGetElements(interp, resObj, &listc, + if (TclListObjGetElementsM(interp, resObj, &listc, &listv) != TCL_OK) { Tcl_DecrRefCount(resObj); resObj = MarshallError(interp); ForwardSetObjError(paramPtr, resObj); } else if ((listc % 2) == 1) { @@ -3227,27 +3320,40 @@ /* * Odd number of elements is wrong. [x]. */ char *buf = (char *)Tcl_Alloc(200); - sprintf(buf, - "{Expected list with even number of elements, got %d %s instead}", + snprintf(buf, 200, + "{Expected list with even number of elements, got %" TCL_SIZE_MODIFIER "u %s instead}", listc, (listc == 1 ? "element" : "elements")); ForwardSetDynamicError(paramPtr, buf); } else { - size_t len; - const char *str = TclGetStringFromObj(resObj, &len); + Tcl_Size len; + const char *str = Tcl_GetStringFromObj(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. */ @@ -3281,11 +3387,11 @@ return 1; } static void SrcExitProc( - ClientData clientData) + void *clientData) { ForwardingEvent *evPtr = (ForwardingEvent *)clientData; ForwardingResult *resultPtr; ForwardParam *paramPtr; @@ -3332,12 +3438,12 @@ static void ForwardSetObjError( ForwardParam *paramPtr, Tcl_Obj *obj) { - size_t len; - const char *msgStr = TclGetStringFromObj(obj, &len); + Tcl_Size len; + const char *msgStr = Tcl_GetStringFromObj(obj, &len); len++; ForwardSetDynamicError(paramPtr, Tcl_Alloc(len)); memcpy(paramPtr->base.msgStr, msgStr, len); } Index: generic/tclIORTrans.c ================================================================== --- generic/tclIORTrans.c +++ generic/tclIORTrans.c @@ -8,11 +8,11 @@ * Parts of this file are based on code contributed by Jean-Claude * Wippler. * * See TIP #230 for the specification of this functionality. * - * Copyright (c) 2007-2008 ActiveState. + * Copyright © 2007-2008 ActiveState. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -29,29 +29,29 @@ /* * Signatures of all functions used in the C layer of the reflection. */ -static int ReflectClose(ClientData clientData, +static int ReflectClose(void *clientData, Tcl_Interp *interp, int flags); -static int ReflectInput(ClientData clientData, char *buf, +static int ReflectInput(void *clientData, char *buf, int toRead, int *errorCodePtr); -static int ReflectOutput(ClientData clientData, const char *buf, +static int ReflectOutput(void *clientData, const char *buf, int toWrite, int *errorCodePtr); -static void ReflectWatch(ClientData clientData, int mask); -static int ReflectBlock(ClientData clientData, int mode); -static Tcl_WideInt ReflectSeekWide(ClientData clientData, - Tcl_WideInt offset, int mode, int *errorCodePtr); -static int ReflectGetOption(ClientData clientData, +static void ReflectWatch(void *clientData, int mask); +static int ReflectBlock(void *clientData, int mode); +static long long ReflectSeekWide(void *clientData, + long long offset, int mode, int *errorCodePtr); +static int ReflectGetOption(void *clientData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); -static int ReflectSetOption(ClientData clientData, +static int ReflectSetOption(void *clientData, Tcl_Interp *interp, const char *optionName, const char *newValue); -static int ReflectHandle(ClientData clientData, int direction, - ClientData *handle); -static int ReflectNotify(ClientData clientData, int mask); +static int ReflectHandle(void *clientData, int direction, + void **handle); +static int ReflectNotify(void *clientData, int mask); /* * The C layer channel type/driver definition used by the reflection. */ @@ -89,16 +89,16 @@ } ResultBuffer; #define ResultLength(r) ((r)->used) /* static int ResultLength(ResultBuffer *r); */ -static void ResultClear(ResultBuffer *r); -static void ResultInit(ResultBuffer *r); -static void ResultAdd(ResultBuffer *r, unsigned char *buf, - int toWrite); -static int ResultCopy(ResultBuffer *r, unsigned char *buf, - int toRead); +static inline void ResultClear(ResultBuffer *r); +static inline void ResultInit(ResultBuffer *r); +static inline void ResultAdd(ResultBuffer *r, unsigned char *buf, + size_t toWrite); +static inline size_t ResultCopy(ResultBuffer *r, unsigned char *buf, + size_t toRead); #define RB_INCREMENT (512) /* * Convenience macro to make some casts easier to use. @@ -210,11 +210,11 @@ #define RANDW \ (TCL_READABLE | TCL_WRITABLE) #define IMPLIES(a,b) ((!(a)) || (b)) #define NEGIMPL(a,b) -#define HAS(x,f) (x & FLAG(f)) +#define HAS(x,f) ((x) & FLAG(f)) #if TCL_THREADS /* * Thread specific types and structures. * @@ -262,11 +262,11 @@ struct ForwardParamTransform { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ char *buf; /* I: Bytes to transform, * O: Bytes in transform result */ - size_t size; /* I: #bytes to transform, + Tcl_Size size; /* I: #bytes to transform, * O: #bytes in the transform result */ }; struct ForwardParamLimit { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ int max; /* O: Character read limit */ @@ -353,11 +353,11 @@ */ static void ForwardOpToOwnerThread(ReflectedTransform *rtPtr, ForwardedOperation op, const void *param); static int ForwardProc(Tcl_Event *evPtr, int mask); -static void SrcExitProc(ClientData clientData); +static void SrcExitProc(void *clientData); #define FreeReceivedError(p) \ do { \ if ((p)->base.mustFree) { \ Tcl_Free((p)->base.msgStr); \ @@ -392,11 +392,11 @@ static void ForwardSetObjError(ForwardParam *p, Tcl_Obj *objPtr); static ReflectedTransformMap * GetThreadReflectedTransformMap(void); static void DeleteThreadReflectedTransformMap( - ClientData clientData); + void *clientData); #endif /* TCL_THREADS */ #define SetChannelErrorStr(c,msgStr) \ Tcl_SetChannelError((c), Tcl_NewStringObj((msgStr), -1)) @@ -411,18 +411,18 @@ static Tcl_Obj * DecodeEventMask(int mask); static ReflectedTransform * NewReflectedTransform(Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj, Tcl_Channel parentChan); static Tcl_Obj * NextHandle(void); -static void FreeReflectedTransform(ReflectedTransform *rtPtr); +static Tcl_FreeProc FreeReflectedTransform; static void FreeReflectedTransformArgs(ReflectedTransform *rtPtr); static int InvokeTclMethod(ReflectedTransform *rtPtr, const char *method, Tcl_Obj *argOneObj, Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr); static ReflectedTransformMap * GetReflectedTransformMap(Tcl_Interp *interp); -static void DeleteReflectedTransformMap(ClientData clientData, +static void DeleteReflectedTransformMap(void *clientData, Tcl_Interp *interp); /* * Global constant strings (messages). ================== * These string are used directly as bypass errors, thus they have to be valid @@ -448,11 +448,11 @@ * control flow in callers easier. */ static void TimerKill(ReflectedTransform *rtPtr); static void TimerSetup(ReflectedTransform *rtPtr); -static void TimerRun(ClientData clientData); +static void TimerRun(void *clientData); static int TransformRead(ReflectedTransform *rtPtr, int *errorCodePtr, Tcl_Obj *bufObj); static int TransformWrite(ReflectedTransform *rtPtr, int *errorCodePtr, unsigned char *buf, int toWrite); @@ -493,11 +493,11 @@ *---------------------------------------------------------------------- */ int TclChanPushObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { ReflectedTransform *rtPtr; /* Instance data of the new (transform) @@ -509,11 +509,11 @@ * commands */ Tcl_Obj *cmdObj; /* Command prefix, list of words */ Tcl_Obj *cmdNameObj; /* Command name */ Tcl_Obj *rtId; /* Handle of the new transform (channel) */ Tcl_Obj *modeObj; /* mode in obj form for method call */ - int listc; /* Result of 'initialize', and of */ + Tcl_Size listc; /* Result of 'initialize', and of */ Tcl_Obj **listv; /* its sublist in the 2nd element */ int methIndex; /* Encoded method name */ int result; /* Result code for 'initialize' */ Tcl_Obj *resObj; /* Result data for 'initialize' */ int methods; /* Bitmask for supported methods. */ @@ -597,11 +597,11 @@ * 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) { + if (TclListObjGetElementsM(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; @@ -632,11 +632,11 @@ } /* * Mode tell us what the parent channel supports. The methods tell us what * the handler supports. We remove the non-supported bits from the mode - * and check that the channel is not completely inacessible. Afterward the + * and check that the channel is not completely inaccessible. Afterward the * mode tells us which methods are still required, and these methods will * also be supported by the handler, by design of the check. */ if (!HAS(methods, METH_READ)) { @@ -711,11 +711,11 @@ /* * We are not going through ReflectClose as we never had a channel * structure. */ - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, FreeReflectedTransform); return TCL_ERROR; #undef CHAN #undef CMD } @@ -738,11 +738,11 @@ *---------------------------------------------------------------------- */ int TclChanPopObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { /* @@ -818,14 +818,14 @@ static void UnmarshallErrorResult( Tcl_Interp *interp, Tcl_Obj *msgObj) { - int lc; + Tcl_Size lc; Tcl_Obj **lv; int explicitResult; - int numOptions; + Tcl_Size numOptions; /* * Process the caught message. * * Syntax = (option value)... ?message? @@ -833,11 +833,11 @@ * Bad syntax causes a panic. This is OK because the other side uses * Tcl_GetReturnOptions and list construction functions to marshall the * information; if we panic here, something has gone badly wrong already. */ - if (Tcl_ListObjGetElements(interp, msgObj, &lc, &lv) != TCL_OK) { + if (TclListObjGetElementsM(interp, msgObj, &lc, &lv) != TCL_OK) { Tcl_Panic("TclChanCaughtErrorBypass: Bad syntax of caught result"); } if (interp == NULL) { return; } @@ -864,21 +864,21 @@ * * This function is invoked when the channel is closed, to delete the * driver specific instance data. * * Results: - * A posix error. + * A Posix error. * * Side effects: * Releases memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectClose( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int flags) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; int errorCode, errorCodeSet = 0; @@ -921,11 +921,11 @@ FreeReceivedError(&p); } } #endif /* TCL_THREADS */ - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, FreeReflectedTransform); return EOK; } /* * In the reflected channel implementation a cleaned method mask here @@ -938,11 +938,11 @@ if (HAS(rtPtr->methods, METH_DRAIN) && !rtPtr->readIsDrained) { if (!TransformDrain(rtPtr, &errorCode)) { #if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, - (Tcl_FreeProc *) FreeReflectedTransform); + FreeReflectedTransform); return errorCode; } #endif /* TCL_THREADS */ errorCodeSet = 1; goto cleanup; @@ -952,11 +952,11 @@ if (HAS(rtPtr->methods, METH_FLUSH)) { if (!TransformFlush(rtPtr, &errorCode, FLUSH_WRITE)) { #if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, - (Tcl_FreeProc *) FreeReflectedTransform); + FreeReflectedTransform); return errorCode; } #endif /* TCL_THREADS */ errorCodeSet = 1; goto cleanup; @@ -972,11 +972,11 @@ ForwardParam p; ForwardOpToOwnerThread(rtPtr, ForwardedClose, &p); result = p.base.code; - Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, FreeReflectedTransform); if (result != TCL_OK) { PassReceivedErrorInterp(interp, &p); return EINVAL; } @@ -983,11 +983,11 @@ return EOK; } #endif /* TCL_THREADS */ /* - * Do the actual invokation of "finalize" now; we're in the right thread. + * Do the actual invocation of "finalize" now; we're in the right thread. */ result = InvokeTclMethod(rtPtr, "finalize", NULL, NULL, &resObj); if ((result != TCL_OK) && (interp != NULL)) { Tcl_SetChannelErrorInterp(interp, resObj); @@ -1031,11 +1031,11 @@ Tcl_DeleteHashEntry(hPtr); } #endif /* TCL_THREADS */ } - Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); + Tcl_EventuallyFree(rtPtr, FreeReflectedTransform); return errorCodeSet ? errorCode : ((result == TCL_OK) ? EOK : EINVAL); } /* *---------------------------------------------------------------------- @@ -1053,11 +1053,11 @@ *---------------------------------------------------------------------- */ static int ReflectInput( - ClientData clientData, + void *clientData, char *buf, int toRead, int *errorCodePtr) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; @@ -1246,11 +1246,11 @@ *---------------------------------------------------------------------- */ static int ReflectOutput( - ClientData clientData, + void *clientData, const char *buf, int toWrite, int *errorCodePtr) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; @@ -1317,14 +1317,14 @@ * scripts. * *---------------------------------------------------------------------- */ -static Tcl_WideInt +static long long ReflectSeekWide( - ClientData clientData, - Tcl_WideInt offset, + void *clientData, + long long offset, int seekMode, int *errorCodePtr) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; Channel *parent = (Channel *) rtPtr->parent; @@ -1406,11 +1406,11 @@ *---------------------------------------------------------------------- */ static void ReflectWatch( - ClientData clientData, + void *clientData, int mask) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; Tcl_DriverWatchProc *watchProc; @@ -1447,21 +1447,21 @@ * * This function is invoked to tell the channel which blocking behaviour * is required of it. * * Results: - * A posix error number. + * A Posix error number. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectBlock( - ClientData clientData, + void *clientData, int nonblocking) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; /* @@ -1490,11 +1490,11 @@ *---------------------------------------------------------------------- */ static int ReflectSetOption( - ClientData clientData, /* Channel to query */ + void *clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ const char *optionName, /* Name of requested option */ const char *newValue) /* The new value */ { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; @@ -1532,13 +1532,13 @@ *---------------------------------------------------------------------- */ static int ReflectGetOption( - ClientData clientData, /* Channel to query */ + void *clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ - const char *optionName, /* Name of reuqested option */ + const char *optionName, /* Name of requested option */ Tcl_DString *dsPtr) /* String to place the result into */ { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; /* @@ -1581,19 +1581,19 @@ *---------------------------------------------------------------------- */ static int ReflectHandle( - ClientData clientData, + void *clientData, int direction, - ClientData *handlePtr) + void **handlePtr) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; /* * Transformations have no handle of their own. As such we simply query - * the parent channel for it. This way the qery will ripple down through + * the parent channel for it. This way the query will ripple down through * all transformations until reaches the base channel. Which then returns * its handle, or fails. The former will then ripple up the stack. * * This all happens in the thread we are in. As the Tcl level is not * involved no forwarding is required. @@ -1617,17 +1617,17 @@ *---------------------------------------------------------------------- */ static int ReflectNotify( - ClientData clientData, + void *clientData, int mask) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; /* - * An event occured in the underlying channel. + * An event occurred in the underlying channel. * * We delete our timer. It was not fired, yet we are here, so the channel * below generated such an event and we don't have to. The renewal of the * interest after the execution of channel handlers will eventually cause * us to recreate the timer (in ReflectWatch). @@ -1717,13 +1717,12 @@ TCL_UNUSED(int) /*mode*/, Tcl_Obj *handleObj, Tcl_Channel parentChan) { ReflectedTransform *rtPtr; - int listc; + Tcl_Size i, listc; Tcl_Obj **listv; - int i; rtPtr = (ReflectedTransform *)Tcl_Alloc(sizeof(ReflectedTransform)); /* rtPtr->chan: Assigned by caller. Dummy data here. */ /* rtPtr->methods: Assigned by caller. Dummy data here. */ @@ -1755,11 +1754,11 @@ * Method placeholder. */ /* ASSERT: cmdpfxObj is a Tcl List */ - Tcl_ListObjGetElements(interp, cmdpfxObj, &listc, &listv); + TclListObjGetElementsM(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. @@ -1869,12 +1868,13 @@ rtPtr->argc = 1; } static void FreeReflectedTransform( - ReflectedTransform *rtPtr) + void *blockPtr) { + ReflectedTransform *rtPtr = (ReflectedTransform *) blockPtr; TimerKill(rtPtr); ResultClear(&rtPtr->result); FreeReflectedTransformArgs(rtPtr); @@ -1886,11 +1886,11 @@ *---------------------------------------------------------------------- * * InvokeTclMethod -- * * This function is used to invoke the Tcl level of a reflected channel. - * It handles all the command assembly, invokation, and generic state and + * It handles all the command assembly, invocation, and generic state and * result mgmt. It does *not* handle thread redirection; that is the * responsibility of clients of this function. * * Results: * Result code and data as returned by the method. @@ -1918,12 +1918,12 @@ Tcl_Obj **resultObjPtr) /* NULL'able */ { int cmdc; /* #words in constructed command */ Tcl_Obj *methObj = NULL; /* Method name in object form */ Tcl_InterpState sr; /* State of handler interp */ - int result; /* Result code of method invokation */ - Tcl_Obj *resObj = NULL; /* Result of method invokation. */ + int result; /* Result code of method invocation */ + Tcl_Obj *resObj = NULL; /* Result of method invocation. */ if (rtPtr->dead) { /* * The transform is marked as dead. Bail out immediately, with an * appropriate error. @@ -1943,11 +1943,11 @@ * threads. * NO: Caching of command resolutions means storage per channel. */ /* - * Insert method into the pre-allocated area, after the command prefix, + * Insert method into the preallocated area, after the command prefix, * before the channel id. */ methObj = Tcl_NewStringObj(method, -1); Tcl_IncrRefCount(methObj); @@ -1970,11 +1970,11 @@ cmdc++; } } /* - * And run the handler... This is done in auch a manner which leaves any + * And run the handler... This is done in a manner which leaves any * existing state intact. */ sr = Tcl_SaveInterpState(rtPtr->interp, 0 /* Dummy */); Tcl_Preserve(rtPtr); @@ -2003,12 +2003,12 @@ * 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_Size cmdLen; + const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen); Tcl_IncrRefCount(cmd); Tcl_ResetResult(rtPtr->interp); Tcl_SetObjResult(rtPtr->interp, Tcl_ObjPrintf( "chan handler returned bad code: %d", result)); @@ -2106,11 +2106,11 @@ *---------------------------------------------------------------------- */ static void DeleteReflectedTransformMap( - ClientData clientData, /* The per-interpreter data structure. */ + void *clientData, /* The per-interpreter data structure. */ Tcl_Interp *interp) /* The interpreter being deleted. */ { ReflectedTransformMap *rtmPtr; /* The map */ Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ @@ -2117,10 +2117,12 @@ 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 @@ -2267,11 +2269,11 @@ *---------------------------------------------------------------------- */ static void DeleteThreadReflectedTransformMap( - TCL_UNUSED(ClientData)) + TCL_UNUSED(void *)) { Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ Tcl_ThreadId self = Tcl_GetCurrentThread(); ReflectedTransformMap *rtmPtr; /* The map */ @@ -2411,12 +2413,12 @@ /* * Queue the event and poke the other thread's notifier. */ - Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr, TCL_QUEUE_TAIL); - Tcl_ThreadAlert(dst); + Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr, + TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY); /* * (*) Block until the other thread has either processed the transfer or * rejected it. */ @@ -2559,15 +2561,15 @@ /* * Process a regular return. Contains the transformation result. * Sent it back to the request originator. */ - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); paramPtr->transform.size = bytec; if (bytec > 0) { paramPtr->transform.buf = (char *)Tcl_Alloc(bytec); @@ -2593,15 +2595,15 @@ /* * Process a regular return. Contains the transformation result. * Sent it back to the request originator. */ - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); paramPtr->transform.size = bytec; if (bytec > 0) { paramPtr->transform.buf = (char *)Tcl_Alloc(bytec); @@ -2623,14 +2625,14 @@ /* * Process a regular return. Contains the transformation result. * Sent it back to the request originator. */ - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); paramPtr->transform.size = bytec; if (bytec > 0) { paramPtr->transform.buf = (char *)Tcl_Alloc(bytec); @@ -2649,15 +2651,15 @@ /* * Process a regular return. Contains the transformation result. * Sent it back to the request originator. */ - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); paramPtr->transform.size = bytec; if (bytec > 0) { paramPtr->transform.buf = (char *)Tcl_Alloc(bytec); @@ -2716,11 +2718,11 @@ return 1; } static void SrcExitProc( - ClientData clientData) + void *clientData) { ForwardingEvent *evPtr = (ForwardingEvent *)clientData; ForwardingResult *resultPtr; ForwardParam *paramPtr; @@ -2767,12 +2769,12 @@ static void ForwardSetObjError( ForwardParam *paramPtr, Tcl_Obj *obj) { - size_t len; - const char *msgStr = TclGetStringFromObj(obj, &len); + Tcl_Size len; + const char *msgStr = Tcl_GetStringFromObj(obj, &len); len++; ForwardSetDynamicError(paramPtr, Tcl_Alloc(len)); memcpy(paramPtr->base.msgStr, msgStr, len); } @@ -2856,11 +2858,11 @@ *---------------------------------------------------------------------- */ static void TimerRun( - ClientData clientData) + void *clientData) { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; rtPtr->timer = NULL; Tcl_NotifyChannel(rtPtr->chan, TCL_READABLE); @@ -2870,11 +2872,11 @@ *---------------------------------------------------------------------- * * ResultInit -- * * Initializes the specified buffer structure. The structure will contain - * valid information for an emtpy buffer. + * valid information for an empty buffer. * * Side effects: * See above. * * Result: @@ -2881,11 +2883,11 @@ * None. * *---------------------------------------------------------------------- */ -static void +static inline void ResultInit( ResultBuffer *rPtr) /* Reference to the structure to * initialize. */ { rPtr->used = 0; @@ -2906,11 +2908,11 @@ * None. * *---------------------------------------------------------------------- */ -static void +static inline void ResultClear( ResultBuffer *rPtr) /* Reference to the buffer to clear out */ { rPtr->used = 0; @@ -2937,15 +2939,15 @@ * None. * *---------------------------------------------------------------------- */ -static void +static inline void ResultAdd( ResultBuffer *rPtr, /* The buffer to extend */ unsigned char *buf, /* The buffer to read from */ - int toWrite) /* The number of bytes in 'buf' */ + size_t toWrite) /* The number of bytes in 'buf' */ { if ((rPtr->used + toWrite + 1) > rPtr->allocated) { /* * Extension of the internal buffer is required. * NOTE: Currently linear. Should be doubling to amortize. @@ -2985,15 +2987,15 @@ * The number of actually copied bytes, possibly less than 'toRead'. * *---------------------------------------------------------------------- */ -static int +static inline size_t ResultCopy( ResultBuffer *rPtr, /* The buffer to read from */ unsigned char *buf, /* The buffer to copy into */ - int toRead) /* Number of requested bytes */ + size_t toRead) /* Number of requested bytes */ { int copied; if (rPtr->used == 0) { /* @@ -3042,11 +3044,11 @@ ReflectedTransform *rtPtr, int *errorCodePtr, Tcl_Obj *bufObj) { Tcl_Obj *resObj; - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ /* * Are we in the correct thread? */ @@ -3053,11 +3055,11 @@ #if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; - p.transform.buf = (char *) TclGetByteArrayFromObj(bufObj, + p.transform.buf = (char *) Tcl_GetByteArrayFromObj(bufObj, &(p.transform.size)); ForwardOpToOwnerThread(rtPtr, ForwardedInput, &p); if (p.base.code != TCL_OK) { @@ -3081,11 +3083,11 @@ Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ *errorCodePtr = EINVAL; return 0; } - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); ResultAdd(&rtPtr->result, bytev, bytec); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ return 1; } @@ -3097,11 +3099,11 @@ unsigned char *buf, int toWrite) { Tcl_Obj *bufObj; Tcl_Obj *resObj; - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ int res; /* * Are we in the correct thread? @@ -3143,11 +3145,11 @@ return 0; } *errorCodePtr = EOK; - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); res = Tcl_WriteRaw(rtPtr->parent, (char *) bytev, bytec); Tcl_DecrRefCount(bufObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ } @@ -3164,11 +3166,11 @@ TransformDrain( ReflectedTransform *rtPtr, int *errorCodePtr) { Tcl_Obj *resObj; - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ /* * Are we in the correct thread? */ @@ -3196,11 +3198,11 @@ Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ *errorCodePtr = EINVAL; return 0; } - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); ResultAdd(&rtPtr->result, bytev, bytec); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ } @@ -3213,11 +3215,11 @@ ReflectedTransform *rtPtr, int *errorCodePtr, int op) { Tcl_Obj *resObj; - size_t bytec = 0; /* Number of returned bytes */ + Tcl_Size bytec = 0; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ int res; /* * Are we in the correct thread? @@ -3252,11 +3254,11 @@ *errorCodePtr = EINVAL; return 0; } if (op == FLUSH_WRITE) { - bytev = TclGetByteArrayFromObj(resObj, &bytec); + bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); res = Tcl_WriteRaw(rtPtr->parent, (char *) bytev, bytec); } else { res = 0; } Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Index: generic/tclIOSock.c ================================================================== --- generic/tclIOSock.c +++ generic/tclIOSock.c @@ -1,11 +1,11 @@ /* * tclIOSock.c -- * * Common routines used by all socket based channel types. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright © 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -115,15 +115,19 @@ #endif int TclSockMinimumBuffers( void *sock, /* Socket file descriptor */ - int size) /* Minimum buffer size */ + Tcl_Size size1) /* Minimum buffer size */ { int current; socklen_t len; + int size = size1; + if (size != size1) { + return TCL_ERROR; + } len = sizeof(int); getsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_SNDBUF, (char *) ¤t, &len); if (current < size) { len = sizeof(int); @@ -311,21 +315,21 @@ Tcl_OpenTcpServer( Tcl_Interp *interp, int port, const char *host, Tcl_TcpAcceptProc *acceptProc, - ClientData callbackData) + void *callbackData) { char portbuf[TCL_INTEGER_SPACE]; TclFormatInt(portbuf, port); - return Tcl_OpenTcpServerEx(interp, portbuf, host, TCL_TCPSERVER_REUSEADDR, - acceptProc, callbackData); + return Tcl_OpenTcpServerEx(interp, portbuf, host, -1, + TCL_TCPSERVER_REUSEADDR, acceptProc, callbackData); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tclIOUtil.c ================================================================== --- generic/tclIOUtil.c +++ generic/tclIOUtil.c @@ -5,13 +5,13 @@ * creating a filesystem interface in Tcl arbitrary facilities. All * filesystem operations are performed via this interface. Vince Darley * is the primary author. Other signifiant contributors are Karl * Lehenbauer, Mark Diekhans and Peter da Silva. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2001-2004 Vincent Darley. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2001-2004 Vincent Darley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -32,11 +32,11 @@ * * An item in a linked list of registered filesystems */ typedef struct FilesystemRecord { - ClientData clientData; /* Client-specific data for the filesystem + void *clientData; /* Client-specific data for the filesystem * (can be NULL) */ const Tcl_Filesystem *fsPtr;/* Pointer to filesystem dispatch table. */ struct FilesystemRecord *nextPtr; /* The next registered filesystem, or NULL to * indicate the end of the list. */ @@ -56,11 +56,11 @@ size_t filesystemEpoch; Tcl_Obj *cwdPathPtr; /* A private copy of cwdPathPtr. Updated when * the value is accessed and cwdPathEpoch has * changed. */ - ClientData cwdClientData; + void *cwdClientData; FilesystemRecord *filesystemList; size_t claims; } ThreadSpecificData; /* @@ -67,16 +67,16 @@ * Forward declarations. */ static Tcl_NRPostProc EvalFileCallback; static FilesystemRecord*FsGetFirstFilesystem(void); -static void FsThrExitProc(ClientData cd); +static void FsThrExitProc(void *cd); static Tcl_Obj * FsListMounts(Tcl_Obj *pathPtr, const char *pattern); static void FsAddMountsToGlobResult(Tcl_Obj *resultPtr, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); -static void FsUpdateCwd(Tcl_Obj *cwdObj, ClientData clientData); +static void FsUpdateCwd(Tcl_Obj *cwdObj, void *clientData); static void FsRecacheFilesystemList(void); static void Claim(void); static void Disclaim(void); static void * DivertFindSymbol(Tcl_Interp *interp, @@ -176,11 +176,11 @@ }; /* * An initial record in the linked list for the native filesystem. Remains at * the tail of the list and is never freed. Currently the native filesystem is - * hard-coded. It may make sense to modify this to accomodate unconventional + * hard-coded. It may make sense to modify this to accommodate unconventional * uses of Tcl that provide no native filesystem. */ static FilesystemRecord nativeFilesystemRecord = { NULL, @@ -210,11 +210,11 @@ * A files-system indepent sense of the current directory. */ static Tcl_Obj *cwdPathPtr = NULL; static size_t cwdPathEpoch = 0; /* The pathname of the current directory */ -static ClientData cwdClientData = NULL; +static void *cwdClientData = NULL; TCL_DECLARE_MUTEX(cwdMutex) static Tcl_ThreadDataKey fsDataKey; /* @@ -228,11 +228,11 @@ typedef struct { Tcl_LoadHandle loadHandle; Tcl_FSUnloadFileProc *unloadProcPtr; Tcl_Obj *divertedFile; const Tcl_Filesystem *divertedFilesystem; - ClientData divertedFileNativeRep; + void *divertedFileNativeRep; } FsDivertLoad; /* * Obsolete string-based APIs that should be removed in a future release, * perhaps in Tcl 9. @@ -291,11 +291,11 @@ # undef OUT_OF_RANGE # undef OUT_OF_URANGE #endif /* !TCL_WIDE_INT_IS_LONG */ /* - * Copy across all supported fields, with possible type coercions on + * Copy across all supported fields, with possible type coercion on * those fields that change between the normal and lf64 versions of * the stat structure (on Solaris at least). This is slow when the * structure sizes coincide, but that's what you get for using an * obsolete interface. */ @@ -412,11 +412,11 @@ * The basic filesystem implementation. */ static void FsThrExitProc( - ClientData cd) + void *cd) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *)cd; FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL; /* @@ -519,15 +519,15 @@ } if (tsdPtr->cwdPathPtr == *pathPtrPtr) { return 1; } else { - size_t len1, len2; + Tcl_Size len1, len2; const char *str1, *str2; - str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1); - str2 = TclGetStringFromObj(*pathPtrPtr, &len2); + str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1); + str2 = Tcl_GetStringFromObj(*pathPtrPtr, &len2); if ((len1 == len2) && !memcmp(str1, str2, len1)) { /* * The values are equal but the objects are different. Cache the * current structure in place of the old one. */ @@ -659,18 +659,18 @@ */ static void FsUpdateCwd( Tcl_Obj *cwdObj, - ClientData clientData) + void *clientData) { - size_t len = 0; + Tcl_Size len = 0; const char *str = NULL; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); if (cwdObj != NULL) { - str = TclGetStringFromObj(cwdObj, &len); + str = Tcl_GetStringFromObj(cwdObj, &len); } Tcl_MutexLock(&cwdMutex); if (cwdPathPtr != NULL) { Tcl_DecrRefCount(cwdPathPtr); @@ -759,10 +759,11 @@ /* * Remove all filesystems, freeing any allocated memory that is no longer * needed. */ + TclZipfsFinalize(); fsRecPtr = filesystemList; while (fsRecPtr != NULL) { FilesystemRecord *tmpFsRecPtr = fsRecPtr->nextPtr; /* @@ -841,11 +842,11 @@ *---------------------------------------------------------------------- */ int Tcl_FSRegister( - ClientData clientData, /* Client-specific data for this filesystem. */ + void *clientData, /* Client-specific data for this filesystem. */ const Tcl_Filesystem *fsPtr)/* The filesystem record for the new fs. */ { FilesystemRecord *newFilesystemPtr; if (fsPtr == NULL) { @@ -987,11 +988,12 @@ * May be NULL. The directory flag is * particularly significant. */ { const Tcl_Filesystem *fsPtr; Tcl_Obj *cwd, *tmpResultPtr, **elemsPtr; - int resLength, i, ret = -1; + Tcl_Size resLength, i; + int ret = -1; if (types != NULL && (types->type & TCL_GLOB_TYPE_MOUNT)) { /* * Currently external callers may not query mounts, which would be a * valuable future step. This is the only routine that knows about @@ -1063,11 +1065,11 @@ /* * resultPtr and tmpResultPtr are guaranteed to be distinct. */ - ret = Tcl_ListObjGetElements(interp, tmpResultPtr, + ret = TclListObjGetElementsM(interp, tmpResultPtr, &resLength, &elemsPtr); for (i=0 ; ret==TCL_OK && itype & TCL_GLOB_TYPE_DIR)); Tcl_Obj *mounts = FsListMounts(pathPtr, pattern); if (mounts == NULL) { return; } - if (Tcl_ListObjLength(NULL, mounts, &mLength) != TCL_OK || mLength == 0) { + if (TclListObjLengthM(NULL, mounts, &mLength) != TCL_OK || mLength == 0) { goto endOfMounts; } - if (Tcl_ListObjLength(NULL, resultPtr, &gLength) != TCL_OK) { + if (TclListObjLengthM(NULL, resultPtr, &gLength) != TCL_OK) { goto endOfMounts; } for (i=0 ; i= 3) && ( (path[0] == '/' && path[1] == '/') || (path[0] == '\\' && path[1] == '\\') ) ) { for ( i = 2; ; i++) { if (path[i] == '\0') break; @@ -1473,11 +1473,12 @@ * 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; + int mode, c, gotRW; + Tcl_Size modeArgc, i; 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 @@ -1684,12 +1685,11 @@ * 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; + int result = TCL_ERROR; Tcl_StatBuf statBuf; Tcl_Obj *oldScriptFile; Interp *iPtr; const char *string; Tcl_Channel chan; @@ -1713,15 +1713,15 @@ TclGetString(pathPtr), Tcl_PosixError(interp))); return result; } /* - * The eof character is \32 (^Z). This is standard on Windows, and Tcl - * uses it on every platform to allow for scripted documents. [Bug: 2040] + * The eof character is \x1A (^Z). Tcl uses it on every platform to allow + * for scripted documents. [Bug: 2040] */ - Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}"); + Tcl_SetChannelOption(interp, chan, "-eofchar", "\x1A"); /* * If the encoding is specified, set the channel to that encoding. * Otherwise use utf-8. If the encoding is unknown report an error. */ @@ -1754,12 +1754,12 @@ /* * If first character is not a BOM, append the remaining characters. * Otherwise, replace them. [Bug 3466099] */ - if (Tcl_ReadChars(chan, objPtr, -1, - memcmp(string, "\xef\xbb\xbf", 3)) == TCL_IO_FAILURE) { + if (Tcl_ReadChars(chan, objPtr, TCL_INDEX_NONE, + memcmp(string, "\xEF\xBB\xBF", 3)) == TCL_IO_FAILURE) { Tcl_CloseEx(interp, chan, 0); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); goto end; @@ -1771,18 +1771,17 @@ iPtr = (Interp *) interp; oldScriptFile = iPtr->scriptFile; iPtr->scriptFile = pathPtr; Tcl_IncrRefCount(iPtr->scriptFile); - string = TclGetStringFromObj(objPtr, &length); /* * TIP #280: Open a frame for the evaluated script. */ iPtr->evalFlags |= TCL_EVAL_FILE; - result = TclEvalEx(interp, string, length, 0, 1, NULL, string); + result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT); /* * Restore the original iPtr->scriptFile value, but because the value may * have hanged during evaluation, don't assume it currently points to * pathPtr. @@ -1798,13 +1797,14 @@ } else if (result == TCL_ERROR) { /* * Record information about where the error occurred. */ - const char *pathString = TclGetStringFromObj(pathPtr, &length); + Tcl_Size length; + const char *pathString = Tcl_GetStringFromObj(pathPtr, &length); unsigned limit = 150; - int overflow = (length > limit); + int overflow = ((unsigned)length > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (file \"%.*s%s\" line %d)", (overflow ? limit : (unsigned)length), pathString, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); @@ -1849,15 +1849,15 @@ return TCL_ERROR; } TclPkgFileSeen(interp, TclGetString(pathPtr)); /* - * The eof character is \32 (^Z). This is standard on Windows, and Tcl - * uses it on every platform to allow for scripted documents. [Bug: 2040] + * The eof character is \x1A (^Z). Tcl uses it on every platform to allow + * for scripted documents. [Bug: 2040] */ - Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}"); + Tcl_SetChannelOption(interp, chan, "-eofchar", "\x1A"); /* * If the encoding is specified, set the channel to that encoding. * Otherwise use utf-8. If the encoding is unknown report an error. */ @@ -1891,12 +1891,12 @@ /* * If first character is not a BOM, append the remaining characters. * Otherwise, replace them. [Bug 3466099] */ - if (Tcl_ReadChars(chan, objPtr, -1, - memcmp(string, "\xef\xbb\xbf", 3)) == TCL_IO_FAILURE) { + if (Tcl_ReadChars(chan, objPtr, TCL_INDEX_NONE, + memcmp(string, "\xEF\xBB\xBF", 3)) == TCL_IO_FAILURE) { Tcl_CloseEx(interp, chan, 0); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); Tcl_DecrRefCount(objPtr); @@ -1923,11 +1923,11 @@ return TclNREvalObjEx(interp, objPtr, 0, NULL, INT_MIN); } static int EvalFileCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *oldScriptFile = (Tcl_Obj *)data[0]; @@ -1950,18 +1950,18 @@ } 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_Size length; + const char *pathString = Tcl_GetStringFromObj(pathPtr, &length); + const unsigned limit = 150; + int overflow = ((unsigned)length > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (file \"%.*s%s\" line %d)", - (overflow ? limit : (unsigned int)length), pathString, + (overflow ? limit : (unsigned)length), pathString, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } Tcl_DecrRefCount(objPtr); return result; @@ -2050,11 +2050,11 @@ const char *id, *msg; msg = Tcl_ErrnoMsg(errno); id = Tcl_ErrnoId(); if (interp) { - Tcl_SetErrorCode(interp, "POSIX", id, msg, NULL); + Tcl_SetErrorCode(interp, "POSIX", id, msg, (void *)NULL); } return msg; } /* @@ -2061,12 +2061,11 @@ *---------------------------------------------------------------------- * * Tcl_FSStat -- * Calls 'statProc' of the filesystem corresponding to pathPtr. * - * Replaces the standard library routines stat. - * + * Replaces the standard library "stat" routine. * * Results: * See stat documentation. * * Side effects: @@ -2281,15 +2280,21 @@ 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 && fsPtr->utimeProc != NULL) { - return fsPtr->utimeProc(pathPtr, tval); + if (fsPtr == NULL) { + err = ENOENT; + } else { + if (fsPtr->utimeProc != NULL) { + return fsPtr->utimeProc(pathPtr, tval); + } + err = ENOTSUP; } - /* TODO: set errno here? Tcl_SetErrno(ENOENT); */ + Tcl_SetErrno(err); return -1; } /* *---------------------------------------------------------------------- @@ -2472,14 +2477,14 @@ } else if (listObj != NULL) { /* * It's a non-constant attribute list, so do a literal search. */ - int i, objc; + Tcl_Size i, objc; Tcl_Obj **objv; - if (Tcl_ListObjGetElements(NULL, listObj, &objc, &objv) != TCL_OK) { + if (TclListObjGetElementsM(NULL, listObj, &objc, &objv) != TCL_OK) { TclDecrRefCount(listObj); return TCL_ERROR; } for (i=0 ; inextPtr) { - ClientData retCd; + void *retCd; TclFSGetCwdProc2 *proc2; if (fsRecPtr->fsPtr->getCwdProc == NULL) { continue; } @@ -2645,12 +2650,13 @@ retVal = fsRecPtr->fsPtr->internalToNormalizedProc(retCd); Tcl_IncrRefCount(retVal); norm = TclFSNormalizeAbsolutePath(interp,retVal); if (norm != NULL) { /* - * Assign to global storage the pathname of the current directory - * and copy it into thread-local storage as well. + * Assign to global storage the pathname of the current + * directory and copy it into thread-local storage as + * well. * * At system startup multiple threads could in principle * call this function simultaneously, which is a little * peculiar, but should be fine given the mutex locks in * FSUPdateCWD. Once some value is assigned to the global @@ -2719,11 +2725,11 @@ * changed. */ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(tsdPtr->cwdPathPtr); - ClientData retCd = NULL; + void *retCd = NULL; Tcl_Obj *retVal, *norm; if (fsPtr == NULL || fsPtr->getCwdProc == NULL) { /* * There is no corresponding filesystem or the filesystem does not @@ -2792,15 +2798,15 @@ * are normalized pathnames, do something more efficient than * calling 'Tcl_FSEqualPaths', and in addition avoid a nasty * infinite loop bug when trying to normalize tsdPtr->cwdPathPtr. */ - size_t len1, len2; + Tcl_Size len1, len2; const char *str1, *str2; - str1 = TclGetStringFromObj(tsdPtr->cwdPathPtr, &len1); - str2 = TclGetStringFromObj(norm, &len2); + str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1); + str2 = Tcl_GetStringFromObj(norm, &len2); if ((len1 == len2) && (strcmp(str1, str2) == 0)) { /* * The pathname values are equal so retain the old pathname * object which is probably already shared and free the * normalized pathname that was just produced. @@ -2921,12 +2927,12 @@ Tcl_SetErrno(ENOENT); return -1; } if (fsPtr == &tclNativeFilesystem) { - ClientData cd; - ClientData oldcd = tsdPtr->cwdClientData; + void *cd; + void *oldcd = tsdPtr->cwdClientData; /* * Assume that the native filesystem has a getCwdProc and that it * is at version 2. */ @@ -3008,11 +3014,11 @@ Tcl_Obj *pathPtr, /* Pathname of the file containing the dynamic shared object. */ const char *sym1, const char *sym2, /* Names of two functions to find in the * dynamic shared object. */ - Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr, + Tcl_LibraryInitProc **proc1Ptr, Tcl_LibraryInitProc **proc2Ptr, /* Places to store pointers to the functions * named by sym1 and sym2. */ Tcl_LoadHandle *handlePtr, /* A place to store the token for the loaded * object. Can be passed to * (*unloadProcPtr)() to unload the file. */ @@ -3026,12 +3032,12 @@ symbols[1] = sym2; symbols[2] = NULL; res = Tcl_LoadFile(interp, pathPtr, symbols, 0, procPtrs, handlePtr); if (res == TCL_OK) { - *proc1Ptr = (Tcl_PackageInitProc *) procPtrs[0]; - *proc2Ptr = (Tcl_PackageInitProc *) procPtrs[1]; + *proc1Ptr = (Tcl_LibraryInitProc *) procPtrs[0]; + *proc2Ptr = (Tcl_LibraryInitProc *) procPtrs[1]; } else { *proc1Ptr = *proc2Ptr = NULL; } return res; @@ -3075,10 +3081,17 @@ * 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) { @@ -3097,11 +3110,11 @@ #ifdef hpux (void)shlibFile; return 1; #else - char *skipstr = getenv("TCL_TEMPLOAD_NO_UNLINK"); + WCHAR *skipstr = getenv("TCL_TEMPLOAD_NO_UNLINK"); if (skipstr && (skipstr[0] != '\0')) { return atoi(skipstr); } @@ -3593,95 +3606,10 @@ 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 -- @@ -3723,12 +3651,17 @@ */ int linkAction) /* Action to perform. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); - if (fsPtr != NULL && fsPtr->linkProc != NULL) { - return fsPtr->linkProc(pathPtr, toPtr, linkAction); + if (fsPtr) { + if (fsPtr->linkProc == NULL) { + Tcl_SetErrno(ENOTSUP); + return NULL; + } else { + return fsPtr->linkProc(pathPtr, toPtr, linkAction); + } } /* * If S_IFLNK isn't defined the machine doesn't support symbolic links, so * the file can't possibly be a symbolic link. Generate an EINVAL error, @@ -3781,14 +3714,16 @@ if (fsRecPtr->fsPtr->listVolumesProc != NULL) { Tcl_Obj *thisFsVolumes = fsRecPtr->fsPtr->listVolumesProc(); if (thisFsVolumes != NULL) { Tcl_ListObjAppendList(NULL, resultPtr, thisFsVolumes); - /* The refCount of each list returned by a `listVolumesProc` is - * already incremented. Do not hang onto the list, though. It - * belongs to the filesystem. Add its contents to * the result - * we are building, and then decrement the refCount. */ + /* + * The refCount of each list returned by a `listVolumesProc` + * is already incremented. Do not hang onto the list, though. + * It belongs to the filesystem. Add its contents to the + * result we are building, and then decrement the refCount. + */ Tcl_DecrRefCount(thisFsVolumes); } } fsRecPtr = fsRecPtr->nextPtr; } @@ -3860,20 +3795,21 @@ * If lenPtr is not null, sets it to the number of elements in the result. * *--------------------------------------------------------------------------- */ +#undef Tcl_FSSplitPath Tcl_Obj * Tcl_FSSplitPath( Tcl_Obj *pathPtr, /* The pathname to split. */ - int *lenPtr) /* A place to hold the number of pathname + Tcl_Size *lenPtr) /* A place to hold the number of pathname * elements. */ { Tcl_Obj *result = NULL; /* Just to squelch gcc warnings. */ const Tcl_Filesystem *fsPtr; char separator = '/'; - int driveNameLength; + Tcl_Size driveNameLength; const char *p; /* * Perform platform-specific splitting. */ @@ -3915,34 +3851,28 @@ * Add the remaining pathname elements to the list. */ for (;;) { const char *elementStart = p; - int length; + Tcl_Size length; while ((*p != '\0') && (*p != separator)) { p++; } length = p - elementStart; if (length > 0) { Tcl_Obj *nextElt; - - if (elementStart[0] == '~') { - TclNewLiteralStringObj(nextElt, "./"); - Tcl_AppendToObj(nextElt, elementStart, length); - } else { - nextElt = Tcl_NewStringObj(elementStart, length); - } - Tcl_ListObjAppendElement(NULL, result, nextElt); + nextElt = Tcl_NewStringObj(elementStart, length); + Tcl_ListObjAppendElement(NULL, result, nextElt); } if (*p++ == '\0') { break; } } if (lenPtr != NULL) { - TclListObjLength(NULL, result, lenPtr); + TclListObjLengthM(NULL, result, lenPtr); } return result; } /* *---------------------------------------------------------------------- @@ -3966,19 +3896,19 @@ 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 + 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. */ { - size_t pathLen; - const char *path = TclGetStringFromObj(pathPtr, &pathLen); + Tcl_Size pathLen; + const char *path = Tcl_GetStringFromObj(pathPtr, &pathLen); Tcl_PathType type; type = TclFSNonnativePathType(path, pathLen, filesystemPtrPtr, driveNameLengthPtr, driveNameRef); @@ -4015,16 +3945,16 @@ */ Tcl_PathType TclFSNonnativePathType( const char *path, /* Pathname to determine the type of. */ - int pathLen, /* Length of the pathname. */ + Tcl_Size pathLen, /* Length of the pathname. */ const Tcl_Filesystem **filesystemPtrPtr, /* If not NULL, a place to store a pointer to * the filesystem for this pathname when it is * an absolute pathname. */ - int *driveNameLengthPtr, /* If not NULL, a place to store the length of + 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 @@ -4057,15 +3987,15 @@ * filesystem continuously returning a list of volumes. */ if ((fsRecPtr->fsPtr != &tclNativeFilesystem) && (fsRecPtr->fsPtr->listVolumesProc != NULL)) { - int numVolumes; + Tcl_Size numVolumes; Tcl_Obj *thisFsVolumes = fsRecPtr->fsPtr->listVolumesProc(); if (thisFsVolumes != NULL) { - if (Tcl_ListObjLength(NULL, thisFsVolumes, &numVolumes) + if (TclListObjLengthM(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'. @@ -4072,21 +4002,21 @@ * * It would be better to signal an error here, but * Tcl_Panic seems a bit excessive. */ - numVolumes = -1; + numVolumes = TCL_INDEX_NONE; } while (numVolumes > 0) { Tcl_Obj *vol; - size_t len; + Tcl_Size len; const char *strVol; numVolumes--; Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol); - strVol = TclGetStringFromObj(vol,&len); - if ((size_t) pathLen < len) { + strVol = Tcl_GetStringFromObj(vol,&len); + if (pathLen < len) { continue; } if (strncmp(strVol, path, len) == 0) { type = TCL_PATH_ABSOLUTE; if (filesystemPtrPtr != NULL) { @@ -4298,15 +4228,21 @@ 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 && fsPtr->deleteFileProc != NULL) { - return fsPtr->deleteFileProc(pathPtr); + if (fsPtr == NULL) { + err = ENOENT; + } else { + if (fsPtr->deleteFileProc != NULL) { + return fsPtr->deleteFileProc(pathPtr); + } + err = ENOTSUP; } - Tcl_SetErrno(ENOENT); + Tcl_SetErrno(err); return -1; } /* *--------------------------------------------------------------------------- @@ -4329,15 +4265,21 @@ 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 && fsPtr->createDirectoryProc != NULL) { - return fsPtr->createDirectoryProc(pathPtr); + if (fsPtr == NULL) { + err = ENOENT; + } else { + if (fsPtr->createDirectoryProc != NULL) { + return fsPtr->createDirectoryProc(pathPtr); + } + err = ENOTSUP; } - Tcl_SetErrno(ENOENT); + Tcl_SetErrno(err); return -1; } /* *--------------------------------------------------------------------------- @@ -4357,19 +4299,18 @@ *--------------------------------------------------------------------------- */ int Tcl_FSCopyDirectory( - Tcl_Obj *srcPathPtr, /* - * The pathname of the directory to be copied. - */ + Tcl_Obj *srcPathPtr, /* The pathname of the directory to be + * copied. */ Tcl_Obj *destPathPtr, /* The pathname of the target directory. */ Tcl_Obj **errorPtr) /* If not NULL, and there is an error, a place - * to store a pointer to a new object, with - * its refCount already incremented, and - * containing the pathname name of file - * causing the error. */ + * to store a pointer to a new object, with + * its refCount already incremented, and + * containing the pathname name of file + * causing the error. */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr); @@ -4415,25 +4356,29 @@ * the name of the file that produced an error. * */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); - if (fsPtr == NULL || fsPtr->removeDirectoryProc == NULL) { + if (fsPtr == NULL) { Tcl_SetErrno(ENOENT); return -1; + } + if (fsPtr->removeDirectoryProc == NULL) { + Tcl_SetErrno(ENOTSUP); + return -1; } if (recursive) { Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL); if (cwdPtr != NULL) { const char *cwdStr, *normPathStr; - size_t cwdLen, normLen; + Tcl_Size cwdLen, normLen; Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (normPath != NULL) { - normPathStr = TclGetStringFromObj(normPath, &normLen); - cwdStr = TclGetStringFromObj(cwdPtr, &cwdLen); + normPathStr = Tcl_GetStringFromObj(normPath, &normLen); + cwdStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen); if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr, normLen) == 0)) { /* * The cwd is inside the directory to be removed. Change * the cwd to [file dirname $path]. @@ -4512,11 +4457,11 @@ /* * Call each of the "pathInFilesystem" functions in succession until the * corresponding filesystem is found. */ for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) { - ClientData clientData = NULL; + void *clientData = NULL; if (fsRecPtr->fsPtr->pathInFilesystemProc == NULL) { continue; } @@ -4569,11 +4514,11 @@ *--------------------------------------------------------------------------- */ static void NativeFreeInternalRep( - ClientData clientData) + void *clientData) { Tcl_Free(clientData); } /* Index: generic/tclIndexObj.c ================================================================== --- generic/tclIndexObj.c +++ generic/tclIndexObj.c @@ -3,19 +3,20 @@ * * This file implements objects of type "index". This object type is used * to lookup a keyword in a table of valid values and cache the index of * the matching entry. Also provides table-based argv/argc processing. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1997 Sun Microsystems, Inc. - * Copyright (c) 2006 Sam Bromley. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1997 Sun Microsystems, Inc. + * Copyright © 2006 Sam Bromley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" +#include /* * Prototypes for functions defined later in this file: */ @@ -23,33 +24,28 @@ 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 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. */ -static const Tcl_ObjType indexType = { +const Tcl_ObjType tclIndexType = { "index", /* name */ FreeIndex, /* freeIntRepProc */ DupIndex, /* dupIntRepProc */ UpdateStringOfIndex, /* updateStringProc */ - NULL /* setFromAnyProc */ + NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; /* * The definition of the internal representation of the "index" object; The * internalRep.twoPtrValue.ptr1 field of an object of "index" type will be a @@ -58,12 +54,12 @@ * Keep this structure declaration in sync with tclTestObj.c */ typedef struct { void *tablePtr; /* Pointer to the table of strings */ - size_t offset; /* Offset between table entries */ - size_t index; /* Selected index into table. */ + Tcl_Size offset; /* Offset between table entries */ + Tcl_Size index; /* Selected index into table. */ } IndexRep; /* * The following macros greatly simplify moving through a table... */ @@ -71,11 +67,11 @@ #define STRING_AT(table, offset) \ (*((const char *const *)(((char *)(table)) + (offset)))) #define NEXT_ENTRY(table, offset) \ (&(STRING_AT(table, offset))) #define EXPAND_OF(indexRep) \ - STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index) + (((indexRep)->index != TCL_INDEX_NONE) ? STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index) : "") /* *---------------------------------------------------------------------- * * GetIndexFromObjList -- @@ -110,23 +106,27 @@ * messages. */ int flags, /* 0 or TCL_EXACT */ int *indexPtr) /* Place to store resulting integer index. */ { - int objc, result, t; + 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 ineffiecient but simpler. + * of the code there. This is a bit inefficient but simpler. */ - result = Tcl_ListObjGetElements(interp, tableObjPtr, &objc, &objv); + result = TclListObjGetElementsM(interp, tableObjPtr, &objc, &objv); if (result != TCL_OK) { return result; } + + /* Return type is int* so caller should not be passing larger table */ + assert(objc <= INT_MAX); /* * Build a string table from the list. */ @@ -136,11 +136,11 @@ /* * An exact match is always chosen, so we can stop here. */ Tcl_Free((void *)tablePtr); - *indexPtr = t; + *indexPtr = (int) t; return TCL_OK; } tablePtr[t] = TclGetString(objv[t]); } @@ -164,83 +164,89 @@ * the strings are embedded in some other kind of array. * * Results: * If the value of objPtr is identical to or a unique abbreviation for * one of the entries in tablePtr, then the return value is TCL_OK and - * the index of the matching entry is stored at *indexPtr. If there isn't - * a proper match, then TCL_ERROR is returned and an error message is - * left in interp's result (unless interp is NULL). The msg argument is - * used in the error message; for example, if msg has the value "option" - * then the error message will say something like 'bad option "foo": must + * the index of the matching entry is stored at *indexPtr + * (unless indexPtr is NULL). If there isn't a proper match, then + * TCL_ERROR is returned and an error message is left in interp's + * result (unless interp is NULL). The msg argument is used in the + * error message; for example, if msg has the value "option" then + * the error message will say something like 'bad option "foo": must * be ...' * * Side effects: * The result of the lookup is cached as the internal rep of objPtr, so * that repeated lookups can be done quickly. * *---------------------------------------------------------------------- */ +#undef Tcl_GetIndexFromObjStruct int Tcl_GetIndexFromObjStruct( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr, /* Object containing the string to lookup. */ const void *tablePtr, /* The first string in the table. The second * string will be at this address plus the * offset, the third plus the offset again, * etc. The last entry must be NULL and there * must not be duplicate entries. */ - size_t offset, /* The number of bytes between entries */ + Tcl_Size offset, /* The number of bytes between entries */ const char *msg, /* Identifying word to use in error * messages. */ - int flags, /* 0 or TCL_EXACT */ - int *indexPtr) /* Place to store resulting integer index. */ + int flags, /* 0, TCL_EXACT, TCL_NULL_OK or TCL_INDEX_TEMP_TABLE */ + void *indexPtr) /* Place to store resulting index. */ { - int index, idx, numAbbrev; + Tcl_Size index, idx, numAbbrev; const char *key, *p1; const char *p2; const char *const *entryPtr; Tcl_Obj *resultPtr; IndexRep *indexRep; - const Tcl_ObjIntRep *irPtr; + const Tcl_ObjInternalRep *irPtr; - /* Protect against invalid values, like -1 or 0. */ - if (offset+1 <= sizeof(char *)) { - offset = sizeof(char *); + if (offset < (Tcl_Size) sizeof(char *)) { + return TclIndexInvalidError(interp, "struct offset", offset); } /* * See if there is a valid cached result from a previous lookup. */ - if (!(flags & TCL_INDEX_TEMP_TABLE)) { - irPtr = TclFetchIntRep(objPtr, &indexType); + 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) { - *indexPtr = indexRep->index; - return TCL_OK; + 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 = TclGetString(objPtr); - index = -1; + key = objPtr ? TclGetString(objPtr) : ""; + index = TCL_INDEX_NONE; numAbbrev = 0; + if (!*key && (flags & TCL_NULL_OK)) { + goto uncachedDone; + } /* * Scan the table looking for one of: * - An exact match (always preferred) * - A single abbreviation (allowed depending on flags) * - Several abbreviations (never allowed, but overridden by exact match) */ - for (entryPtr = (const char* const*)tablePtr, idx = 0; *entryPtr != NULL; + for (entryPtr = (const char *const *)tablePtr, idx = 0; *entryPtr != NULL; entryPtr = NEXT_ENTRY(entryPtr, offset), idx++) { for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) { if (*p1 == '\0') { index = idx; goto done; @@ -273,27 +279,46 @@ * Cache the found representation. Note that we want to avoid allocating a * new internal-rep if at all possible since that is potentially a slow * operation. */ - if (!(flags & TCL_INDEX_TEMP_TABLE)) { - irPtr = TclFetchIntRep(objPtr, &indexType); + if (objPtr && (index != TCL_INDEX_NONE) && !(flags & TCL_INDEX_TEMP_TABLE)) { + irPtr = TclFetchInternalRep(objPtr, &tclIndexType); if (irPtr) { indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1; } else { - Tcl_ObjIntRep ir; + Tcl_ObjInternalRep ir; indexRep = (IndexRep*)Tcl_Alloc(sizeof(IndexRep)); ir.twoPtrValue.ptr1 = indexRep; - Tcl_StoreIntRep(objPtr, &indexType, &ir); + Tcl_StoreInternalRep(objPtr, &tclIndexType, &ir); } indexRep->tablePtr = (void *) tablePtr; indexRep->offset = offset; indexRep->index = index; } - *indexPtr = 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) { /* @@ -301,39 +326,45 @@ */ int count = 0; TclNewObj(resultPtr); - entryPtr = (const char* const *)tablePtr; + entryPtr = (const char *const *)tablePtr; while ((*entryPtr != NULL) && !**entryPtr) { entryPtr = NEXT_ENTRY(entryPtr, offset); } Tcl_AppendStringsToObj(resultPtr, (numAbbrev>1 && !(flags & TCL_EXACT) ? "ambiguous " : "bad "), - msg, " \"", key, NULL); + msg, " \"", key, (void *)NULL); if (*entryPtr == NULL) { - Tcl_AppendStringsToObj(resultPtr, "\": no valid options", NULL); + Tcl_AppendStringsToObj(resultPtr, "\": no valid options", (void *)NULL); } else { Tcl_AppendStringsToObj(resultPtr, "\": must be ", - *entryPtr, NULL); + *entryPtr, (void *)NULL); entryPtr = NEXT_ENTRY(entryPtr, offset); while (*entryPtr != NULL) { - if (*NEXT_ENTRY(entryPtr, offset) == NULL) { + if ((*NEXT_ENTRY(entryPtr, offset) == NULL) && !(flags & TCL_NULL_OK)) { Tcl_AppendStringsToObj(resultPtr, (count > 0 ? "," : ""), - " or ", *entryPtr, NULL); + " or ", *entryPtr, (void *)NULL); } else if (**entryPtr) { - Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr, NULL); + Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr, (void *)NULL); count++; } entryPtr = NEXT_ENTRY(entryPtr, offset); } + if ((flags & TCL_NULL_OK)) { + Tcl_AppendStringsToObj(resultPtr, ", or \"\"", (void *)NULL); + } } Tcl_SetObjResult(interp, resultPtr); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", msg, key, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", msg, key, (void *)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 -- @@ -352,11 +383,11 @@ static void UpdateStringOfIndex( Tcl_Obj *objPtr) { - IndexRep *indexRep = (IndexRep *)TclFetchIntRep(objPtr, &indexType)->twoPtrValue.ptr1; + IndexRep *indexRep = (IndexRep *)TclFetchInternalRep(objPtr, &tclIndexType)->twoPtrValue.ptr1; const char *indexStr = EXPAND_OF(indexRep); Tcl_InitStringRep(objPtr, indexStr, strlen(indexStr)); } @@ -381,18 +412,18 @@ static void DupIndex( Tcl_Obj *srcPtr, Tcl_Obj *dupPtr) { - Tcl_ObjIntRep ir; + Tcl_ObjInternalRep ir; IndexRep *dupIndexRep = (IndexRep *)Tcl_Alloc(sizeof(IndexRep)); - memcpy(dupIndexRep, TclFetchIntRep(srcPtr, &indexType)->twoPtrValue.ptr1, + memcpy(dupIndexRep, TclFetchInternalRep(srcPtr, &tclIndexType)->twoPtrValue.ptr1, sizeof(IndexRep)); ir.twoPtrValue.ptr1 = dupIndexRep; - Tcl_StoreIntRep(dupPtr, &indexType, &ir); + Tcl_StoreInternalRep(dupPtr, &tclIndexType, &ir); } /* *---------------------------------------------------------------------- * @@ -412,11 +443,11 @@ static void FreeIndex( Tcl_Obj *objPtr) { - Tcl_Free(TclFetchIntRep(objPtr, &indexType)->twoPtrValue.ptr1); + Tcl_Free(TclFetchInternalRep(objPtr, &tclIndexType)->twoPtrValue.ptr1); objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- @@ -469,68 +500,68 @@ *---------------------------------------------------------------------- */ static int PrefixMatchObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int flags = 0, result, index; - int dummyLength, i, errorLength; + int flags = 0, result, dummy, i; + Tcl_Size dummyLength, 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 - }; + } index; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? table string"); return TCL_ERROR; } for (i = 1; i < (objc - 2); i++) { - if (Tcl_GetIndexFromObj(interp, objv[i], matchOptions, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], matchOptions, + sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum matchOptionsEnum) index) { + switch (index) { case PRFMATCH_EXACT: flags |= TCL_EXACT; break; case PRFMATCH_MESSAGE: if (i > objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing value for -message", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", NULL); + Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", (void *)NULL); return TCL_ERROR; } i++; - result = Tcl_ListObjLength(interp, objv[i], &errorLength); + result = TclListObjLengthM(interp, objv[i], &errorLength); if (result != TCL_OK) { return TCL_ERROR; } if ((errorLength % 2) != 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "error options must have an even number of elements", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", (void *)NULL); return TCL_ERROR; } errorPtr = objv[i]; break; } @@ -542,17 +573,17 @@ /* * Check that table is a valid list first, since we want to handle that * error case regardless of level. */ - result = Tcl_ListObjLength(interp, tablePtr, &dummyLength); + result = TclListObjLengthM(interp, tablePtr, &dummyLength); if (result != TCL_OK) { return result; } result = GetIndexFromObjList(interp, objPtr, tablePtr, message, flags, - &index); + &dummy); if (result != TCL_OK) { if (errorPtr != NULL && errorLength == 0) { Tcl_ResetResult(interp); return TCL_OK; } else if (errorPtr == NULL) { @@ -567,11 +598,11 @@ Tcl_ListObjAppendElement(interp, errorPtr, Tcl_NewWideIntObj(result)); return Tcl_SetReturnOptions(interp, errorPtr); } - result = Tcl_ListObjIndex(interp, tablePtr, index, &resultPtr); + result = Tcl_ListObjIndex(interp, tablePtr, dummy, &resultPtr); if (result != TCL_OK) { return result; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; @@ -593,34 +624,34 @@ *---------------------------------------------------------------------- */ static int PrefixAllObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int tableObjc, result, t; - size_t length, elemLength; + int result; + Tcl_Size length, elemLength, tableObjc, t; const char *string, *elemString; Tcl_Obj **tableObjv, *resultPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "table string"); return TCL_ERROR; } - result = Tcl_ListObjGetElements(interp, objv[1], &tableObjc, &tableObjv); + result = TclListObjGetElementsM(interp, objv[1], &tableObjc, &tableObjv); if (result != TCL_OK) { return result; } resultPtr = Tcl_NewListObj(0, NULL); - string = TclGetStringFromObj(objv[2], &length); + string = Tcl_GetStringFromObj(objv[2], &length); for (t = 0; t < tableObjc; t++) { - elemString = TclGetStringFromObj(tableObjv[t], &elemLength); + elemString = Tcl_GetStringFromObj(tableObjv[t], &elemLength); /* * A prefix cannot match if it is longest. */ @@ -651,36 +682,36 @@ *---------------------------------------------------------------------- */ static int PrefixLongestObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int tableObjc, result, t; - size_t i, length, elemLength, resultLength; + int result; + Tcl_Size i, length, elemLength, resultLength, tableObjc, t; const char *string, *elemString, *resultString; Tcl_Obj **tableObjv; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "table string"); return TCL_ERROR; } - result = Tcl_ListObjGetElements(interp, objv[1], &tableObjc, &tableObjv); + result = TclListObjGetElementsM(interp, objv[1], &tableObjc, &tableObjv); if (result != TCL_OK) { return result; } - string = TclGetStringFromObj(objv[2], &length); + string = Tcl_GetStringFromObj(objv[2], &length); resultString = NULL; resultLength = 0; for (t = 0; t < tableObjc; t++) { - elemString = TclGetStringFromObj(tableObjv[t], &elemLength); + elemString = Tcl_GetStringFromObj(tableObjv[t], &elemLength); /* * First check if the prefix string matches the element. A prefix * cannot match if it is longest. */ @@ -716,11 +747,11 @@ if (resultString[i] != elemString[i]) { /* * Adjust in case we stopped in the middle of a UTF char. */ - resultLength = TclUtfPrev(&resultString[i+1], + resultLength = Tcl_UtfPrev(&resultString[i+1], resultString) - resultString; break; } } } @@ -772,22 +803,21 @@ */ void Tcl_WrongNumArgs( Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments to print from objv. */ + Tcl_Size objc, /* Number of arguments to print from objv. */ Tcl_Obj *const objv[], /* Initial argument objects, which should be * included in the error message. */ const char *message) /* Error message to print after the leading * objects in objv. The message may be * NULL. */ { Tcl_Obj *objPtr; - int i; - size_t len, elemLen; + Tcl_Size i, len, elemLen; char flags; - Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *)interp; const char *elementStr; TclNewObj(objPtr); if (iPtr->flags & INTERP_ALTERNATE_WRONG_ARGS) { iPtr->flags &= ~INTERP_ALTERNATE_WRONG_ARGS; @@ -796,31 +826,23 @@ } 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 processing an an ensemble implementation, rewrite the results in + * terms of how the ensemble was invoked. */ if (iPtr->ensembleRewrite.sourceObjs != NULL) { - int toSkip = iPtr->ensembleRewrite.numInsertedObjs; - int toPrint = iPtr->ensembleRewrite.numRemovedObjs; - Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs; + Tcl_Size toSkip = iPtr->ensembleRewrite.numInsertedObjs; + Tcl_Size toPrint = iPtr->ensembleRewrite.numRemovedObjs; + Tcl_Obj *const *origObjv = TclEnsembleGetRewriteValues(interp); /* - * Check for spelling fixes, and substitute the fixed values. - */ - - if (origObjv[0] == NULL) { - origObjv = (Tcl_Obj *const *)origObjv[2]; - } - - /* - * We only know how to do rewriting if all the replaced objects are + * Only do rewrite the command if all the replaced objects are * actually arguments (in objv) to this function. Otherwise it just - * gets too complicated and we'd be better off just giving a slightly + * gets too complicated and it's to just give a slightly * confusing error message... */ if (objc < toSkip) { goto addNormalArgumentsToMessage; @@ -832,26 +854,26 @@ objv += toSkip; objc -= toSkip; /* - * We assume no object is of index type. + * Assume no object is of index type. */ for (i=0 ; itwoPtrValue.ptr1; elementStr = EXPAND_OF(indexRep); elemLen = strlen(elementStr); } else { - elementStr = TclGetStringFromObj(origObjv[i], &elemLen); + elementStr = Tcl_GetStringFromObj(origObjv[i], &elemLen); } flags = 0; len = TclScanElement(elementStr, elemLen, &flags); if (len != elemLen) { @@ -869,11 +891,11 @@ * Add a space if the word is not the last one (which has a * moderately complex condition here). */ if (itwoPtrValue.ptr1; - Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), NULL); + Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), (void *)NULL); } else { /* * Quote the argument if it contains spaces (Bug 942757). */ - elementStr = TclGetStringFromObj(objv[i], &elemLen); + elementStr = Tcl_GetStringFromObj(objv[i], &elemLen); flags = 0; len = TclScanElement(elementStr, elemLen, &flags); if (len != elemLen) { char *quotedElementStr = (char *)TclStackAlloc(interp, len + 1); @@ -918,12 +940,12 @@ /* * Append a space character (" ") if there is more text to follow * (either another element from objv, or the message string). */ - if (i 0) { curArg = objv[srcIndex]; srcIndex++; objc--; - str = TclGetStringFromObj(curArg, &length); + str = Tcl_GetStringFromObj(curArg, &length); if (length > 0) { c = str[1]; } else { c = 0; } /* - * Loop throught the argument descriptors searching for one with the + * Loop through the argument descriptors searching for one with the * matching key string. If found, leave a pointer to it in matchPtr. */ matchPtr = NULL; infoPtr = argTable; @@ -1146,18 +1169,25 @@ objc--; } break; } case TCL_ARGV_GENFUNC: { + + if (objc > INT_MAX) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "too many (%" TCL_SIZE_MODIFIER "d) arguments for TCL_ARGV_GENFUNC", objc)); + goto error; + } Tcl_ArgvGenFuncProc *handlerProc = (Tcl_ArgvGenFuncProc *) infoPtr->srcPtr; - objc = handlerProc(infoPtr->clientData, interp, objc, + int i = handlerProc(infoPtr->clientData, interp, (int) objc, &objv[srcIndex], infoPtr->dstPtr); - if (objc < 0) { + if (i < 0) { goto error; } + objc = i; break; } case TCL_ARGV_HELP: PrintUsage(interp, argTable); goto error; @@ -1235,27 +1265,26 @@ { const Tcl_ArgvInfo *infoPtr; int width, numSpaces; #define NUM_SPACES 20 static const char spaces[] = " "; - char tmp[TCL_DOUBLE_SPACE]; Tcl_Obj *msg; /* * First, compute the width of the widest option key, so that we can make * everything line up. */ width = 4; for (infoPtr = argTable; infoPtr->type != TCL_ARGV_END; infoPtr++) { - size_t length; + Tcl_Size length; if (infoPtr->keyStr == NULL) { continue; } length = strlen(infoPtr->keyStr); - if (length > (size_t)width) { + if (length > width) { width = length; } } /* @@ -1285,11 +1314,10 @@ *((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) { @@ -1331,16 +1359,16 @@ { static const char *const returnCodes[] = { "ok", "error", "return", "break", "continue", NULL }; - if (!TclHasIntRep(value, &indexType) + if (!TclHasInternalRep(value, &tclIndexType) && TclGetIntFromObj(NULL, value, codePtr) == TCL_OK) { return TCL_OK; } - if (Tcl_GetIndexFromObj(NULL, value, returnCodes, NULL, TCL_EXACT, - codePtr) == TCL_OK) { + if (Tcl_GetIndexFromObjStruct(NULL, value, returnCodes, + sizeof(char *), NULL, TCL_EXACT, codePtr) == TCL_OK) { return TCL_OK; } /* * Value is not a legal completion code. @@ -1349,11 +1377,11 @@ if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad completion code \"%s\": must be" " ok, error, return, break, continue, or an integer", TclGetString(value))); - Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_CODE", NULL); + Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_CODE", (void *)NULL); } return TCL_ERROR; } /* Index: generic/tclInt.decls ================================================================== --- generic/tclInt.decls +++ generic/tclInt.decls @@ -3,65 +3,50 @@ # 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 +# Copyright © 1998-1999 Scriptics Corporation. +# Copyright © 2001 Kevin B. Kenny. All rights reserved. +# Copyright © 2007 Daniel A. Steffen # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. library tcl # Define the unsupported generic interfaces. interface tclInt +scspec EXTERN # Declare each of the functions in the unsupported internal Tcl # interface. These interfaces are allowed to changed between versions. # Use at your own risk. Note that the position of functions should not # be changed between versions to avoid gratuitous incompatibilities. -# Replaced by Tcl_FSAccess in 8.4: -#declare 0 { -# int TclAccess(const char *path, int mode) -#} -#declare 1 { -# int TclAccessDeleteProc(TclAccessProc_ *proc) -#} -#declare 2 { -# int TclAccessInsertProc(TclAccessProc_ *proc) -#} declare 3 { void TclAllocateFreeObjects(void) } -# Replaced by TclpChdir in 8.1: -# declare 4 { -# int TclChdir(Tcl_Interp *interp, char *dirName) -# } declare 5 { - int TclCleanupChildren(Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, + int TclCleanupChildren(Tcl_Interp *interp, Tcl_Size numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan) } declare 6 { void TclCleanupCommand(Command *cmdPtr) } declare 7 { - size_t TclCopyAndCollapse(size_t count, const char *src, char *dst) + Tcl_Size TclCopyAndCollapse(Tcl_Size count, const char *src, char *dst) } # Removed in 9.0: #declare 8 { # int TclCopyChannelOld(Tcl_Interp *interp, Tcl_Channel inChan, # Tcl_Channel outChan, int toRead, Tcl_Obj *cmdPtr) #} - # TclCreatePipeline unofficially exported for use by BLT. - declare 9 { - int TclCreatePipeline(Tcl_Interp *interp, int argc, const char **argv, + Tcl_Size TclCreatePipeline(Tcl_Interp *interp, Tcl_Size argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr) } declare 10 { int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr, @@ -72,113 +57,57 @@ void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr) } declare 12 { void TclDeleteVars(Interp *iPtr, TclVarHashTable *tablePtr) } -# Removed in 8.5: -#declare 13 { -# int TclDoGlob(Tcl_Interp *interp, char *separators, -# Tcl_DString *headPtr, char *tail, Tcl_GlobTypeData *types) -#} declare 14 { int TclDumpMemoryInfo(void *clientData, int flags) } -# Removed in 8.1: -# declare 15 { -# void TclExpandParseValue(ParseValue *pvPtr, int needed) -# } declare 16 { void TclExprFloatError(Tcl_Interp *interp, double value) } -# Removed in 8.4: -#declare 17 { -# int TclFileAttrsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) -#} -#declare 18 { -# int TclFileCopyCmd(Tcl_Interp *interp, int argc, char **argv) -#} -#declare 19 { -# int TclFileDeleteCmd(Tcl_Interp *interp, int argc, char **argv) -#} -#declare 20 { -# int TclFileMakeDirsCmd(Tcl_Interp *interp, int argc, char **argv) -#} -#declare 21 { -# int TclFileRenameCmd(Tcl_Interp *interp, int argc, char **argv) -#} declare 22 { int TclFindElement(Tcl_Interp *interp, const char *listStr, - int listLength, const char **elementPtr, const char **nextPtr, - size_t *sizePtr, int *bracePtr) + Tcl_Size listLength, const char **elementPtr, const char **nextPtr, + Tcl_Size *sizePtr, int *bracePtr) } declare 23 { Proc *TclFindProc(Interp *iPtr, const char *procName) } # Replaced with macro (see tclInt.h) in Tcl 8.5.0, restored in 8.5.10 declare 24 { - size_t TclFormatInt(char *buffer, Tcl_WideInt n) + Tcl_Size TclFormatInt(char *buffer, Tcl_WideInt n) } declare 25 { void TclFreePackageInfo(Interp *iPtr) } -# Removed in 8.1: -# declare 26 { -# char *TclGetCwd(Tcl_Interp *interp) -# } -# Removed in 8.5: -#declare 27 { -# int TclGetDate(char *p, unsigned long now, long zone, -# unsigned long *timePtr) -#} declare 28 { Tcl_Channel TclpGetDefaultStdChannel(int type) } -# Removed in 8.4b2: -#declare 29 { -# Tcl_Obj *TclGetElementOfIndexedArray(Tcl_Interp *interp, -# int localIndex, Tcl_Obj *elemPtr, int flags) -#} -# Replaced by char *TclGetEnv(const char *name, Tcl_DString *valuePtr) in 8.1: -# declare 30 { -# char *TclGetEnv(const char *name) -# } declare 31 { const char *TclGetExtension(const char *name) } declare 32 { int TclGetFrame(Tcl_Interp *interp, const char *str, CallFrame **framePtrPtr) } -# Removed in 8.5: -#declare 33 { -# TclCmdProcType TclGetInterpProc(void) -#} # Removed in 9.0: -#declare 34 {deprecated {Use Tcl_GetIntForIndex}} { +#declare 34 { # 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 37 { +# int TclGetLoadedPackages(Tcl_Interp *interp, const char *targetName) +#} declare 38 { int TclGetNamespaceForQualName(Tcl_Interp *interp, const char *qualName, Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr, Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr, const char **simpleNamePtr) } declare 39 { - TclObjCmdProcType TclGetObjInterpProc(void) + Tcl_ObjCmdProc *TclGetObjInterpProc(void) } declare 40 { int TclGetOpenMode(Tcl_Interp *interp, const char *str, int *seekFlagPtr) } declare 41 { @@ -185,196 +114,94 @@ Tcl_Command TclGetOriginalCommand(Tcl_Command command) } declare 42 { const char *TclpGetUserHome(const char *name, Tcl_DString *bufferPtr) } -# Removed in 8.5a2: -#declare 43 { -# int TclGlobalInvoke(Tcl_Interp *interp, int argc, const char **argv, -# int flags) +declare 43 { + Tcl_ObjCmdProc2 *TclGetObjInterpProc2(void) +} +# Removed in 9.0: +#declare 44 { +# int TclGuessPackageName(const char *fileName, Tcl_DString *bufPtr) #} -declare 44 { - int TclGuessPackageName(const char *fileName, Tcl_DString *bufPtr) -} declare 45 { int TclHideUnsafeCommands(Tcl_Interp *interp) } declare 46 { int TclInExit(void) } -# Removed in 8.4b2: -#declare 47 { -# Tcl_Obj *TclIncrElementOfIndexedArray(Tcl_Interp *interp, -# int localIndex, Tcl_Obj *elemPtr, long incrAmount) -#} -# Removed in 8.4b2: -#declare 48 { -# Tcl_Obj *TclIncrIndexedScalar(Tcl_Interp *interp, int localIndex, -# long incrAmount) -#} -#declare 49 { -# Tcl_Obj *TclIncrVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, -# Tcl_Obj *part2Ptr, long incrAmount, int part1NotParsed) -#} # Removed in 9.0: #declare 50 { # void TclInitCompiledLocals(Tcl_Interp *interp, CallFrame *framePtr, # Namespace *nsPtr) #} declare 51 { int TclInterpInit(Tcl_Interp *interp) } -# Removed in 8.5a2: -#declare 52 { -# int TclInvoke(Tcl_Interp *interp, int argc, const char **argv, -# int flags) +# Removed in 9.0 +#declare 53 { +# int TclInvokeObjectCommand(void *clientData, Tcl_Interp *interp, +# Tcl_Size argc, const char **argv) #} -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 54 { +# int TclInvokeStringCommand(void *clientData, Tcl_Interp *interp, +# Tcl_Size objc, Tcl_Obj *const objv[]) +#} declare 55 { Proc *TclIsProc(Command *cmdPtr) } -# Replaced with TclpLoadFile in 8.1: -# declare 56 { -# int TclLoadFile(Tcl_Interp *interp, char *fileName, char *sym1, -# char *sym2, Tcl_PackageInitProc **proc1Ptr, -# Tcl_PackageInitProc **proc2Ptr) -# } -# Signature changed to take a length in 8.1: -# declare 57 { -# int TclLooksLikeInt(char *p) -# } declare 58 { Var *TclLookupVar(Tcl_Interp *interp, const char *part1, const char *part2, int flags, const char *msg, int createPart1, int createPart2, Var **arrayPtrPtr) } -# Replaced by Tcl_FSMatchInDirectory in 8.4 -#declare 59 { -# int TclpMatchFiles(Tcl_Interp *interp, char *separators, -# Tcl_DString *dirPtr, char *pattern, char *tail) -#} declare 60 { int TclNeedSpace(const char *start, const char *end) } declare 61 { Tcl_Obj *TclNewProcBodyObj(Proc *procPtr) } declare 62 { int TclObjCommandComplete(Tcl_Obj *cmdPtr) } -declare 63 { - int TclObjInterpProc(void *clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]) -} +# 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, int objc, Tcl_Obj *const objv[], + int TclObjInvoke(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags) } -# Removed in 8.5a2: -#declare 65 { -# int TclObjInvokeGlobal(Tcl_Interp *interp, int objc, -# Tcl_Obj *const objv[], int flags) -#} -#declare 66 { -# int TclOpenFileChannelDeleteProc(TclOpenFileChannelProc_ *proc) -#} -#declare 67 { -# int TclOpenFileChannelInsertProc(TclOpenFileChannelProc_ *proc) -#} -# Replaced by Tcl_FSAccess in 8.4: -#declare 68 { -# int TclpAccess(const char *path, int mode) -#} declare 69 { - void *TclpAlloc(size_t size) -} -#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) -#} + void *TclpAlloc(TCL_HASH_TYPE size) +} declare 74 { void TclpFree(void *ptr) } declare 75 { - Tcl_WideUInt TclpGetClicks(void) + unsigned long long TclpGetClicks(void) } declare 76 { - Tcl_WideUInt TclpGetSeconds(void) + unsigned long long TclpGetSeconds(void) } - # Removed in 9.0: #declare 77 { # void TclpGetTime(Tcl_Time *time) #} -# Removed in 8.6: -#declare 78 { -# int TclpGetTimeZone(unsigned long time) -#} -# Replaced by Tcl_FSListVolumes in 8.4: -#declare 79 { -# int TclpListVolumes(Tcl_Interp *interp) -#} -# Replaced by Tcl_FSOpenFileChannel in 8.4: -#declare 80 { -# Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp, char *fileName, -# char *modeString, int permissions) -#} declare 81 { - void *TclpRealloc(void *ptr, size_t size) -} -#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) -# } + 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) } -# 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, @@ -382,19 +209,10 @@ 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 { @@ -401,23 +219,14 @@ 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) -} +# 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, @@ -425,33 +234,19 @@ } # Removed in 9.0: #declare 104 { # int TclSockMinimumBuffersOld(int sock, int size) #} -# Replaced by Tcl_FSStat in 8.4: -#declare 105 { -# int TclStat(const char *path, Tcl_StatBuf *buf) -#} -#declare 106 { -# int TclStatDeleteProc(TclStatProc_ *proc) -#} -#declare 107 { -# int TclStatInsertProc(TclStatProc_ *proc) -#} declare 108 { void TclTeardownNamespace(Namespace *nsPtr) } declare 109 { int TclUpdateReturnInfo(Interp *iPtr) } declare 110 { - int TclSockMinimumBuffers(void *sock, int size) + int TclSockMinimumBuffers(void *sock, Tcl_Size size) } -# Removed in 8.1: -# declare 110 { -# char *TclWordEnd(char *start, char *lastChar, int nested, int *semiPtr) -# } # Procedures used in conjunction with Tcl namespaces. They are # defined here instead of in tcl.decls since they are not stable yet. declare 111 { @@ -459,35 +254,30 @@ Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc) } # Removed in 9.0: #declare 112 { -# int Tcl_AppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr, +# int TclAppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr, # Tcl_Obj *objPtr) #} -# Removed in 9.0: #declare 113 { -# Tcl_Namespace *Tcl_CreateNamespace(Tcl_Interp *interp, const char *name, +# Tcl_Namespace *TclCreateNamespace(Tcl_Interp *interp, const char *name, # void *clientData, Tcl_NamespaceDeleteProc *deleteProc) #} -# Removed in 9.0: #declare 114 { -# void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr) +# void TclDeleteNamespace(Tcl_Namespace *nsPtr) #} -# Removed in 9.0: #declare 115 { -# int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr, +# int TclExport(Tcl_Interp *interp, Tcl_Namespace *nsPtr, # const char *pattern, int resetListFirst) #} -# Removed in 9.0: #declare 116 { -# Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, const char *name, +# Tcl_Command TclFindCommand(Tcl_Interp *interp, const char *name, # Tcl_Namespace *contextNsPtr, int flags) #} -# Removed in 9.0: #declare 117 { -# Tcl_Namespace *Tcl_FindNamespace(Tcl_Interp *interp, const char *name, +# Tcl_Namespace *TclFindNamespace(Tcl_Interp *interp, const char *name, # Tcl_Namespace *contextNsPtr, int flags) #} declare 118 { int Tcl_GetInterpResolvers(Tcl_Interp *interp, const char *name, Tcl_ResolverInfo *resInfo) @@ -500,37 +290,33 @@ 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, +# int TclForgetImport(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) +# Tcl_Command TclGetCommandFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr) #} -# Removed in 9.0: #declare 123 { -# void Tcl_GetCommandFullName(Tcl_Interp *interp, Tcl_Command command, +# void TclGetCommandFullName(Tcl_Interp *interp, Tcl_Command command, # Tcl_Obj *objPtr) #} -# Removed in 9.0: #declare 124 { -# Tcl_Namespace *Tcl_GetCurrentNamespace(Tcl_Interp *interp) +# Tcl_Namespace *TclGetCurrentNamespace_(Tcl_Interp *interp) #} -# Removed in 9.0: #declare 125 { -# Tcl_Namespace *Tcl_GetGlobalNamespace(Tcl_Interp *interp) +# Tcl_Namespace *TclGetGlobalNamespace_(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, +# int TclImport(Tcl_Interp *interp, Tcl_Namespace *nsPtr, # const char *pattern, int allowOverwrite) #} declare 128 { void Tcl_PopCallFrame(Tcl_Interp *interp) } @@ -544,42 +330,21 @@ 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 +# Removed in 9.0: +#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 { @@ -607,59 +372,38 @@ TclHandle TclHandlePreserve(TclHandle handle) } declare 149 { void TclHandleRelease(TclHandle handle) } - -# Added for Tcl 8.2 - declare 150 { int TclRegAbout(Tcl_Interp *interp, Tcl_RegExp re) } declare 151 { - void TclRegExpRangeUniChar(Tcl_RegExp re, size_t index, size_t *startPtr, - size_t *endPtr) + void TclRegExpRangeUniChar(Tcl_RegExp re, Tcl_Size index, Tcl_Size *startPtr, + Tcl_Size *endPtr) } declare 152 { void TclSetLibraryPath(Tcl_Obj *pathPtr) } declare 153 { Tcl_Obj *TclGetLibraryPath(void) } - -# moved to tclTest.c (static) in 8.3.2/8.4a2 -#declare 154 { -# int TclTestChannelCmd(void *clientData, -# Tcl_Interp *interp, int argc, char **argv) -#} -#declare 155 { -# int TclTestChannelEventCmd(void *clientData, -# Tcl_Interp *interp, int argc, char **argv) -#} - declare 156 { void TclRegError(Tcl_Interp *interp, const char *msg, int status) } declare 157 { Var *TclVarTraceExists(Tcl_Interp *interp, const char *varName) } -# REMOVED - use public Tcl_SetStartupScript() +# Removed in 9.0: #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 { @@ -689,56 +433,41 @@ } # New function due to TIP #33 declare 166 { int TclListObjSetElement(Tcl_Interp *interp, Tcl_Obj *listPtr, - int index, Tcl_Obj *valuePtr) + Tcl_Size index, Tcl_Obj *valuePtr) } -# VFS-aware versions of Tcl*StartupScriptFileName (158 and 159 above) -# REMOVED - use public Tcl_SetStartupScript() +# Removed in 9.0: #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[]) + Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags, + Tcl_Size objc, Tcl_Obj *const objv[]) } declare 171 { int TclCheckExecutionTraces(Tcl_Interp *interp, const char *command, - size_t numChars, Command *cmdPtr, int result, int traceFlags, - int objc, Tcl_Obj *const objv[]) + Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags, + Tcl_Size objc, Tcl_Obj *const objv[]) } declare 172 { int TclInThreadExit(void) } - -# added for 8.4.2 - declare 173 { - int TclUniCharMatch(const Tcl_UniChar *string, size_t strLen, - const Tcl_UniChar *pattern, size_t ptnLen, int flags) -} - -# 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 - + 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 { @@ -746,99 +475,30 @@ } 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 +# Removed in 9.0: #declare 178 { -# void Tcl_SetStartupScript(Tcl_Obj *pathPtr, const char *encodingName) +# void TclSetStartupScript(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 +# Tcl_Obj *TclGetStartupScript(const char **encodingNamePtr) +#} #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) } @@ -866,20 +526,10 @@ } 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) @@ -886,11 +536,11 @@ } declare 214 { void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding) } declare 215 { - void *TclStackAlloc(Tcl_Interp *interp, size_t numBytes) + void *TclStackAlloc(Tcl_Interp *interp, TCL_HASH_TYPE numBytes) } declare 216 { void TclStackFree(Tcl_Interp *interp, void *freePtr) } declare 217 { @@ -898,42 +548,52 @@ Tcl_Namespace *namespacePtr, int isProcCallFrame) } declare 218 { void TclPopStackFrame(Tcl_Interp *interp) } +# TIP 431: temporary directory creation function +declare 219 { + Tcl_Obj *TclpCreateTemporaryDirectory(Tcl_Obj *dirObj, + Tcl_Obj *basenameObj) +} # for use in tclTest.c + +# TIP 625: for unit testing - create list objects with span +declare 221 { + Tcl_Obj *TclListTestObj(size_t length, size_t leadingSpace, size_t endSpace) +} +# TIP 625: for unit testing - check list invariants +declare 222 { + void TclListObjValidate(Tcl_Interp *interp, Tcl_Obj *listObj) +} +# Bug 7371b6270b +declare 223 { + void *TclGetCStackPtr(void) +} declare 224 { TclPlatformType *TclGetPlatform(void) } - -# declare 225 { Tcl_Obj *TclTraceDictPath(Tcl_Interp *interp, Tcl_Obj *rootPtr, - int keyc, Tcl_Obj *const keyv[], int flags) + Tcl_Size keyc, Tcl_Obj *const keyv[], int flags) } declare 226 { int TclObjBeingDeleted(Tcl_Obj *objPtr) } declare 227 { - void TclSetNsPath(Namespace *nsPtr, size_t pathLength, + void TclSetNsPath(Namespace *nsPtr, Tcl_Size pathLength, Tcl_Namespace *pathAry[]) } -# Used to be needed for TclOO-extension; unneeded now that TclOO is in the -# core and NRE-enabled -# declare 228 { -# int TclObjInterpProcCore(Tcl_Interp *interp, Tcl_Obj *procNameObj, -# int skip, ProcErrorProc *errorProc) -# } declare 229 { int TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr, const char *myName, int myFlags, int index) } declare 230 { Var *TclObjLookupVar(Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, int flags, const char *msg, - const int createPart1, const int createPart2, Var **arrayPtrPtr) + int createPart1, int createPart2, Var **arrayPtrPtr) } declare 231 { int TclGetNamespaceFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr) } @@ -953,13 +613,11 @@ int *newPtr) } declare 235 { void TclInitVarHashTable(TclVarHashTable *tablePtr, Namespace *nsPtr) } - - -# TIP 337 made this one public +# Removed in 9.0: #declare 236 { # void TclBackgroundException(Tcl_Interp *interp, int code) #} # TIP #285: Script cancellation support. @@ -969,15 +627,15 @@ # NRE functions for "rogue" extensions to exploit NRE; they will need to # include NRE.h too. declare 238 { int TclNRInterpProc(void *clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]) + Tcl_Size objc, Tcl_Obj *const objv[]) } declare 239 { int TclNRInterpProcCore(Tcl_Interp *interp, Tcl_Obj *procNameObj, - int skip, ProcErrorProc *errorProc) + Tcl_Size skip, ProcErrorProc *errorProc) } declare 240 { int TclNRRunCallbacks(Tcl_Interp *interp, int result, struct NRE_callback *rootPtr) } @@ -984,11 +642,11 @@ declare 241 { int TclNREvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word) } declare 242 { - int TclNREvalObjv(Tcl_Interp *interp, int objc, + int TclNREvalObjv(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags, Command *cmdPtr) } # Tcl_Obj leak detection support. declare 243 { @@ -1001,20 +659,20 @@ } declare 245 { Tcl_HashTable *TclGetNamespaceCommandTable(Tcl_Namespace *nsPtr) } declare 246 { - int TclInitRewriteEnsemble(Tcl_Interp *interp, size_t numRemoved, - size_t numInserted, Tcl_Obj *const *objv) + int TclInitRewriteEnsemble(Tcl_Interp *interp, Tcl_Size numRemoved, + Tcl_Size numInserted, Tcl_Obj *const *objv) } declare 247 { void TclResetRewriteEnsemble(Tcl_Interp *interp, int isRootEnsemble) } declare 248 { int TclCopyChannel(Tcl_Interp *interp, Tcl_Channel inChan, - Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr) + Tcl_Channel outChan, long long toRead, Tcl_Obj *cmdPtr) } declare 249 { char *TclDoubleDigits(double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr) @@ -1025,312 +683,122 @@ } # Allow extensions for optimization declare 251 { int TclRegisterLiteral(void *envPtr, - const char *bytes, size_t length, int flags) + const char *bytes, Tcl_Size length, int flags) } # Exporting of the internal API to variables. declare 252 { Tcl_Obj *TclPtrGetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, - const int flags) + int flags) } declare 253 { Tcl_Obj *TclPtrSetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, - Tcl_Obj *newValuePtr, const int flags) + Tcl_Obj *newValuePtr, int flags) } declare 254 { Tcl_Obj *TclPtrIncrObjVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, - Tcl_Obj *incrPtr, const int flags) + Tcl_Obj *incrPtr, int flags) } declare 255 { int TclPtrObjMakeUpvar(Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags) } declare 256 { int TclPtrUnsetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, - Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags) -} -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) -} - + 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 259 { + int TclMSB(size_t n) +} +declare 261 { + void TclUnusedStubEntry(void) +} ############################################################################## # 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} { +# Platform specific functions + +# Removed in 9.0 +#declare 0 {unix win} { +# void TclWinConvertError(unsigned errCode) +#} +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 { + size_t 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, size_t 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: Index: generic/tclInt.h ================================================================== --- generic/tclInt.h +++ generic/tclInt.h @@ -59,30 +59,23 @@ * greater modularity. The order of the three groups of #includes is * important. For example, stdio.h is needed by tcl.h. */ #include "tclPort.h" +#include "tclBrodnik.h" #include #include #include -#ifdef NO_STDLIB_H -# include "../compat/stdlib.h" -#else -# include -#endif +#include +#include #ifdef NO_STRING_H #include "../compat/string.h" #else #include #endif -#if !defined(STDC_HEADERS) && !defined(__STDC__) && !defined(__C99__FUNC__) \ - && !defined(__cplusplus) && !defined(_MSC_VER) && !defined(__ICC) -typedef int ptrdiff_t; -#endif -#include #include /* * Ensure WORDS_BIGENDIAN is defined correctly: * Needs to happen here in addition to configure to work with fat compiles on @@ -113,31 +106,26 @@ * 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 +#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(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 +#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 @@ -180,11 +168,11 @@ Tcl_ResolveRuntimeVarProc *fetchProc; Tcl_ResolveVarDeleteProc *deleteProc; } Tcl_ResolvedVarInfo; typedef int (Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp, - const char *name, int length, Tcl_Namespace *context, + const char *name, Tcl_Size length, Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr); typedef int (Tcl_ResolveVarProc)(Tcl_Interp *interp, const char *name, Tcl_Namespace *context, int flags, Tcl_Var *rPtr); @@ -214,10 +202,18 @@ * - Bug #631741 - do not use special namespace or interp resolvers */ #define TCL_AVOID_RESOLVERS 0x40000 +/* + *---------------------------------------------------------------- + * Declarations for the HAMT interface routines. + *---------------------------------------------------------------- + */ + +#include "tclHAMT.h" + /* *---------------------------------------------------------------- * Data structures related to namespaces. *---------------------------------------------------------------- */ @@ -224,19 +220,22 @@ typedef struct Tcl_Ensemble Tcl_Ensemble; typedef struct NamespacePathEntry NamespacePathEntry; /* - * Special hashtable for variables: this is just a Tcl_HashTable with an nsPtr - * field added at the end: in this way variables can find their namespace - * without having to copy a pointer in their struct: they can access it via - * their hPtr->tablePtr. + * Special hashtable for variables: This is just a Tcl_HashTable with nsPtr + * and arrayPtr fields added at the end so that variables can find their + * namespace and possibly containing array without having to copy a pointer in + * their struct by accessing them via their hPtr->tablePtr. */ typedef struct TclVarHashTable { Tcl_HashTable table; struct Namespace *nsPtr; +#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 :( */ @@ -282,20 +281,24 @@ 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. */ - size_t activationCount; /* Number of "activations" or active call + Tcl_Size activationCount; /* Number of "activations" or active call * frames for this namespace that are on the * Tcl call stack. The namespace won't be * freed until activationCount becomes zero. */ - size_t refCount; /* Count of references by namespaceName + Tcl_Size refCount; /* Count of references by namespaceName * objects. The namespace can't be freed until * refCount becomes zero. */ Tcl_HashTable cmdTable; /* Contains all the commands currently * registered in the namespace. Indexed by * strings; values have type (Command *). @@ -305,27 +308,20 @@ * 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 + Tcl_Obj *exportPatternList; + /* Set of "string match" style patterns that + * specify which commands are exported. + * No namespace qualifiers are allowed. */ + Tcl_Size cmdRefEpoch; /* Incremented if a newly added command * shadows a command for which this namespace * has already cached a Command* pointer; this * causes all its cached Command* pointers to * be invalidated. */ - size_t resolverEpoch; /* Incremented whenever (a) the name + Tcl_Size resolverEpoch; /* Incremented whenever (a) the name * resolution rules change for this namespace * or (b) a newly added command shadows a * command that is compiled to bytecodes. This * invalidates all byte codes compiled in the * namespace, causing the code to be @@ -348,11 +344,11 @@ * usual variable resolution mechanism in Tcl. * This procedure is invoked within * LookupCompiledLocal to resolve variable * references within the namespace at compile * time. */ - size_t exportLookupEpoch; /* Incremented whenever a command is added to + Tcl_Size exportLookupEpoch; /* Incremented whenever a command is added to * a namespace, removed from a namespace or * the exports of a namespace are changed. * Allows TIP#112-driven command lists to be * validated efficiently. */ Tcl_Ensemble *ensembles; /* List of structures that contain the details @@ -359,11 +355,11 @@ * of the ensembles that are implemented on * top of this namespace. */ Tcl_Obj *unknownHandlerPtr; /* A script fragment to be used when command * resolution in this namespace fails. TIP * 181. */ - size_t commandPathLength; /* The length of the explicit path. */ + Tcl_Size commandPathLength; /* The length of the explicit path. */ NamespacePathEntry *commandPathArray; /* The explicit path of the namespace as an * array. */ NamespacePathEntry *commandPathSourceList; /* Linked list of path entries that point to @@ -397,33 +393,32 @@ /* * Flags used to represent the status of a namespace: * * NS_DYING - 1 means Tcl_DeleteNamespace has been called to delete the - * namespace but there are still active call frames on the Tcl + * namespace. There may still be active call frames on the Tcl * stack that refer to the namespace. When the last call frame - * referring to it has been popped, it's variables and command - * will be destroyed and it will be marked "dead" (NS_DEAD). The - * namespace can no longer be looked up by name. + * referring to it has been popped, its remaining variables and + * commands are destroyed and it is marked "dead" (NS_DEAD). + * NS_TEARDOWN -1 means that TclTeardownNamespace has already been called on + * this namespace and it should not be called again [Bug 1355942]. * NS_DEAD - 1 means Tcl_DeleteNamespace has been called to delete the - * namespace and no call frames still refer to it. Its variables - * and command have already been destroyed. This bit allows the - * namespace 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] + * 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_KILLED 0x04 +#define NS_TEARDOWN 0x04 +#define NS_KILLED 0x04 /* Same as NS_TEARDOWN (Deprecated) */ #define NS_SUPPRESS_COMPILATION 0x08 /* * Flags passed to TclGetNamespaceForQualName: * @@ -449,11 +444,11 @@ Tcl_Command token; /* The token for the command that provides * ensemble support for the namespace, or NULL * if the command has been deleted (or never * existed; the global namespace never has an * ensemble command.) */ - size_t epoch; /* The epoch at which this ensemble's table of + Tcl_Size epoch; /* The epoch at which this ensemble's table of * exported commands is valid. */ char **subcommandArrayPtr; /* Array of ensemble subcommand names. At all * consistent points, this will have the same * number of entries as there are entries in * the subcommandTable hash. */ @@ -475,11 +470,11 @@ * this field points to this ensemble, the * structure has already been unlinked from * all lists, and cannot be found by scanning * the list from the namespace's ensemble * field. */ - int flags; /* ORed combo of TCL_ENSEMBLE_PREFIX, + int flags; /* OR'ed combo of TCL_ENSEMBLE_PREFIX, * ENSEMBLE_DEAD and ENSEMBLE_COMPILE. */ /* OBJECT FIELDS FOR ENSEMBLE CONFIGURATION */ Tcl_Obj *subcommandDict; /* Dictionary providing mapping from @@ -502,15 +497,15 @@ * the arguments to the ensemble command * (including objv[0]) and will have the * results passed directly back to the caller * (including the error code) unless the code * is TCL_CONTINUE in which case the - * subcommand will be reparsed by the ensemble + * subcommand will be re-parsed by the ensemble * core, presumably because the ensemble * itself has been updated. */ Tcl_Obj *parameterList; /* List of ensemble parameter names. */ - int numParameters; /* Cached number of parameters. This is either + Tcl_Size numParameters; /* Cached number of parameters. This is either * 0 (if the parameterList field is NULL) or * the length of the list in the parameterList * field. */ } EnsembleConfig; @@ -562,11 +557,11 @@ * interested in: OR-ed combination of * TCL_TRACE_RENAME, TCL_TRACE_DELETE. */ struct CommandTrace *nextPtr; /* Next in list of traces associated with a * particular command. */ - size_t refCount; /* Used to ensure this structure is not + Tcl_Size refCount; /* Used to ensure this structure is not * deleted too early. Keeps track of how many * pieces of code have a pointer to this * structure. */ } CommandTrace; @@ -635,11 +630,11 @@ } value; } Var; typedef struct VarInHash { Var var; - size_t refCount; /* Counts number of active uses of this + 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 @@ -646,11 +641,11 @@ * record can't be deleted until refCount * becomes 0. */ Tcl_HashEntry entry; /* The hash table entry that refers to this * variable. This is used to find the name of * the variable and to delete it from its - * hashtable if it is no longer needed. It + * hash table if it is no longer needed. It * also holds the variable's name. */ } VarInHash; /* * Flag bits for variables. The first two (VAR_ARRAY and VAR_LINK) are @@ -657,11 +652,11 @@ * mutually exclusive and give the "type" of the variable. If none is set, * this is a scalar variable. * * VAR_ARRAY - 1 means this is an array variable rather than * a scalar variable or link. The "tablePtr" - * field points to the array's hashtable for its + * field points to the array's hash table for its * elements. * VAR_LINK - 1 means this Var structure contains a pointer * to another Var structure that either has the * real value or is itself another VAR_LINK * pointer. Variables like this come about @@ -670,16 +665,16 @@ * 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 + * VAR_IN_HASHTABLE - 1 means this variable is in a hash table and + * the Var structure is malloc'ed. 0 if it is a * local variable that was assigned a slot in a * procedure frame by the compiler so the Var * storage is part of the call frame. - * VAR_DEAD_HASH 1 means that this var's entry in the hashtable + * VAR_DEAD_HASH 1 means that this var's entry in the hash table * has already been deleted. * VAR_ARRAY_ELEMENT - 1 means that this variable is an array * element, so it is not legal for it to be an * array itself (the VAR_ARRAY flag had better * not be set). @@ -822,10 +817,18 @@ * 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) \ @@ -867,30 +870,42 @@ #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 TclIsVarDirectReadable(varPtr) \ - ( !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ)) \ - && (varPtr)->value.objPtr) +#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) \ - !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_WRITE|VAR_DEAD_HASH)) + (!TclIsVarTricky(varPtr,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)) + (!TclIsVarTricky(varPtr,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) + ( (!TclIsVarTricky(varPtr,VAR_TRACED_READ|VAR_TRACED_WRITE)) \ + && (varPtr)->value.objPtr) #define TclIsVarDirectReadable2(varPtr, arrayPtr) \ (TclIsVarDirectReadable(varPtr) &&\ (!(arrayPtr) || !((arrayPtr)->flags & VAR_TRACED_READ))) @@ -907,11 +922,13 @@ * Data structures related to procedures. These are used primarily in * tclProc.c, tclCompile.c, and tclExecute.c. *---------------------------------------------------------------- */ -#if defined(__GNUC__) && (__GNUC__ > 2) +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define TCLFLEXARRAY +#elif defined(__GNUC__) && (__GNUC__ > 2) # define TCLFLEXARRAY 0 #else # define TCLFLEXARRAY 1 #endif @@ -938,18 +955,17 @@ typedef struct CompiledLocal { struct CompiledLocal *nextPtr; /* Next compiler-recognized local variable for * this procedure, or NULL if this is the last * local. */ - size_t nameLength; /* The number of bytes in local variable's name. + Tcl_Size nameLength; /* The number of bytes in local variable's name. * Among others used to speed up var lookups. */ - int frameIndex; /* Index in the array of compiler-assigned + Tcl_Size frameIndex; /* Index in the array of compiler-assigned * variables in the procedure call frame. */ - 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. */ +#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 @@ -956,10 +972,16 @@ * 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! */ @@ -972,11 +994,11 @@ */ typedef struct Proc { struct Interp *iPtr; /* Interpreter for which this command is * defined. */ - size_t refCount; /* Reference count: 1 if still present in + Tcl_Size refCount; /* Reference count: 1 if still present in * command table plus 1 for each call to the * procedure that is currently active. This * structure can be freed when refCount * becomes zero. */ struct Command *cmdPtr; /* Points to the Command structure for this @@ -983,12 +1005,12 @@ * procedure. This is used to get the * namespace in which to execute the * procedure. */ Tcl_Obj *bodyPtr; /* Points to the ByteCode object for * procedure's body command. */ - int numArgs; /* Number of formal parameters. */ - int numCompiledLocals; /* Count of local variables recognized by the + Tcl_Size numArgs; /* Number of formal parameters. */ + Tcl_Size numCompiledLocals; /* Count of local variables recognized by the * compiler including arguments and * temporaries. */ CompiledLocal *firstLocalPtr; /* Pointer to first of the procedure's * compiler-allocated local variables, or NULL @@ -1011,13 +1033,17 @@ * The structure below defines a command trace. This is used to allow Tcl * clients to find out whenever a command is about to be executed. */ typedef struct Trace { - int level; /* Only trace commands at nesting level less + Tcl_Size level; /* Only trace commands at nesting level less * than or equal to this. */ +#if TCL_MAJOR_VERSION > 8 + Tcl_CmdObjTraceProc2 *proc; /* Procedure to call to trace command. */ +#else Tcl_CmdObjTraceProc *proc; /* Procedure to call to trace command. */ +#endif void *clientData; /* Arbitrary value to pass to proc. */ 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; @@ -1056,10 +1082,106 @@ * "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 @@ -1089,12 +1211,12 @@ * 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_Size refCount; + Tcl_Size numVars; Tcl_Obj *varName0; } LocalCache; #define localName(framePtr, i) \ ((&((framePtr)->localCachePtr->varName0))[(i)]) @@ -1110,11 +1232,11 @@ * treated as references to namespace vars; * varTablePtr and compiledLocals are ignored. * If FRAME_IS_PROC is set, the frame was * pushed to execute a Tcl procedure and may * have local vars. */ - int objc; /* This and objv below describe the arguments + Tcl_Size objc; /* This and objv below describe the arguments * for this procedure call. */ Tcl_Obj *const *objv; /* Array of argument objects. */ struct CallFrame *callerPtr; /* Value of interp->framePtr when this * procedure was invoked (i.e. next higher in @@ -1124,11 +1246,11 @@ * procedure was invoked (i.e. determines * variable scoping within caller). Same as * callerPtr unless an "uplevel" command or * something equivalent was active in the * caller). */ - int level; /* Level of this procedure, for "uplevel" + Tcl_Size level; /* Level of this procedure, for "uplevel" * purposes (i.e. corresponds to nesting of * callerVarPtr's, not callerPtr's). 1 for * outermost procedure, 0 for top-level. */ Proc *procPtr; /* Points to the structure defining the called * procedure. Used to get information such as @@ -1138,12 +1260,12 @@ TclVarHashTable *varTablePtr; /* Hash table containing local variables not * recognized by the compiler, or created at * execution time through, e.g., upvar. * Initially NULL and created if needed. */ - int numCompiledLocals; /* Count of local variables recognized by the - * compiler including arguments. */ + Tcl_Size numCompiledLocals; /* Count of local variables recognized + * by the compiler including arguments. */ Var *compiledLocals; /* Points to the array of local variables * recognized by the compiler. The compiler * emits code that refers to these variables * using an index into this array. */ void *clientData; /* Pointer to some context that is used by @@ -1199,12 +1321,12 @@ */ int type; /* Values see below. */ int level; /* Number of frames in stack, prevent O(n) * scan of list. */ - int *line; /* Lines the words of the command start on. */ - int nline; + Tcl_Size *line; /* Lines the words of the command start on. */ + Tcl_Size nline; CallFrame *framePtr; /* Procedure activation record, may be * NULL. */ struct CmdFrame *nextPtr; /* Link to calling frame. */ /* * Data needed for Eval vs TEBC @@ -1244,35 +1366,35 @@ const char *pc; /* ... and instruction pointer. */ } tebc; } data; Tcl_Obj *cmdObj; const char *cmd; /* The executed command, if possible... */ - size_t len; /* ... and its length. */ + Tcl_Size len; /* ... and its length. */ const struct CFWordBC *litarg; /* Link to set of literal arguments which have * ben pushed on the lineLABCPtr stack by * TclArgumentBCEnter(). These will be removed * by TclArgumentBCRelease. */ } CmdFrame; typedef struct CFWord { CmdFrame *framePtr; /* CmdFrame to access. */ - int word; /* Index of the word in the command. */ - size_t refCount; /* Number of times the word is on the + Tcl_Size word; /* Index of the word in the command. */ + Tcl_Size refCount; /* Number of times the word is on the * stack. */ } CFWord; typedef struct CFWordBC { CmdFrame *framePtr; /* CmdFrame to access. */ - size_t pc; /* Instruction pointer of a command in + Tcl_Size pc; /* Instruction pointer of a command in * ExtCmdLoc.loc[.] */ - int word; /* Index of word in + Tcl_Size word; /* Index of word in * ExtCmdLoc.loc[cmd]->line[.] */ struct CFWordBC *prevPtr; /* Previous entry in stack for same Tcl_Obj. */ struct CFWordBC *nextPtr; /* Next entry for same command call. See * CmdFrame litarg field for the list start. */ - Tcl_Obj *obj; /* Back reference to hashtable key */ + Tcl_Obj *obj; /* Back reference to hash table key */ } CFWordBC; /* * Structure to record the locations of invisible continuation lines in * literal scripts, as character offset from the beginning of the script. Both @@ -1282,23 +1404,23 @@ * the \n which was part of it is gone as well, breaking regular line * tracking. * * These structures are allocated and filled by both the function * TclSubstTokens() in the file "tclParse.c" and its caller TclEvalEx() in the - * file "tclBasic.c", and stored in the thread-global hashtable "lineCLPtr" in + * file "tclBasic.c", and stored in the thread-global hash table "lineCLPtr" in * file "tclObj.c". They are used by the functions TclSetByteCodeFromAny() and * TclCompileScript(), both found in the file "tclCompile.c". Their memory is * released by the function TclFreeObj(), in the file "tclObj.c", and also by * the function TclThreadFinalizeObjects(), in the same file. */ #define CLL_END (-1) typedef struct ContLineLoc { - int num; /* Number of entries in loc, not counting the + Tcl_Size num; /* Number of entries in loc, not counting the * final -1 marker entry. */ - int loc[TCLFLEXARRAY];/* Table of locations, as character offsets. + Tcl_Size loc[TCLFLEXARRAY];/* Table of locations, as character offsets. * The table is allocated as part of the * structure, extending behind the nominal end * of the structure. An entry containing the * value -1 is put after the last location, as * end-marker/sentinel. */ @@ -1342,11 +1464,11 @@ * 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. */ + Tcl_Size length; /* Length of array. */ ExtraFrameInfoField fields[2]; /* Really as long as necessary, but this is * long enough for nearly anything. */ } ExtraFrameInfo; @@ -1416,16 +1538,12 @@ * 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 @@ -1473,17 +1591,22 @@ * coroutine. */ CorContext caller; CorContext running; Tcl_HashTable *lineLABCPtr; /* See Interp.lineLABCPtr */ void *stackLevel; - int auxNumLevels; /* While the coroutine is running the + Tcl_Size auxNumLevels; /* While the coroutine is running the * numLevels of the create/resume command is * stored here; for suspended coroutines it * holds the nesting numLevels at yield. */ - int nargs; /* Number of args required for resuming this - * coroutine; -2 means "0 or 1" (default), -1 - * means "any" */ + Tcl_Size nargs; /* Number of args required for resuming this + * coroutine; COROUTINE_ARGUMENTS_SINGLE_OPTIONAL means "0 or 1" + * (default), COROUTINE_ARGUMENTS_ARBITRARY means "any" */ + Tcl_Obj *yieldPtr; /* The command to yield to. Stored here in + * order to reset splice point in + * TclNRCoroutineActivateCallback if the + * coroutine is busy. + */ } CoroutineData; typedef struct ExecEnv { ExecStack *execStackPtr; /* Points to the first item in the evaluation * stack on the heap. */ @@ -1518,11 +1641,11 @@ struct LiteralEntry *nextPtr; /* Points to next entry in this hash bucket or * NULL if end of chain. */ Tcl_Obj *objPtr; /* Points to Tcl object that holds the * literal's bytes and length. */ - size_t refCount; /* If in an interpreter's global literal + Tcl_Size refCount; /* If in an interpreter's global literal * table, the number of ByteCode structures * that share the literal object; the literal * entry can be freed when refCount drops to * 0. If in a local literal table, TCL_INDEX_NONE. */ Namespace *nsPtr; /* Namespace in which this literal is used. We @@ -1536,17 +1659,17 @@ * points to first entry in bucket's hash * chain, or NULL. */ LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; /* Bucket array used for small tables to avoid * mallocs and frees. */ - size_t numBuckets; /* Total number of buckets allocated at + TCL_HASH_TYPE numBuckets; /* Total number of buckets allocated at * **buckets. */ - size_t numEntries; /* Total number of entries present in + TCL_HASH_TYPE numEntries; /* Total number of entries present in * table. */ - size_t rebuildSize; /* Enlarge table when numEntries gets to be + TCL_HASH_TYPE rebuildSize; /* Enlarge table when numEntries gets to be * this large. */ - size_t mask; /* Mask value used in hashing function. */ + TCL_HASH_TYPE mask; /* Mask value used in hashing function. */ } LiteralTable; /* * The following structure defines for each Tcl interpreter various * statistics-related information about the bytecode compiler and @@ -1660,16 +1783,16 @@ * already (this can happen if deleteProc * causes the command to be deleted or * recreated). */ Namespace *nsPtr; /* Points to the namespace containing this * command. */ - size_t refCount; /* 1 if in command hashtable plus 1 for each + Tcl_Size refCount; /* 1 if in command hashtable plus 1 for each * reference from a CmdName Tcl object * representing a command's name in a ByteCode * instruction sequence. This structure can be * freed when refCount becomes zero. */ - size_t cmdEpoch; /* Incremented to invalidate any references + Tcl_Size cmdEpoch; /* Incremented to invalidate any references * that point to this command when it is * renamed, deleted, hidden, or exposed. */ CompileProc *compileProc; /* Procedure called to compile command. NULL * if no compile proc exists for command. */ Tcl_ObjCmdProc *objProc; /* Object-based command procedure. */ @@ -1837,22 +1960,33 @@ * 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. */ - int numLevels; /* Keeps track of how many nested calls to + Tcl_Size numLevels; /* Keeps track of how many nested calls to * Tcl_Eval are in progress for this * interpreter. It's used to delay deletion of * the table until all Tcl_Eval invocations * are completed. */ - int maxNestingDepth; /* If numLevels exceeds this value then Tcl + Tcl_Size maxNestingDepth; /* If numLevels exceeds this value then Tcl * assumes that infinite recursion has * occurred and it generates an error. */ CallFrame *framePtr; /* Points to top-most in stack of all nested * procedure invocations. */ CallFrame *varFramePtr; /* Points to the call frame whose variables @@ -1866,10 +2000,16 @@ 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 @@ -1882,22 +2022,25 @@ * NULL. */ /* * Miscellaneous information: */ - size_t cmdCount; /* Total number of times a command procedure + Tcl_Size cmdCount; /* Total number of times a command procedure * has been called for this interpreter. */ int evalFlags; /* Flags to control next call to Tcl_Eval. * Normally zero, but may be set before * calling Tcl_Eval. See below for valid * values. */ +#if TCL_MAJOR_VERSION < 9 + int unused1; /* No longer used (was termOffset) */ +#endif LiteralTable literalTable; /* Contains LiteralEntry's describing all Tcl * objects holding literals of scripts * compiled by the interpreter. Indexed by the * string representations of literals. Used to * avoid creating duplicate objects. */ - size_t compileEpoch; /* Holds the current "compilation epoch" for + Tcl_Size compileEpoch; /* Holds the current "compilation epoch" for * this interpreter. This is incremented to * invalidate existing ByteCodes when, e.g., a * command with a compile procedure is * redefined. */ Proc *compiledProcPtr; /* If a procedure is being compiled, a pointer @@ -1925,10 +2068,13 @@ * 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. */ @@ -1937,11 +2083,11 @@ * interp, or NULL if no active traces. */ ActiveInterpTrace *activeInterpTracePtr; /* First in list of active traces for interp, * or NULL if no active traces. */ - int tracesForbiddingInline; /* Count of traces (in the list headed by + Tcl_Size tracesForbiddingInline; /* Count of traces (in the list headed by * tracePtr) that forbid inline bytecode * compilation. */ /* * Fields used to manage extensible return options (TIP 90). @@ -1967,11 +2113,11 @@ * check the limits. */ int exceeded; /* Which limits have been exceeded, described * as flag values the same as the 'active' * field. */ - size_t cmdCount; /* Limit for how many commands to execute in + Tcl_Size cmdCount; /* Limit for how many commands to execute in * the interpreter. */ LimitHandler *cmdHandlers; /* Handlers to execute when the limit is * reached. */ int cmdGranularity; /* Mod factor used to determine how often to @@ -2003,13 +2149,13 @@ Tcl_Obj *const *sourceObjs; /* What arguments were actually input into the * *root* ensemble command? (Nested ensembles * don't rewrite this.) NULL if we're not * processing an ensemble. */ - size_t numRemovedObjs; /* How many arguments have been stripped off + Tcl_Size numRemovedObjs; /* How many arguments have been stripped off * because of ensemble processing. */ - size_t numInsertedObjs; /* How many of the current arguments were + Tcl_Size numInsertedObjs; /* How many of the current arguments were * inserted by an ensemble. */ } ensembleRewrite; /* * TIP #219: Global info for the I/O system. @@ -2300,26 +2446,38 @@ #else #define TCL_ALLOCALIGN (2*sizeof(void *)) #endif /* - * This macro is used to determine the offset needed to safely allocate any + * TCL_ALIGN is used to determine the offset needed to safely allocate any * data structure in memory. Given a starting offset or size, it "rounds up" - * or "aligns" the offset to the next 8-byte boundary so that any data - * structure can be placed at the resulting offset without fear of an - * alignment error. + * or "aligns" the offset to the next aligned (typically 8-byte) boundary so + * that any data structure can be placed at the resulting offset without fear + * of an alignment error. Note this is clamped to a minimum of 8 for API + * compatibility. * * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce the - * wrong result on platforms that allocate addresses that are divisible by 4 - * or 2. Only use it for offsets or sizes. + * wrong result on platforms that allocate addresses that are divisible by a + * non-trivial factor of this alignment. Only use it for offsets or sizes. * * This macro is only used by tclCompile.c in the core (Bug 926445). It * however not be made file static, as extensions that touch bytecodes * (notably tbcload) require it. */ -#define TCL_ALIGN(x) (((int)(x) + 7) & ~7) +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. */ @@ -2367,63 +2525,195 @@ #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) + * 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 TclListObjGetElementsM(interp_, listObj_, objcPtr_, objvPtr_) \ + (((listObj_)->typePtr == &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 TclListObjLengthM(interp_, listObj_, lenPtr_) \ + (((listObj_)->typePtr == &tclListType) \ + ? ((ListObjLength((listObj_), *(lenPtr_))), TCL_OK) \ + : Tcl_ListObjLength((interp_), (listObj_), (lenPtr_))) + +#define TclListObjIsCanonical(listObj_) \ + (((listObj_)->typePtr == &tclListType) ? ListObjIsCanonical((listObj_)) : 0) /* * Modes for collecting (or not) in the implementations of TclNRForeachCmd, * TclNRLmapCmd and their compilations. */ @@ -2437,15 +2727,24 @@ * and Tcl_GetIntForIndex. * * WARNING: these macros eval their args more than once. */ -#define TclGetBooleanFromObj(interp, objPtr, boolPtr) \ +#if TCL_MAJOR_VERSION > 8 +#define TclGetBooleanFromObj(interp, objPtr, intPtr) \ (((objPtr)->typePtr == &tclIntType \ || (objPtr)->typePtr == &tclBooleanType) \ - ? (*(boolPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK) \ - : Tcl_GetBooleanFromObj((interp), (objPtr), (boolPtr))) + ? (*(intPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK) \ + : Tcl_GetBooleanFromObj((interp), (objPtr), (intPtr))) +#else +#define TclGetBooleanFromObj(interp, objPtr, intPtr) \ + (((objPtr)->typePtr == &tclIntType) \ + ? (*(intPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK) \ + : ((objPtr)->typePtr == &tclBooleanType) \ + ? (*(intPtr) = ((objPtr)->internalRep.longValue!=0), TCL_OK) \ + : Tcl_GetBooleanFromObj((interp), (objPtr), (intPtr))) +#endif #ifdef TCL_WIDE_INT_IS_LONG #define TclGetLongFromObj(interp, objPtr, longPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? ((*(longPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \ @@ -2465,12 +2764,12 @@ && (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) \ + && ((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: @@ -2553,20 +2852,10 @@ * 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 @@ -2583,24 +2872,55 @@ typedef Tcl_Channel (TclOpenFileChannelProc_)(Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions); /* *---------------------------------------------------------------- - * Data structures related to procedures + * Internal definitions related to parsing, substitution, evaluation *---------------------------------------------------------------- */ -typedef Tcl_CmdProc *TclCmdProcType; -typedef Tcl_ObjCmdProc *TclObjCmdProcType; +/* + * New internal Tcl_Token types. + * + * TCL_TOKEN_SCRIPT - Leading Tcl_Token type for an entire script. + * The numComponents field stores the number of + * commands in the script. + * TCL_TOKEN_SCRIPT_SUBST - So-called "command substituion" in Tcl is + * really "script substitution" and this internal + * Tcl_Token type indicates it. Unlike + * the TCL_TOKEN_COMMAND type, which also denotes + * "command substitution", the numComponents field + * is *not* always 0, so we can store the results + * of nested parsing, and avoid reparsing the + * same string again and again. The numComponents + * field stores the number of following Tcl_Tokens + * that are parsed from the nested script. The + * numComponents value is always at least 1, for + * the TCL_TOKEN_SCRIPT token that follows. + * TCL_TOKEN_CMD - Leading Tcl_Token type for a parsed Tcl command. * There will be one of these tokens for each + * command in a script. The numComponents field + * stores the number of words in the command. + * TCL_TOKEN_ERROR - This Tcl_Token type is used to represent a + * parse error. It may appear following all + * the commands that follow a TCL_TOKEN_SCRIPT + * token. The TCL_TOKEN_ERROR token represents + * the remainder of the original string that + * could not be parsed into commands. + */ + +#define TCL_TOKEN_SCRIPT 512 +#define TCL_TOKEN_SCRIPT_SUBST 1024 +#define TCL_TOKEN_CMD 2048 +#define TCL_TOKEN_ERROR 4096 /* *---------------------------------------------------------------- * Data structures for process-global values. *---------------------------------------------------------------- */ -typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, size_t *lengthPtr, +typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, TCL_HASH_TYPE *lengthPtr, Tcl_Encoding *encodingPtr); /* * 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 @@ -2608,13 +2928,13 @@ * mutex control. Each ProcessGlobalValue struct should be a static variable in * some file. */ typedef struct ProcessGlobalValue { - size_t epoch; /* Epoch counter to detect changes in the + Tcl_Size epoch; /* Epoch counter to detect changes in the * global value. */ - size_t numBytes; /* Length of the global string. */ + TCL_HASH_TYPE numBytes; /* Length of the global string. */ char *value; /* The global string value. */ Tcl_Encoding encoding; /* system encoding when global string was * initialized. */ TclInitProcessGlobalValueProc *proc; /* A procedure to initialize the global string @@ -2649,20 +2969,94 @@ #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_; \ + } while (0) + /* *---------------------------------------------------------------------- - * Type values TclGetNumberFromObj + * 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. + * *---------------------------------------------------------------------- */ - -#define TCL_NUMBER_INT 2 -#define TCL_NUMBER_BIG 3 -#define TCL_NUMBER_DOUBLE 4 -#define TCL_NUMBER_NAN 5 +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. *---------------------------------------------------------------- @@ -2670,13 +3064,25 @@ MODULE_SCOPE char *tclNativeExecutableName; MODULE_SCOPE int tclFindExecutableSearchDone; MODULE_SCOPE char *tclMemDumpFileName; MODULE_SCOPE TclPlatformType tclPlatform; -MODULE_SCOPE Tcl_NotifierProcs tclNotifierHooks; + +/* + * Declarations related to internal encoding functions. + */ MODULE_SCOPE Tcl_Encoding tclIdentityEncoding; +MODULE_SCOPE Tcl_Encoding tclUtf8Encoding; +MODULE_SCOPE int +TclEncodingProfileNameToId(Tcl_Interp *interp, + const char *profileName, + int *profilePtr); +MODULE_SCOPE const char *TclEncodingProfileIdToName(Tcl_Interp *interp, + int profileId); +MODULE_SCOPE int TclEncodingSetProfileFlags(int flags); +MODULE_SCOPE void TclGetEncodingProfiles(Tcl_Interp *interp); /* * TIP #233 (Virtualized Time) * Data for the time hooks, if any. */ @@ -2689,14 +3095,14 @@ * 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 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; @@ -2736,10 +3142,46 @@ enum CheckEmptyStringResult { TCL_EMPTYSTRING_UNKNOWN = -1, TCL_EMPTYSTRING_NO, TCL_EMPTYSTRING_YES }; +/* + * Flags used to control details of parsing. + * The first three are #define'd in tcl.h, so that may be set by callers + * of Tcl_SubstObj(). See the docs for what they do. + * + * #define TCL_SUBST_COMMANDS 001 + * #define TCL_SUBST_VARIABLES 002 + * #define TCL_SUBST_BACKSLASHES 004 + * + * tcl.h also #define's their combination for brevity: + * + * #define TCL_SUBST_ALL 007 + * + * The other flag values that control parsing are: + * + * PARSE_NESTED - Passed to ParseCommand to indicate that the + * close bracket character should be treated as + * a command terminator, as well as newlines, + * semi-colons, and end of string. + * + * PARSE_APPEND - Passed throughout the Parse routines to + * indicate that parsing should append to the + * Tcl_Parse structure passed in (by reference). + * If this flag is not set, some routines will + * re-initialize the Tcl_Parse structure. + * + * PARSE_USE_INTERNAL_TOKENS - Passed throughout the Parse routines to + * indicate the parse is being done for Tcl's + * internal use, so it is acceptable to use + * Tcl_Token types that are known only internally. + */ + +#define PARSE_NESTED 010 +#define PARSE_APPEND 020 +#define PARSE_USE_INTERNAL_TOKENS 040 + /* *---------------------------------------------------------------- * Procedures shared among Tcl modules but not used by the outside world, * introduced by/for NRE. *---------------------------------------------------------------- @@ -2792,11 +3234,11 @@ typedef struct ForIterData { Tcl_Obj *cond; /* Loop condition expression. */ Tcl_Obj *body; /* Loop body. */ Tcl_Obj *next; /* Loop step script, NULL for 'while'. */ const char *msg; /* Error message part. */ - int word; /* Index of the body script in the command */ + Tcl_Size word; /* Index of the body script in the command */ } ForIterData; /* TIP #357 - Structure doing the bookkeeping of handles for Tcl_LoadFile * and Tcl_FindSymbol. This structure corresponds to an opaque * typedef in tcl.h */ @@ -2836,33 +3278,38 @@ *---------------------------------------------------------------- * Procedures shared among Tcl modules but not used by the outside world: *---------------------------------------------------------------- */ +#if TCL_MAJOR_VERSION > 8 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, + const unsigned char *bytes, Tcl_Size len); +MODULE_SCOPE void TclAdvanceContinuations(Tcl_Size *line, Tcl_Size **next, int loc); -MODULE_SCOPE void TclAdvanceLines(int *line, const char *start, +MODULE_SCOPE void TclAdvanceLines(Tcl_Size *line, const char *start, const char *end); MODULE_SCOPE void 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); + 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 void TclBAConvertIndices(size_t index, unsigned int *hiPtr, + unsigned int *loPtr); +MODULE_SCOPE size_t TclBAInvertIndices(unsigned int hi, unsigned int lo); MODULE_SCOPE double TclBignumToDouble(const void *bignum); MODULE_SCOPE int TclByteArrayMatch(const unsigned char *string, - size_t strLen, const unsigned char *pattern, - size_t ptnLen, int flags); + Tcl_Size strLen, const unsigned char *pattern, + Tcl_Size ptnLen, int flags); MODULE_SCOPE double TclCeil(const void *a); MODULE_SCOPE void TclChannelPreserve(Tcl_Channel chan); MODULE_SCOPE void TclChannelRelease(Tcl_Channel chan); MODULE_SCOPE int TclCheckArrayTraces(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *name, int index); @@ -2871,57 +3318,67 @@ 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 ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, Tcl_Size num, + Tcl_Size *loc); MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr, - int start, int *clNext); + Tcl_Size start, Tcl_Size *clNext); MODULE_SCOPE ContLineLoc *TclContinuationsGet(Tcl_Obj *objPtr); MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr, Tcl_Obj *originObjPtr); -MODULE_SCOPE size_t TclConvertElement(const char *src, size_t length, +MODULE_SCOPE Tcl_Size TclConvertElement(const char *src, Tcl_Size length, char *dst, int flags); MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs(Tcl_Interp *interp, const char *cmdName, Tcl_Namespace *nsPtr, Tcl_ObjCmdProc *proc, void *clientData, Tcl_CmdDeleteProc *deleteProc); MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(Tcl_Interp *interp, const char *name, Tcl_Namespace *nameNamespacePtr, Tcl_Namespace *ensembleNamespacePtr, int flags); MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr); +MODULE_SCOPE void TclDeleteNamespaceChildren(Namespace *nsPtr); +MODULE_SCOPE Tcl_Size TclDictGetSize(Tcl_Obj *dictPtr); MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp, - const char *dict, int dictLength, + const char *dict, Tcl_Size dictLength, const char **elementPtr, const char **nextPtr, - size_t *sizePtr, int *literalPtr); + Tcl_Size *sizePtr, int *literalPtr); /* TIP #280 - Modified token based evaluation, with line information. */ MODULE_SCOPE int TclEvalEx(Tcl_Interp *interp, const char *script, - size_t numBytes, int flags, int line, - int *clNextOuter, const char *outerScript); + Tcl_Size numBytes, int flags, Tcl_Size line, + Tcl_Size *clNextOuter, const char *outerScript); +MODULE_SCOPE int TclEvalScriptTokens(Tcl_Interp *interp, + Tcl_Token *tokenPtr, Tcl_Size length, int flags, + Tcl_Size line, Tcl_Size *clNextOuter, + const char* outerScript); MODULE_SCOPE Tcl_ObjCmdProc TclFileAttrsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileCopyCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileDeleteCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileLinkCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileMakeDirsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileReadLinkCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileRenameCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileTempDirCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileTemporaryCmd; +MODULE_SCOPE Tcl_ObjCmdProc TclFileHomeCmd; +MODULE_SCOPE Tcl_ObjCmdProc TclFileTildeExpandCmd; MODULE_SCOPE void TclCreateLateExitHandler(Tcl_ExitProc *proc, void *clientData); MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc, void *clientData); MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr, Tcl_Obj *objPtr); MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr, Tcl_DString *toAppendPtr); -MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr); MODULE_SCOPE Tcl_Obj *const *TclFetchEnsembleRoot(Tcl_Interp *interp, - Tcl_Obj *const *objv, int objc, int *objcPtr); + Tcl_Obj *const *objv, Tcl_Size objc, Tcl_Size *objcPtr); +MODULE_SCOPE Tcl_Obj *const *TclEnsembleGetRewriteValues(Tcl_Interp *interp); MODULE_SCOPE Tcl_Namespace *TclEnsureNamespace(Tcl_Interp *interp, Tcl_Namespace *namespacePtr); +MODULE_SCOPE void TclFillTableWithExports(Namespace *nsPtr, + Tcl_HashTable *hash); 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); @@ -2947,15 +3404,13 @@ MODULE_SCOPE int TclFSFileAttrIndex(Tcl_Obj *pathPtr, const char *attributeName, int *indexPtr); MODULE_SCOPE Tcl_Command TclNRCreateCommandInNs(Tcl_Interp *interp, const char *cmdName, Tcl_Namespace *nsPtr, Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc, - void *clientData, - Tcl_CmdDeleteProc *deleteProc); + void *clientData, Tcl_CmdDeleteProc *deleteProc); MODULE_SCOPE int TclNREvalFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *encodingName); -MODULE_SCOPE void TclFSUnloadTempFile(Tcl_LoadHandle loadHandle); MODULE_SCOPE int * TclGetAsyncReadyPtr(void); MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler(Tcl_Interp *interp); MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Channel *chanPtr, int *modePtr, int flags); @@ -2962,44 +3417,35 @@ 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, + 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 TclGlob(Tcl_Interp *interp, char *pattern, - Tcl_Obj *unquotedPrefix, int globFlags, - Tcl_GlobTypeData *types); +MODULE_SCOPE Tcl_Token *TclGetTokensFromObj(Tcl_Obj *objPtr, + Tcl_Token **lastTokenPtrPtr); 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_ObjCmdProc TclInfoExistsCmd; +MODULE_SCOPE Tcl_ObjCmdProc TclInfoCoroutineCmd; 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 Tcl_ObjCmdProc TclInfoGlobalsCmd; +MODULE_SCOPE Tcl_ObjCmdProc TclInfoLocalsCmd; +MODULE_SCOPE Tcl_ObjCmdProc TclInfoVarsCmd; MODULE_SCOPE void TclInitAlloc(void); MODULE_SCOPE void TclInitDbCkalloc(void); MODULE_SCOPE void TclInitDoubleConversion(void); MODULE_SCOPE void TclInitEmbeddedConfigurationInformation( Tcl_Interp *interp); @@ -3008,34 +3454,41 @@ MODULE_SCOPE void TclInitLimitSupport(Tcl_Interp *interp); MODULE_SCOPE void TclInitNamespaceSubsystem(void); MODULE_SCOPE void TclInitNotifier(void); MODULE_SCOPE void TclInitObjSubsystem(void); MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp); -MODULE_SCOPE int TclIsDigitProc(int byte); MODULE_SCOPE int TclIsBareword(int byte); -MODULE_SCOPE Tcl_Obj * TclJoinPath(int elements, Tcl_Obj * const objv[], +MODULE_SCOPE Tcl_Obj * TclJoinPath(Tcl_Size elements, Tcl_Obj * const objv[], int forceRelative); +MODULE_SCOPE Tcl_Obj * TclGetHomeDirObj(Tcl_Interp *interp, const char *user); +MODULE_SCOPE Tcl_Obj * TclResolveTildePath(Tcl_Interp *interp, + Tcl_Obj *pathObj); +MODULE_SCOPE Tcl_Obj * TclResolveTildePathList(Tcl_Obj *pathsObj); MODULE_SCOPE int TclJoinThread(Tcl_ThreadId id, int *result); MODULE_SCOPE void TclLimitRemoveAllHandlers(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *argPtr); MODULE_SCOPE Tcl_Obj * TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr, - int indexCount, Tcl_Obj *const indexArray[]); + Tcl_Size indexCount, Tcl_Obj *const indexArray[]); +MODULE_SCOPE Tcl_Obj * TclListObjGetElement(Tcl_Obj *listObj, Tcl_Size index); /* TIP #280 */ -MODULE_SCOPE void TclListLines(Tcl_Obj *listObj, int line, int n, - int *lines, Tcl_Obj *const *elems); +MODULE_SCOPE void TclListLines(Tcl_Obj *listObj, Tcl_Size line, Tcl_Size n, + Tcl_Size *lines, Tcl_Obj *const *elems); MODULE_SCOPE Tcl_Obj * TclListObjCopy(Tcl_Interp *interp, Tcl_Obj *listPtr); -MODULE_SCOPE Tcl_Obj * TclListObjRange(Tcl_Obj *listPtr, size_t fromIdx, - size_t toIdx); +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, - int indexCount, Tcl_Obj *const indexArray[], + Tcl_Size indexCount, Tcl_Obj *const indexArray[], Tcl_Obj *valuePtr); MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name, const EnsembleImplMap map[]); -MODULE_SCOPE int TclMaxListLength(const char *bytes, size_t numBytes, +MODULE_SCOPE Tcl_Size TclMaxListLength(const char *bytes, Tcl_Size numBytes, const char **endPtr); MODULE_SCOPE int TclMergeReturnOptions(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr, int *codePtr, int *levelPtr); MODULE_SCOPE Tcl_Obj * TclNoErrorStack(Tcl_Interp *interp, Tcl_Obj *options); @@ -3049,55 +3502,86 @@ 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); + Tcl_Size numBytes, Tcl_Size *readPtr, char *dst); +MODULE_SCOPE int TclParseCommand(Tcl_Interp *interp, const char *start, + Tcl_Size numBytes, int flags, Tcl_Parse *parsePtr); MODULE_SCOPE int TclParseNumber(Tcl_Interp *interp, Tcl_Obj *objPtr, const char *expected, const char *bytes, - size_t numBytes, const char **endPtrPtr, int flags); + Tcl_Size numBytes, const char **endPtrPtr, int flags); MODULE_SCOPE void TclParseInit(Tcl_Interp *interp, const char *string, - size_t numBytes, Tcl_Parse *parsePtr); -MODULE_SCOPE size_t TclParseAllWhiteSpace(const char *src, size_t numBytes); + Tcl_Size numBytes, Tcl_Parse *parsePtr); + +MODULE_SCOPE int TclParseQuotedString(Tcl_Interp *interp, + const char *start, Tcl_Size numBytes, + Tcl_Parse *parsePtr, int flags, + const char **termPtr); +MODULE_SCOPE Tcl_Token *TclParseScript(Tcl_Interp *interp, const char *script, + Tcl_Size numBytes, int flags, + Tcl_Token **lastTokenPtrPtr, const char **termPtr); +MODULE_SCOPE int TclParseScriptSubst(const char *src, Tcl_Size numBytes, + Tcl_Parse *parsePtr, int flags); +MODULE_SCOPE int TclParseVarName(Tcl_Interp *interp, const char *start, + Tcl_Size numBytes, Tcl_Parse *parsePtr, int flags); +MODULE_SCOPE Tcl_Size TclParseAllWhiteSpace(const char *src, + Tcl_Size numBytes); MODULE_SCOPE int TclProcessReturn(Tcl_Interp *interp, int code, int level, Tcl_Obj *returnOpts); +MODULE_SCOPE void TclUndoRefCount(Tcl_Obj *objPtr); MODULE_SCOPE int TclpObjLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf); MODULE_SCOPE Tcl_Obj * TclpTempFileName(void); -MODULE_SCOPE Tcl_Obj * TclpTempFileNameForLibrary(Tcl_Interp *interp, Tcl_Obj* pathPtr); +MODULE_SCOPE Tcl_Obj * TclpTempFileNameForLibrary(Tcl_Interp *interp, + Tcl_Obj* pathPtr); +MODULE_SCOPE 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, - size_t len); + 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, - size_t stackSize, int flags); -MODULE_SCOPE size_t TclpFindVariable(const char *name, size_t *lengthPtr); + TCL_HASH_TYPE stackSize, int flags); +MODULE_SCOPE Tcl_Size TclpFindVariable(const char *name, Tcl_Size *lengthPtr); MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr, - size_t *lengthPtr, Tcl_Encoding *encodingPtr); + TCL_HASH_TYPE *lengthPtr, Tcl_Encoding *encodingPtr); MODULE_SCOPE void TclpInitLock(void); +MODULE_SCOPE void *TclpInitNotifier(void); MODULE_SCOPE void TclpInitPlatform(void); MODULE_SCOPE void TclpInitUnlock(void); MODULE_SCOPE Tcl_Obj * TclpObjListVolumes(void); MODULE_SCOPE void TclpGlobalLock(void); MODULE_SCOPE void TclpGlobalUnlock(void); -MODULE_SCOPE int TclpMatchFiles(Tcl_Interp *interp, char *separators, - Tcl_DString *dirPtr, char *pattern, char *tail); MODULE_SCOPE int TclpObjNormalizePath(Tcl_Interp *interp, Tcl_Obj *pathPtr, int nextCheckpoint); MODULE_SCOPE void TclpNativeJoinPath(Tcl_Obj *prefix, const char *joining); -MODULE_SCOPE Tcl_Obj * TclpNativeSplitPath(Tcl_Obj *pathPtr, int *lenPtr); +MODULE_SCOPE Tcl_Obj * TclpNativeSplitPath(Tcl_Obj *pathPtr, Tcl_Size *lenPtr); MODULE_SCOPE Tcl_PathType TclpGetNativePathType(Tcl_Obj *pathPtr, - int *driveNameLengthPtr, Tcl_Obj **driveNameRef); + Tcl_Size *driveNameLengthPtr, Tcl_Obj **driveNameRef); MODULE_SCOPE int TclCrossFilesystemCopy(Tcl_Interp *interp, Tcl_Obj *source, Tcl_Obj *target); MODULE_SCOPE int TclpMatchInDirectory(Tcl_Interp *interp, Tcl_Obj *resultPtr, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); @@ -3107,12 +3591,13 @@ int linkType); MODULE_SCOPE int TclpObjChdir(Tcl_Obj *pathPtr); MODULE_SCOPE Tcl_Channel TclpOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); -MODULE_SCOPE void TclPkgFileSeen(Tcl_Interp *interp, const char *fileName); -MODULE_SCOPE void *TclInitPkgFiles(Tcl_Interp *interp); +MODULE_SCOPE void TclPkgFileSeen(Tcl_Interp *interp, + const char *fileName); +MODULE_SCOPE void * TclInitPkgFiles(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclPathPart(Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_PathPart portion); MODULE_SCOPE char * TclpReadlink(const char *fileName, Tcl_DString *linkPtr); MODULE_SCOPE void TclpSetVariables(Tcl_Interp *interp); @@ -3123,17 +3608,17 @@ MODULE_SCOPE void TclRememberCondition(Tcl_Condition *mutex); MODULE_SCOPE void TclRememberJoinableThread(Tcl_ThreadId id); MODULE_SCOPE void TclRememberMutex(Tcl_Mutex *mutex); MODULE_SCOPE void TclRemoveScriptLimitCallbacks(Tcl_Interp *interp); MODULE_SCOPE int TclReToGlob(Tcl_Interp *interp, const char *reStr, - size_t reStrLen, Tcl_DString *dsPtr, int *flagsPtr, + Tcl_Size reStrLen, Tcl_DString *dsPtr, int *flagsPtr, int *quantifiersFoundPtr); -MODULE_SCOPE size_t TclScanElement(const char *string, size_t length, +MODULE_SCOPE Tcl_Size TclScanElement(const char *string, Tcl_Size length, char *flagPtr); MODULE_SCOPE void TclSetBgErrorHandler(Tcl_Interp *interp, Tcl_Obj *cmdPrefix); -MODULE_SCOPE void TclSetBignumIntRep(Tcl_Obj *objPtr, +MODULE_SCOPE void TclSetBignumInternalRep(Tcl_Obj *objPtr, void *bignumValue); MODULE_SCOPE int TclSetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); MODULE_SCOPE void TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Command *cmdPtr); @@ -3140,61 +3625,49 @@ 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 *const *objv, Tcl_Size objc, Tcl_Size subIdx, Tcl_Obj *bad, Tcl_Obj *fix); MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, - size_t numBytes); + TCL_HASH_TYPE numBytes); typedef int (*memCmpFn_t)(const void*, const void*, size_t); MODULE_SCOPE int TclStringCmp(Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr, - int checkEq, int nocase, size_t reqlength); -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, + 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, - size_t numBytes, int flags, int line, + Tcl_Size numBytes, int flags, Tcl_Size line, struct CompileEnv *envPtr); -MODULE_SCOPE int TclSubstOptions(Tcl_Interp *interp, int numOpts, +MODULE_SCOPE int TclSubstOptions(Tcl_Interp *interp, Tcl_Size numOpts, Tcl_Obj *const opts[], int *flagPtr); MODULE_SCOPE void TclSubstParse(Tcl_Interp *interp, const char *bytes, - size_t numBytes, int flags, Tcl_Parse *parsePtr, - Tcl_InterpState *statePtr); + Tcl_Size numBytes, int flags, Tcl_Parse *parsePtr); MODULE_SCOPE int TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr, - int count, int *tokensLeftPtr, int line, - int *clNextOuter, const char *outerScript); -MODULE_SCOPE size_t TclTrim(const char *bytes, size_t numBytes, - const char *trim, size_t numTrim, size_t *trimRight); -MODULE_SCOPE size_t TclTrimLeft(const char *bytes, size_t numBytes, - const char *trim, size_t numTrim); -MODULE_SCOPE size_t TclTrimRight(const char *bytes, size_t numBytes, - const char *trim, size_t numTrim); + Tcl_Size count, int *tokensLeftPtr, Tcl_Size line, + Tcl_Size *clNextOuter, const char* outerScript, + int flags); +MODULE_SCOPE Tcl_Obj * TclTokensCopy(Tcl_Obj *objPtr); +MODULE_SCOPE Tcl_Size TclTrim(const char *bytes, Tcl_Size numBytes, + const char *trim, Tcl_Size numTrim, Tcl_Size *trimRight); +MODULE_SCOPE Tcl_Size TclTrimLeft(const char *bytes, Tcl_Size numBytes, + const char *trim, Tcl_Size numTrim); +MODULE_SCOPE Tcl_Size TclTrimRight(const char *bytes, Tcl_Size numBytes, + const char *trim, Tcl_Size numTrim); MODULE_SCOPE const char*TclGetCommandTypeName(Tcl_Command command); +MODULE_SCOPE int TclObjInterpProc(void *clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); MODULE_SCOPE void TclRegisterCommandTypeName( Tcl_ObjCmdProc *implementationProc, const char *nameStr); MODULE_SCOPE int TclUtfCmp(const char *cs, const char *ct); MODULE_SCOPE int TclUtfCasecmp(const char *cs, const char *ct); -MODULE_SCOPE size_t TclUtfCount(int ch); -#if TCL_UTF_MAX > 3 -# define TclUtfToUCS4 Tcl_UtfToUniChar -# define TclUniCharToUCS4(src, ptr) (*ptr = *(src),1) -# define TclUCS4Complete Tcl_UtfCharComplete -# define TclChar16Complete(src, length) (((unsigned)((unsigned char)*(src) - 0xF0) < 5) \ - ? ((length) >= 3) : Tcl_UtfCharComplete((src), (length))) -#else - MODULE_SCOPE int TclUtfToUCS4(const char *src, int *ucs4Ptr); - MODULE_SCOPE int 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 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); @@ -3208,34 +3681,35 @@ MODULE_SCOPE void TclInitThreadStorage(void); MODULE_SCOPE void TclFinalizeThreadDataThread(void); MODULE_SCOPE void TclFinalizeThreadStorage(void); #ifdef TCL_WIDE_CLICKS -MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void); -MODULE_SCOPE double TclpWideClicksToNanoseconds(Tcl_WideInt clicks); +MODULE_SCOPE long long TclpGetWideClicks(void); +MODULE_SCOPE double TclpWideClicksToNanoseconds(long long clicks); MODULE_SCOPE double TclpWideClickInMicrosec(void); #else # ifdef _WIN32 # define TCL_WIDE_CLICKS 1 -MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void); +MODULE_SCOPE long long TclpGetWideClicks(void); MODULE_SCOPE double TclpWideClickInMicrosec(void); # define TclpWideClicksToNanoseconds(clicks) \ ((double)(clicks) * TclpWideClickInMicrosec() * 1000) # endif #endif -MODULE_SCOPE Tcl_WideInt TclpGetMicroseconds(void); +MODULE_SCOPE long long TclpGetMicroseconds(void); MODULE_SCOPE int TclZlibInit(Tcl_Interp *interp); MODULE_SCOPE void * TclpThreadCreateKey(void); MODULE_SCOPE void TclpThreadDeleteKey(void *keyPtr); MODULE_SCOPE void TclpThreadSetGlobalTSD(void *tsdKeyPtr, void *ptr); MODULE_SCOPE void * TclpThreadGetGlobalTSD(void *tsdKeyPtr); MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp, - const char *msg, size_t length); + const char *msg, Tcl_Size length); /* Tip 430 */ -MODULE_SCOPE int TclZipfs_Init(Tcl_Interp *interp); - +MODULE_SCOPE int TclZipfs_Init(Tcl_Interp *interp); +MODULE_SCOPE int TclIsZipfsPath(const char *path); +MODULE_SCOPE void TclZipfsFinalize(void); /* * Many parsing tasks need a common definition of whitespace. * Use this routine and macro to achieve that and place * optimization (fragile on changes) in one place. @@ -3249,780 +3723,303 @@ *---------------------------------------------------------------- * 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_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 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_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 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 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 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_ObjCmdProc TclClockOldscanObjCmd; +MODULE_SCOPE Tcl_ObjCmdProc Tcl_CloseObjCmd; +MODULE_SCOPE Tcl_ObjCmdProc Tcl_ConcatObjCmd; +MODULE_SCOPE Tcl_ObjCmdProc Tcl_ContinueObjCmd; 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_ObjCmdProc TclDefaultBgErrorHandlerObjCmd; MODULE_SCOPE Tcl_Command TclInitDictCmd(Tcl_Interp *interp); +MODULE_SCOPE Tcl_Command TclInitHamtCmd(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[]); + Tcl_Size pathc, Tcl_Obj *const pathv[]); +MODULE_SCOPE Tcl_ObjCmdProc Tcl_DisassembleObjCmd; /* 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_ObjCmdProc Tcl_AssembleObjCmd; +MODULE_SCOPE Tcl_ObjCmdProc TclNRAssembleObjCmd; 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_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 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_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 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_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 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_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 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_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 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[]); +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 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); +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 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, int objc, +MODULE_SCOPE Tcl_Obj * TclStringCat(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); MODULE_SCOPE Tcl_Obj * TclStringFirst(Tcl_Obj *needle, Tcl_Obj *haystack, - size_t start); + Tcl_Size start); MODULE_SCOPE Tcl_Obj * TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack, - size_t last); + Tcl_Size last); MODULE_SCOPE Tcl_Obj * TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr, - size_t count, int flags); + Tcl_Size count, int flags); MODULE_SCOPE Tcl_Obj * TclStringReplace(Tcl_Interp *interp, Tcl_Obj *objPtr, - size_t first, size_t count, Tcl_Obj *insertPtr, + Tcl_Size first, Tcl_Size count, Tcl_Obj *insertPtr, int flags); MODULE_SCOPE Tcl_Obj * TclStringReverse(Tcl_Obj *objPtr, int flags); /* Flag values for the [string] ensemble functions. */ @@ -4035,34 +4032,34 @@ * the public interface. */ MODULE_SCOPE Var * TclObjLookupVarEx(Tcl_Interp * interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags, - const char *msg, const int createPart1, - const int createPart2, Var **arrayPtrPtr); + const char *msg, int createPart1, + int createPart2, Var **arrayPtrPtr); MODULE_SCOPE Var * TclLookupArrayElement(Tcl_Interp *interp, Tcl_Obj *arrayNamePtr, Tcl_Obj *elNamePtr, - const int flags, const char *msg, - const int createPart1, const int createPart2, + int flags, const char *msg, + int createPart1, int createPart2, Var *arrayPtr, int index); MODULE_SCOPE Tcl_Obj * TclPtrGetVarIdx(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, - Tcl_Obj *part2Ptr, const int flags, int index); + Tcl_Obj *part2Ptr, int flags, int index); MODULE_SCOPE Tcl_Obj * TclPtrSetVarIdx(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, - const int flags, int index); + int flags, int index); MODULE_SCOPE Tcl_Obj * TclPtrIncrObjVarIdx(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, - const int flags, int index); + int flags, int index); MODULE_SCOPE int TclPtrObjMakeUpvarIdx(Tcl_Interp *interp, Var *otherPtr, Tcl_Obj *myNamePtr, int myFlags, int index); MODULE_SCOPE int TclPtrUnsetVarIdx(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, - Tcl_Obj *part2Ptr, const int flags, + Tcl_Obj *part2Ptr, int flags, int index); MODULE_SCOPE void TclInvalidateNsPath(Namespace *nsPtr); MODULE_SCOPE void TclFindArrayPtrElements(Var *arrayPtr, Tcl_HashTable *tablePtr); @@ -4132,10 +4129,11 @@ 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); @@ -4145,16 +4143,86 @@ * Utility routines for encoding index values as integers. Used by both * some of the command compilers and by [lsort] and [lsearch]. */ MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr, - size_t before, size_t after, int *indexPtr); -MODULE_SCOPE size_t TclIndexDecode(int encoded, size_t endValue); + int before, int after, int *indexPtr); +MODULE_SCOPE Tcl_Size TclIndexDecode(int encoded, Tcl_Size endValue); +MODULE_SCOPE int TclIndexInvalidError(Tcl_Interp *interp, + const char *idxType, Tcl_Size idx); + +/* + * Error message utility functions + */ +MODULE_SCOPE int TclCommandWordLimitError(Tcl_Interp *interp, Tcl_Size count); + +#endif /* TCL_MAJOR_VERSION > 8 */ /* Constants used in index value encoding routines. */ -#define TCL_INDEX_END ((size_t)-2) -#define TCL_INDEX_START ((size_t)0) +#define TCL_INDEX_END ((Tcl_Size)-2) +#define TCL_INDEX_START ((Tcl_Size)0) + +/* + *------------------------------------------------------------------------ + * + * TclGetSizeIntFromObj -- + * + * Extract a Tcl_Size from a Tcl_Obj + * + * Results: + * TCL_OK / TCL_ERROR + * + * Side effects: + * On success, the integer value is stored in *sizePtr. On error, + * an error message in interp it it is not NULL. + * + *------------------------------------------------------------------------ + */ +static inline int TclGetSizeIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Size *sizePtr) { + 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; + } +} + + +/* + *---------------------------------------------------------------------- + * + * 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. @@ -4251,11 +4319,11 @@ * allocates and frees a single Tcl_Obj so that tools like Purify can better * track memory leaks. */ # define TclAllocObjStorageEx(interp, objPtr) \ - (objPtr) = (Tcl_Obj *) Tcl_Alloc(sizeof(Tcl_Obj)) + (objPtr) = (Tcl_Obj *)Tcl_Alloc(sizeof(Tcl_Obj)) # define TclFreeObjStorageEx(interp, objPtr) \ Tcl_Free(objPtr) #undef USE_THREAD_ALLOC @@ -4368,41 +4436,60 @@ TclDbNewObj(objPtr, __FILE__, __LINE__); # define TclDecrRefCount(objPtr) \ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__) -# define TclNewListObjDirect(objc, objv) \ - TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__) - #undef USE_THREAD_ALLOC #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------- - * Macro used by the Tcl core to set a Tcl_Obj's string representation to a - * copy of the "len" bytes starting at "bytePtr". This code works even if the - * byte array contains NULLs as long as the length is correct. Because "len" - * is referenced multiple times, it should be as simple an expression as - * possible. The ANSI C "prototype" for this macro is: + * Macros used by the Tcl core to set a Tcl_Obj's string representation to a + * copy of the "len" bytes starting at "bytePtr". The value of "len" must + * not be negative. When "len" is 0, then it is acceptable to pass + * "bytePtr" = NULL. When "len" > 0, "bytePtr" must not be NULL, and it + * must point to a location from which "len" bytes may be read. These + * constraints are not checked here. The validity of the bytes copied + * as a value string representation is also not verififed. This macro + * must not be called while "objPtr" is being freed or when "objPtr" + * already has a string representation. The caller must use + * this macro properly. Improper use can lead to dangerous results. + * Because "len" is referenced multiple times, take care that it is an + * expression with the same value each use. + * + * The ANSI C "prototypes" for these macros are: * + * MODULE_SCOPE void TclInitEmptyStringRep(Tcl_Obj *objPtr); * MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len); + * MODULE_SCOPE void TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len); * - * This macro should only be called on an unshared objPtr where - * objPtr->typePtr->freeIntRepProc == NULL *---------------------------------------------------------------- */ + +#define TclInitEmptyStringRep(objPtr) \ + ((objPtr)->length = (((objPtr)->bytes = &tclEmptyString), 0)) + #define TclInitStringRep(objPtr, bytePtr, len) \ if ((len) == 0) { \ - (objPtr)->bytes = &tclEmptyString; \ - (objPtr)->length = 0; \ + TclInitEmptyStringRep(objPtr); \ } else { \ - (objPtr)->bytes = (char *)Tcl_Alloc((len) + 1); \ + (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 @@ -4415,54 +4502,21 @@ */ #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); + * MODULE_SCOPE void TclFreeInternalRep(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ -#define TclFreeIntRep(objPtr) \ +#define TclFreeInternalRep(objPtr) \ if ((objPtr)->typePtr != NULL) { \ if ((objPtr)->typePtr->freeIntRepProc != NULL) { \ (objPtr)->typePtr->freeIntRepProc(objPtr); \ } \ (objPtr)->typePtr = NULL; \ @@ -4568,42 +4622,32 @@ /* Token growth tuning, default to the general value. */ #ifndef TCL_MIN_TOKEN_GROWTH #define TCL_MIN_TOKEN_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Token) #endif -#define TCL_MAX_TOKENS (int)(UINT_MAX / sizeof(Tcl_Token)) +/* TODO - code below does not check for integer overflow */ #define TclGrowTokenArray(tokenPtr, used, available, append, staticPtr) \ do { \ - int _needed = (used) + (append); \ - if (_needed > TCL_MAX_TOKENS) { \ - Tcl_Panic("max # of tokens for a Tcl parse (%d) exceeded", \ - TCL_MAX_TOKENS); \ - } \ + Tcl_Size _needed = (used) + (append); \ if (_needed > (available)) { \ - int allocated = 2 * _needed; \ + Tcl_Size allocated = 2 * _needed; \ Tcl_Token *oldPtr = (tokenPtr); \ Tcl_Token *newPtr; \ if (oldPtr == (staticPtr)) { \ oldPtr = NULL; \ } \ - if (allocated > TCL_MAX_TOKENS) { \ - allocated = TCL_MAX_TOKENS; \ - } \ - newPtr = (Tcl_Token *) Tcl_AttemptRealloc((char *) oldPtr, \ - (allocated * sizeof(Tcl_Token))); \ + newPtr = (Tcl_Token *)Tcl_AttemptRealloc((char *) oldPtr, \ + allocated * sizeof(Tcl_Token)); \ if (newPtr == NULL) { \ allocated = _needed + (append) + TCL_MIN_TOKEN_GROWTH; \ - if (allocated > TCL_MAX_TOKENS) { \ - allocated = TCL_MAX_TOKENS; \ - } \ - newPtr = (Tcl_Token *) Tcl_Realloc((char *) oldPtr, \ - (allocated * sizeof(Tcl_Token))); \ + newPtr = (Tcl_Token *)Tcl_Realloc((char *) oldPtr, \ + allocated * sizeof(Tcl_Token)); \ } \ (available) = allocated; \ if (oldPtr == NULL) { \ memcpy(newPtr, staticPtr, \ - ((used) * sizeof(Tcl_Token))); \ + (used) * sizeof(Tcl_Token)); \ } \ (tokenPtr) = newPtr; \ } \ } while (0) @@ -4629,12 +4673,12 @@ (((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) \ + (((UCHAR(*(str))) < 0x80) ? \ + ((*(chPtr) = UCHAR(*(str))), 1) \ : Tcl_UtfToChar16(str, chPtr)) #endif /* *---------------------------------------------------------------- @@ -4641,32 +4685,28 @@ * Macro counterpart of the Tcl_NumUtfChars() function. To be used in speed- * -sensitive points where it pays to avoid a function call in the common case * of counting along a string of all one-byte characters. The ANSI C * "prototype" for this macro is: * - * MODULE_SCOPE void TclNumUtfChars(int numChars, const char *bytes, - * size_t numBytes); + * MODULE_SCOPE void TclNumUtfCharsM(Tcl_Size numChars, const char *bytes, + * Tcl_Size numBytes); + * numBytes must be >= 0 *---------------------------------------------------------------- */ -#define TclNumUtfChars(numChars, bytes, numBytes) \ +#define TclNumUtfCharsM(numChars, bytes, numBytes) \ do { \ - size_t _count, _i = (numBytes); \ + Tcl_Size _count = 0, _i = (numBytes); \ unsigned char *_str = (unsigned char *) (bytes); \ - while (_i && (*_str < 0xC0)) { _i--; _str++; } \ + while (_i > 0 && (*_str < 0xC0)) { _i--; _str++; } \ _count = (numBytes) - _i; \ if (_i) { \ _count += Tcl_NumUtfChars((bytes) + _count, _i); \ } \ (numChars) = _count; \ } while (0); -#define TclUtfPrev(src, start) \ - (((src) < (start) + 2) ? (start) : \ - ((unsigned char) *((src) - 1)) < 0x80 ? (src) - 1 : \ - Tcl_UtfPrev(src, start)) - /* *---------------------------------------------------------------- * Macro that encapsulates the logic that determines when it is safe to * interpret a string as a byte array directly. In summary, the object must be * a byte array and must not have a string representation (as the operations @@ -4681,14 +4721,14 @@ */ MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr); #define TclIsPureDict(objPtr) \ (((objPtr)->bytes==NULL) && ((objPtr)->typePtr==&tclDictType)) -#define TclHasIntRep(objPtr, type) \ +#define TclHasInternalRep(objPtr, type) \ ((objPtr)->typePtr == (type)) -#define TclFetchIntRep(objPtr, type) \ - (TclHasIntRep((objPtr), (type)) ? &((objPtr)->internalRep) : NULL) +#define TclFetchInternalRep(objPtr, type) \ + (TclHasInternalRep((objPtr), (type)) ? &((objPtr)->internalRep) : NULL) /* *---------------------------------------------------------------- * Macro used by the Tcl core to compare Unicode strings. On big-endian @@ -4699,11 +4739,11 @@ * MODULE_SCOPE int TclUniCharNcmp(const Tcl_UniChar *cs, * const Tcl_UniChar *ct, unsigned long n); *---------------------------------------------------------------- */ -#ifdef WORDS_BIGENDIAN +#if defined(WORDS_BIGENDIAN) && (TCL_UTF_MAX > 3) # define TclUniCharNcmp(cs,ct,n) memcmp((cs),(ct),(n)*sizeof(Tcl_UniChar)) #endif /* WORDS_BIGENDIAN */ /* *---------------------------------------------------------------- @@ -4713,11 +4753,11 @@ * MODULE_SCOPE void TclInvalidateNsCmdLookup(Namespace *nsPtr); *---------------------------------------------------------------- */ #define TclInvalidateNsCmdLookup(nsPtr) \ - if ((nsPtr)->numExportPatterns) { \ + if ((nsPtr)->exportPatternList) { \ (nsPtr)->exportLookupEpoch++; \ } \ if ((nsPtr)->commandPathLength) { \ (nsPtr)->cmdRefEpoch++; \ } @@ -4728,11 +4768,11 @@ * Core procedure added to libtommath for bignum manipulation. * *---------------------------------------------------------------------- */ -MODULE_SCOPE Tcl_PackageInitProc TclTommath_Init; +MODULE_SCOPE Tcl_LibraryInitProc TclTommath_Init; /* *---------------------------------------------------------------------- * * External (platform specific) initialization routine, these declarations @@ -4740,15 +4780,17 @@ * library: * *---------------------------------------------------------------------- */ -MODULE_SCOPE Tcl_PackageInitProc TclplatformtestInit; -MODULE_SCOPE Tcl_PackageInitProc TclObjTest_Init; -MODULE_SCOPE Tcl_PackageInitProc TclThread_Init; -MODULE_SCOPE Tcl_PackageInitProc Procbodytest_Init; -MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; +MODULE_SCOPE Tcl_LibraryInitProc TclplatformtestInit; +MODULE_SCOPE Tcl_LibraryInitProc TclObjTest_Init; +MODULE_SCOPE Tcl_LibraryInitProc TclThread_Init; +MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_Init; +MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit; +MODULE_SCOPE Tcl_LibraryInitProc Tcl_ABSListTest_Init; + /* *---------------------------------------------------------------- * Macro used by the Tcl core to check whether a pattern has any characters * special to [string match]. The ANSI C "prototype" for this macro is: @@ -4772,22 +4814,22 @@ *---------------------------------------------------------------- */ #define TclSetIntObj(objPtr, i) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ ir.wideValue = (Tcl_WideInt) i; \ TclInvalidateStringRep(objPtr); \ - Tcl_StoreIntRep(objPtr, &tclIntType, &ir); \ + Tcl_StoreInternalRep(objPtr, &tclIntType, &ir); \ } while (0) #define TclSetDoubleObj(objPtr, d) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ ir.doubleValue = (double) d; \ TclInvalidateStringRep(objPtr); \ - Tcl_StoreIntRep(objPtr, &tclDoubleType, &ir); \ + Tcl_StoreInternalRep(objPtr, &tclDoubleType, &ir); \ } while (0) /* *---------------------------------------------------------------- * Macros used by the Tcl core to create and initialise objects of standard @@ -4794,11 +4836,11 @@ * types, avoiding the corresponding function calls in time critical parts of * the core. The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE void TclNewIntObj(Tcl_Obj *objPtr, Tcl_WideInt w); * MODULE_SCOPE void TclNewDoubleObj(Tcl_Obj *objPtr, double d); - * MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, const char *s, size_t len); + * MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, const char *s, Tcl_Size len); * MODULE_SCOPE void TclNewLiteralStringObj(Tcl_Obj*objPtr, const char *sLiteral); * *---------------------------------------------------------------- */ @@ -4812,21 +4854,32 @@ (objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \ (objPtr)->typePtr = &tclIntType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) -#define TclNewIndexObj(objPtr, w) \ +#define TclNewUIntObj(objPtr, uw) \ do { \ - size_t _w = (w); \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = NULL; \ - (objPtr)->internalRep.wideValue = ((_w) == TCL_INDEX_NONE) ? -1 : (Tcl_WideInt)(_w); \ - (objPtr)->typePtr = &tclIntType; \ + Tcl_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); \ @@ -4848,13 +4901,28 @@ } while (0) #else /* TCL_MEM_DEBUG */ #define TclNewIntObj(objPtr, w) \ (objPtr) = Tcl_NewWideIntObj(w) + +#define TclNewUIntObj(objPtr, uw) \ + do { \ + Tcl_WideUInt uw_ = (uw); \ + if (uw_ > WIDE_MAX) { \ + mp_int bignumValue_; \ + if (mp_init_u64(&bignumValue_, uw_) == MP_OKAY) { \ + (objPtr) = Tcl_NewBignumObj(&bignumValue_); \ + } else { \ + (objPtr) = NULL; \ + } \ + } else { \ + (objPtr) = Tcl_NewWideIntObj(uw_); \ + } \ + } while (0) #define TclNewIndexObj(objPtr, w) \ - (objPtr) = ((w) == TCL_INDEX_NONE) ? Tcl_NewWideIntObj(-1) : Tcl_NewWideIntObj(w) + TclNewIntObj(objPtr, w) #define TclNewDoubleObj(objPtr, d) \ (objPtr) = Tcl_NewDoubleObj(d) #define TclNewStringObj(objPtr, s, len) \ @@ -4881,36 +4949,10 @@ #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. */ @@ -5010,31 +5052,31 @@ do { \ Tcl_Obj *_objPtr; \ TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \ TclIncrObjsAllocated(); \ TclAllocObjStorageEx((interp), (_objPtr)); \ - *(void **)&memPtr = (void *) (_objPtr); \ + *(void **)&(memPtr) = (void *) (_objPtr); \ } while (0) #define TclSmallFreeEx(interp, memPtr) \ do { \ - TclFreeObjStorageEx((interp), (Tcl_Obj *)memPtr); \ + TclFreeObjStorageEx((interp), (Tcl_Obj *)(memPtr)); \ TclIncrObjsFreed(); \ } while (0) #else /* TCL_MEM_DEBUG */ #define TclSmallAllocEx(interp, nbytes, memPtr) \ do { \ Tcl_Obj *_objPtr; \ TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \ TclNewObj(_objPtr); \ - *(void **)&memPtr = (void *) _objPtr; \ + *(void **)&(memPtr) = (void *)_objPtr; \ } while (0) #define TclSmallFreeEx(interp, memPtr) \ do { \ - Tcl_Obj *_objPtr = (Tcl_Obj *) memPtr; \ + Tcl_Obj *_objPtr = (Tcl_Obj *)(memPtr); \ _objPtr->bytes = NULL; \ _objPtr->typePtr = NULL; \ _objPtr->refCount = 1; \ TclDecrRefCount(_objPtr); \ } while (0) @@ -5103,11 +5145,11 @@ #define TCLNR_ALLOC(interp, ptr) \ TclSmallAllocEx(interp, sizeof(NRE_callback), (ptr)) #define TCLNR_FREE(interp, ptr) TclSmallFreeEx((interp), (ptr)) #else #define TCLNR_ALLOC(interp, ptr) \ - (ptr = (Tcl_Alloc(sizeof(NRE_callback)))) + ((ptr) = Tcl_Alloc(sizeof(NRE_callback))) #define TCLNR_FREE(interp, ptr) Tcl_Free(ptr) #endif #if NRE_ENABLE_ASSERTS #define NRE_ASSERT(expr) assert((expr)) @@ -5122,14 +5164,42 @@ #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: */ Index: generic/tclIntDecls.h ================================================================== --- generic/tclIntDecls.h +++ generic/tclIntDecls.h @@ -48,20 +48,21 @@ /* Slot 2 is reserved */ /* 3 */ EXTERN void TclAllocateFreeObjects(void); /* Slot 4 is reserved */ /* 5 */ -EXTERN int TclCleanupChildren(Tcl_Interp *interp, int numPids, - Tcl_Pid *pidPtr, Tcl_Channel errorChan); +EXTERN int TclCleanupChildren(Tcl_Interp *interp, + Tcl_Size numPids, Tcl_Pid *pidPtr, + Tcl_Channel errorChan); /* 6 */ EXTERN void TclCleanupCommand(Command *cmdPtr); /* 7 */ -EXTERN size_t TclCopyAndCollapse(size_t count, const char *src, +EXTERN Tcl_Size TclCopyAndCollapse(Tcl_Size count, const char *src, char *dst); /* Slot 8 is reserved */ /* 9 */ -EXTERN int TclCreatePipeline(Tcl_Interp *interp, int argc, +EXTERN Tcl_Size TclCreatePipeline(Tcl_Interp *interp, Tcl_Size argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr); /* 10 */ EXTERN int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr, @@ -84,18 +85,18 @@ /* Slot 19 is reserved */ /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* 22 */ EXTERN int TclFindElement(Tcl_Interp *interp, - const char *listStr, int listLength, + const char *listStr, Tcl_Size listLength, const char **elementPtr, - const char **nextPtr, size_t *sizePtr, + const char **nextPtr, Tcl_Size *sizePtr, int *bracePtr); /* 23 */ EXTERN Proc * TclFindProc(Interp *iPtr, const char *procName); /* 24 */ -EXTERN size_t TclFormatInt(char *buffer, Tcl_WideInt n); +EXTERN Tcl_Size TclFormatInt(char *buffer, Tcl_WideInt n); /* 25 */ EXTERN void TclFreePackageInfo(Interp *iPtr); /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* 28 */ @@ -109,34 +110,31 @@ 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); +/* 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 TclObjCmdProcType TclGetObjInterpProc(void); +EXTERN Tcl_ObjCmdProc * 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); +/* 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 */ @@ -144,18 +142,12 @@ /* 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[]); +/* Slot 53 is reserved */ +/* Slot 54 is reserved */ /* 55 */ EXTERN Proc * TclIsProc(Command *cmdPtr); /* Slot 56 is reserved */ /* Slot 57 is reserved */ /* 58 */ @@ -168,39 +160,36 @@ 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[]); +/* Slot 63 is reserved */ /* 64 */ -EXTERN int TclObjInvoke(Tcl_Interp *interp, int objc, +EXTERN int TclObjInvoke(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* Slot 65 is reserved */ /* Slot 66 is reserved */ /* Slot 67 is reserved */ /* Slot 68 is reserved */ /* 69 */ -EXTERN void * TclpAlloc(size_t size); +EXTERN void * TclpAlloc(TCL_HASH_TYPE size); /* Slot 70 is reserved */ /* Slot 71 is reserved */ /* Slot 72 is reserved */ /* Slot 73 is reserved */ /* 74 */ EXTERN void TclpFree(void *ptr); /* 75 */ -EXTERN Tcl_WideUInt TclpGetClicks(void); +EXTERN unsigned long long TclpGetClicks(void); /* 76 */ -EXTERN Tcl_WideUInt TclpGetSeconds(void); +EXTERN unsigned long long TclpGetSeconds(void); /* Slot 77 is reserved */ /* Slot 78 is reserved */ /* Slot 79 is reserved */ /* Slot 80 is reserved */ /* 81 */ -EXTERN void * TclpRealloc(void *ptr, size_t size); +EXTERN void * TclpRealloc(void *ptr, TCL_HASH_TYPE size); /* Slot 82 is reserved */ /* Slot 83 is reserved */ /* Slot 84 is reserved */ /* Slot 85 is reserved */ /* Slot 86 is reserved */ @@ -229,12 +218,11 @@ Command *newCmdPtr); /* 98 */ EXTERN int TclServiceIdle(void); /* Slot 99 is reserved */ /* Slot 100 is reserved */ -/* 101 */ -EXTERN const char * TclSetPreInitScript(const char *string); +/* 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); @@ -245,11 +233,11 @@ /* 108 */ EXTERN void TclTeardownNamespace(Namespace *nsPtr); /* 109 */ EXTERN int TclUpdateReturnInfo(Interp *iPtr); /* 110 */ -EXTERN int TclSockMinimumBuffers(void *sock, int size); +EXTERN int TclSockMinimumBuffers(void *sock, Tcl_Size size); /* 111 */ EXTERN void Tcl_AddInterpResolvers(Tcl_Interp *interp, const char *name, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, @@ -293,12 +281,11 @@ EXTERN void Tcl_SetNamespaceResolvers( Tcl_Namespace *namespacePtr, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); -/* 132 */ -EXTERN int TclpHasSockets(Tcl_Interp *interp); +/* Slot 132 is reserved */ /* Slot 133 is reserved */ /* Slot 134 is reserved */ /* Slot 135 is reserved */ /* Slot 136 is reserved */ /* Slot 137 is reserved */ @@ -329,12 +316,12 @@ /* 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); +EXTERN void TclRegExpRangeUniChar(Tcl_RegExp re, Tcl_Size index, + Tcl_Size *startPtr, Tcl_Size *endPtr); /* 152 */ EXTERN void TclSetLibraryPath(Tcl_Obj *pathPtr); /* 153 */ EXTERN Tcl_Obj * TclGetLibraryPath(void); /* Slot 154 is reserved */ @@ -360,33 +347,33 @@ EXTERN void TclExpandCodeArray(void *envPtr); /* 165 */ EXTERN void TclpSetInitialEncodings(void); /* 166 */ EXTERN int TclListObjSetElement(Tcl_Interp *interp, - Tcl_Obj *listPtr, int index, + Tcl_Obj *listPtr, Tcl_Size index, Tcl_Obj *valuePtr); /* Slot 167 is reserved */ /* Slot 168 is reserved */ /* 169 */ EXTERN int TclpUtfNcmp2(const char *s1, const char *s2, size_t n); /* 170 */ EXTERN int TclCheckInterpTraces(Tcl_Interp *interp, - const char *command, size_t numChars, + const char *command, Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags, - int objc, Tcl_Obj *const objv[]); + Tcl_Size objc, Tcl_Obj *const objv[]); /* 171 */ EXTERN int TclCheckExecutionTraces(Tcl_Interp *interp, - const char *command, size_t numChars, + const char *command, Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags, - int objc, Tcl_Obj *const objv[]); + Tcl_Size objc, Tcl_Obj *const objv[]); /* 172 */ EXTERN int TclInThreadExit(void); /* 173 */ EXTERN int TclUniCharMatch(const Tcl_UniChar *string, - size_t strLen, const Tcl_UniChar *pattern, - size_t ptnLen, int flags); + Tcl_Size strLen, const Tcl_UniChar *pattern, + Tcl_Size ptnLen, int flags); /* Slot 174 is reserved */ /* 175 */ EXTERN int TclCallVarTraces(Interp *iPtr, Var *arrayPtr, Var *varPtr, const char *part1, const char *part2, int flags, @@ -453,46 +440,53 @@ EXTERN Tcl_Obj * TclGetObjNameOfExecutable(void); /* 214 */ EXTERN void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding); /* 215 */ -EXTERN void * TclStackAlloc(Tcl_Interp *interp, size_t numBytes); +EXTERN void * TclStackAlloc(Tcl_Interp *interp, + TCL_HASH_TYPE numBytes); /* 216 */ EXTERN void TclStackFree(Tcl_Interp *interp, void *freePtr); /* 217 */ EXTERN int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 218 */ EXTERN void TclPopStackFrame(Tcl_Interp *interp); -/* Slot 219 is reserved */ +/* 219 */ +EXTERN Tcl_Obj * TclpCreateTemporaryDirectory(Tcl_Obj *dirObj, + Tcl_Obj *basenameObj); /* Slot 220 is reserved */ -/* Slot 221 is reserved */ -/* Slot 222 is reserved */ -/* Slot 223 is reserved */ +/* 221 */ +EXTERN Tcl_Obj * TclListTestObj(size_t length, size_t leadingSpace, + size_t endSpace); +/* 222 */ +EXTERN void TclListObjValidate(Tcl_Interp *interp, + Tcl_Obj *listObj); +/* 223 */ +EXTERN void * TclGetCStackPtr(void); /* 224 */ EXTERN TclPlatformType * TclGetPlatform(void); /* 225 */ EXTERN Tcl_Obj * TclTraceDictPath(Tcl_Interp *interp, - Tcl_Obj *rootPtr, int keyc, + Tcl_Obj *rootPtr, Tcl_Size keyc, Tcl_Obj *const keyv[], int flags); /* 226 */ EXTERN int TclObjBeingDeleted(Tcl_Obj *objPtr); /* 227 */ -EXTERN void TclSetNsPath(Namespace *nsPtr, size_t pathLength, +EXTERN void TclSetNsPath(Namespace *nsPtr, Tcl_Size pathLength, Tcl_Namespace *pathAry[]); /* Slot 228 is reserved */ /* 229 */ EXTERN int TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr, const char *myName, int myFlags, int index); /* 230 */ EXTERN Var * TclObjLookupVar(Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, - int flags, const char *msg, - const int createPart1, const int createPart2, - Var **arrayPtrPtr); + 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, @@ -508,23 +502,23 @@ /* Slot 236 is reserved */ /* 237 */ EXTERN int TclResetCancellation(Tcl_Interp *interp, int force); /* 238 */ EXTERN int TclNRInterpProc(void *clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *const objv[]); + Tcl_Size objc, Tcl_Obj *const objv[]); /* 239 */ EXTERN int TclNRInterpProcCore(Tcl_Interp *interp, - Tcl_Obj *procNameObj, int skip, + Tcl_Obj *procNameObj, Tcl_Size skip, ProcErrorProc *errorProc); /* 240 */ EXTERN int TclNRRunCallbacks(Tcl_Interp *interp, int result, struct NRE_callback *rootPtr); /* 241 */ EXTERN int TclNREvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 242 */ -EXTERN int TclNREvalObjv(Tcl_Interp *interp, int objc, +EXTERN int TclNREvalObjv(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags, Command *cmdPtr); /* 243 */ EXTERN void TclDbDumpActiveObjects(FILE *outFile); /* 244 */ @@ -531,64 +525,61 @@ EXTERN Tcl_HashTable * TclGetNamespaceChildTable(Tcl_Namespace *nsPtr); /* 245 */ EXTERN Tcl_HashTable * TclGetNamespaceCommandTable(Tcl_Namespace *nsPtr); /* 246 */ EXTERN int TclInitRewriteEnsemble(Tcl_Interp *interp, - size_t numRemoved, size_t numInserted, + Tcl_Size numRemoved, Tcl_Size numInserted, Tcl_Obj *const *objv); /* 247 */ EXTERN void TclResetRewriteEnsemble(Tcl_Interp *interp, int isRootEnsemble); /* 248 */ EXTERN int TclCopyChannel(Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, - Tcl_WideInt toRead, Tcl_Obj *cmdPtr); + long long toRead, Tcl_Obj *cmdPtr); /* 249 */ EXTERN char * TclDoubleDigits(double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 250 */ EXTERN void TclSetChildCancelFlags(Tcl_Interp *interp, int flags, int force); /* 251 */ EXTERN int TclRegisterLiteral(void *envPtr, const char *bytes, - size_t length, int flags); + Tcl_Size length, int flags); /* 252 */ EXTERN Tcl_Obj * TclPtrGetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, - Tcl_Obj *part2Ptr, const int flags); + Tcl_Obj *part2Ptr, int flags); /* 253 */ EXTERN Tcl_Obj * TclPtrSetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, - const int flags); + int flags); /* 254 */ EXTERN Tcl_Obj * TclPtrIncrObjVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, - const int flags); + int flags); /* 255 */ EXTERN int TclPtrObjMakeUpvar(Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags); /* 256 */ EXTERN int TclPtrUnsetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, - Tcl_Obj *part2Ptr, const int flags); + Tcl_Obj *part2Ptr, int flags); /* 257 */ -EXTERN void TclStaticPackage(Tcl_Interp *interp, - const char *pkgName, - Tcl_PackageInitProc *initProc, - Tcl_PackageInitProc *safeInitProc); -/* 258 */ -EXTERN Tcl_Obj * TclpCreateTemporaryDirectory(Tcl_Obj *dirObj, - Tcl_Obj *basenameObj); +EXTERN void TclStaticLibrary(Tcl_Interp *interp, + const char *prefix, + Tcl_LibraryInitProc *initProc, + Tcl_LibraryInitProc *safeInitProc); +/* Slot 258 is reserved */ /* 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); +EXTERN int TclMSB(size_t n); +/* Slot 260 is reserved */ +/* 261 */ +EXTERN void TclUnusedStubEntry(void); typedef struct TclIntStubs { int magic; void *hooks; @@ -595,15 +586,15 @@ void (*reserved0)(void); void (*reserved1)(void); void (*reserved2)(void); void (*tclAllocateFreeObjects) (void); /* 3 */ void (*reserved4)(void); - int (*tclCleanupChildren) (Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 5 */ + int (*tclCleanupChildren) (Tcl_Interp *interp, Tcl_Size numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 5 */ void (*tclCleanupCommand) (Command *cmdPtr); /* 6 */ - size_t (*tclCopyAndCollapse) (size_t count, const char *src, char *dst); /* 7 */ + Tcl_Size (*tclCopyAndCollapse) (Tcl_Size count, const char *src, char *dst); /* 7 */ void (*reserved8)(void); - int (*tclCreatePipeline) (Tcl_Interp *interp, int argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr); /* 9 */ + Tcl_Size (*tclCreatePipeline) (Tcl_Interp *interp, Tcl_Size argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr); /* 9 */ int (*tclCreateProc) (Tcl_Interp *interp, Namespace *nsPtr, const char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr); /* 10 */ void (*tclDeleteCompiledLocalVars) (Interp *iPtr, CallFrame *framePtr); /* 11 */ void (*tclDeleteVars) (Interp *iPtr, TclVarHashTable *tablePtr); /* 12 */ void (*reserved13)(void); int (*tclDumpMemoryInfo) (void *clientData, int flags); /* 14 */ @@ -612,13 +603,13 @@ void (*reserved17)(void); void (*reserved18)(void); void (*reserved19)(void); void (*reserved20)(void); void (*reserved21)(void); - int (*tclFindElement) (Tcl_Interp *interp, const char *listStr, int listLength, const char **elementPtr, const char **nextPtr, size_t *sizePtr, int *bracePtr); /* 22 */ + int (*tclFindElement) (Tcl_Interp *interp, const char *listStr, Tcl_Size listLength, const char **elementPtr, const char **nextPtr, Tcl_Size *sizePtr, int *bracePtr); /* 22 */ Proc * (*tclFindProc) (Interp *iPtr, const char *procName); /* 23 */ - size_t (*tclFormatInt) (char *buffer, Tcl_WideInt n); /* 24 */ + Tcl_Size (*tclFormatInt) (char *buffer, Tcl_WideInt n); /* 24 */ void (*tclFreePackageInfo) (Interp *iPtr); /* 25 */ void (*reserved26)(void); void (*reserved27)(void); Tcl_Channel (*tclpGetDefaultStdChannel) (int type); /* 28 */ void (*reserved29)(void); @@ -627,55 +618,55 @@ int (*tclGetFrame) (Tcl_Interp *interp, const char *str, CallFrame **framePtrPtr); /* 32 */ void (*reserved33)(void); void (*reserved34)(void); void (*reserved35)(void); void (*reserved36)(void); - int (*tclGetLoadedPackages) (Tcl_Interp *interp, const char *targetName); /* 37 */ + void (*reserved37)(void); int (*tclGetNamespaceForQualName) (Tcl_Interp *interp, const char *qualName, Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr, Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr, const char **simpleNamePtr); /* 38 */ - TclObjCmdProcType (*tclGetObjInterpProc) (void); /* 39 */ + Tcl_ObjCmdProc * (*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 */ + 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); - int (*tclInvokeObjectCommand) (void *clientData, Tcl_Interp *interp, int argc, const char **argv); /* 53 */ - int (*tclInvokeStringCommand) (void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 54 */ + void (*reserved53)(void); + void (*reserved54)(void); Proc * (*tclIsProc) (Command *cmdPtr); /* 55 */ void (*reserved56)(void); void (*reserved57)(void); Var * (*tclLookupVar) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, const char *msg, int createPart1, int createPart2, Var **arrayPtrPtr); /* 58 */ void (*reserved59)(void); int (*tclNeedSpace) (const char *start, const char *end); /* 60 */ Tcl_Obj * (*tclNewProcBodyObj) (Proc *procPtr); /* 61 */ int (*tclObjCommandComplete) (Tcl_Obj *cmdPtr); /* 62 */ - int (*tclObjInterpProc) (void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 63 */ - int (*tclObjInvoke) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 64 */ + void (*reserved63)(void); + int (*tclObjInvoke) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags); /* 64 */ void (*reserved65)(void); void (*reserved66)(void); void (*reserved67)(void); void (*reserved68)(void); - void * (*tclpAlloc) (size_t size); /* 69 */ + void * (*tclpAlloc) (TCL_HASH_TYPE size); /* 69 */ void (*reserved70)(void); void (*reserved71)(void); void (*reserved72)(void); void (*reserved73)(void); void (*tclpFree) (void *ptr); /* 74 */ - Tcl_WideUInt (*tclpGetClicks) (void); /* 75 */ - Tcl_WideUInt (*tclpGetSeconds) (void); /* 76 */ + unsigned long long (*tclpGetClicks) (void); /* 75 */ + unsigned long long (*tclpGetSeconds) (void); /* 76 */ void (*reserved77)(void); void (*reserved78)(void); void (*reserved79)(void); void (*reserved80)(void); - void * (*tclpRealloc) (void *ptr, size_t size); /* 81 */ + void * (*tclpRealloc) (void *ptr, TCL_HASH_TYPE size); /* 81 */ void (*reserved82)(void); void (*reserved83)(void); void (*reserved84)(void); void (*reserved85)(void); void (*reserved86)(void); @@ -691,20 +682,20 @@ int (*tclRenameCommand) (Tcl_Interp *interp, const char *oldName, const char *newName); /* 96 */ void (*tclResetShadowedCmdRefs) (Tcl_Interp *interp, Command *newCmdPtr); /* 97 */ int (*tclServiceIdle) (void); /* 98 */ void (*reserved99)(void); void (*reserved100)(void); - const char * (*tclSetPreInitScript) (const char *string); /* 101 */ + void (*reserved101)(void); void (*tclSetupEnv) (Tcl_Interp *interp); /* 102 */ int (*tclSockGetPort) (Tcl_Interp *interp, const char *str, const char *proto, int *portPtr); /* 103 */ void (*reserved104)(void); void (*reserved105)(void); void (*reserved106)(void); void (*reserved107)(void); void (*tclTeardownNamespace) (Namespace *nsPtr); /* 108 */ int (*tclUpdateReturnInfo) (Interp *iPtr); /* 109 */ - int (*tclSockMinimumBuffers) (void *sock, int size); /* 110 */ + int (*tclSockMinimumBuffers) (void *sock, Tcl_Size size); /* 110 */ void (*tcl_AddInterpResolvers) (Tcl_Interp *interp, const char *name, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 111 */ void (*reserved112)(void); void (*reserved113)(void); void (*reserved114)(void); void (*reserved115)(void); @@ -722,11 +713,11 @@ void (*reserved127)(void); void (*tcl_PopCallFrame) (Tcl_Interp *interp); /* 128 */ int (*tcl_PushCallFrame) (Tcl_Interp *interp, Tcl_CallFrame *framePtr, Tcl_Namespace *nsPtr, int isProcCallFrame); /* 129 */ int (*tcl_RemoveInterpResolvers) (Tcl_Interp *interp, const char *name); /* 130 */ void (*tcl_SetNamespaceResolvers) (Tcl_Namespace *namespacePtr, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 131 */ - int (*tclpHasSockets) (Tcl_Interp *interp); /* 132 */ + void (*reserved132)(void); void (*reserved133)(void); void (*reserved134)(void); void (*reserved135)(void); void (*reserved136)(void); void (*reserved137)(void); @@ -741,11 +732,11 @@ 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 (*tclRegExpRangeUniChar) (Tcl_RegExp re, Tcl_Size index, Tcl_Size *startPtr, Tcl_Size *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 */ @@ -756,18 +747,18 @@ int (*tclChannelTransform) (Tcl_Interp *interp, Tcl_Channel chan, Tcl_Obj *cmdObjPtr); /* 161 */ void (*tclChannelEventScriptInvoker) (void *clientData, int flags); /* 162 */ const void * (*tclGetInstructionTable) (void); /* 163 */ void (*tclExpandCodeArray) (void *envPtr); /* 164 */ void (*tclpSetInitialEncodings) (void); /* 165 */ - int (*tclListObjSetElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr); /* 166 */ + int (*tclListObjSetElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index, Tcl_Obj *valuePtr); /* 166 */ void (*reserved167)(void); void (*reserved168)(void); int (*tclpUtfNcmp2) (const char *s1, const char *s2, size_t n); /* 169 */ - int (*tclCheckInterpTraces) (Tcl_Interp *interp, const char *command, size_t numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 170 */ - int (*tclCheckExecutionTraces) (Tcl_Interp *interp, const char *command, size_t numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 171 */ + int (*tclCheckInterpTraces) (Tcl_Interp *interp, const char *command, Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags, Tcl_Size objc, Tcl_Obj *const objv[]); /* 170 */ + int (*tclCheckExecutionTraces) (Tcl_Interp *interp, const char *command, Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags, Tcl_Size objc, Tcl_Obj *const objv[]); /* 171 */ int (*tclInThreadExit) (void); /* 172 */ - int (*tclUniCharMatch) (const Tcl_UniChar *string, size_t strLen, const Tcl_UniChar *pattern, size_t ptnLen, int flags); /* 173 */ + int (*tclUniCharMatch) (const Tcl_UniChar *string, Tcl_Size strLen, const Tcl_UniChar *pattern, Tcl_Size ptnLen, int flags); /* 173 */ void (*reserved174)(void); int (*tclCallVarTraces) (Interp *iPtr, Var *arrayPtr, Var *varPtr, const char *part1, const char *part2, int flags, int leaveErrMsg); /* 175 */ void (*tclCleanupVar) (Var *varPtr, Var *arrayPtr); /* 176 */ void (*tclVarErrMsg) (Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason); /* 177 */ void (*reserved178)(void); @@ -805,56 +796,57 @@ void (*reserved210)(void); void (*reserved211)(void); void (*tclpFindExecutable) (const char *argv0); /* 212 */ Tcl_Obj * (*tclGetObjNameOfExecutable) (void); /* 213 */ void (*tclSetObjNameOfExecutable) (Tcl_Obj *name, Tcl_Encoding encoding); /* 214 */ - void * (*tclStackAlloc) (Tcl_Interp *interp, size_t numBytes); /* 215 */ + void * (*tclStackAlloc) (Tcl_Interp *interp, TCL_HASH_TYPE numBytes); /* 215 */ void (*tclStackFree) (Tcl_Interp *interp, void *freePtr); /* 216 */ int (*tclPushStackFrame) (Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 217 */ void (*tclPopStackFrame) (Tcl_Interp *interp); /* 218 */ - void (*reserved219)(void); + Tcl_Obj * (*tclpCreateTemporaryDirectory) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj); /* 219 */ void (*reserved220)(void); - void (*reserved221)(void); - void (*reserved222)(void); - void (*reserved223)(void); + Tcl_Obj * (*tclListTestObj) (size_t length, size_t leadingSpace, size_t endSpace); /* 221 */ + void (*tclListObjValidate) (Tcl_Interp *interp, Tcl_Obj *listObj); /* 222 */ + void * (*tclGetCStackPtr) (void); /* 223 */ TclPlatformType * (*tclGetPlatform) (void); /* 224 */ - Tcl_Obj * (*tclTraceDictPath) (Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *const keyv[], int flags); /* 225 */ + Tcl_Obj * (*tclTraceDictPath) (Tcl_Interp *interp, Tcl_Obj *rootPtr, Tcl_Size keyc, Tcl_Obj *const keyv[], int flags); /* 225 */ int (*tclObjBeingDeleted) (Tcl_Obj *objPtr); /* 226 */ - void (*tclSetNsPath) (Namespace *nsPtr, size_t pathLength, Tcl_Namespace *pathAry[]); /* 227 */ + void (*tclSetNsPath) (Namespace *nsPtr, Tcl_Size pathLength, Tcl_Namespace *pathAry[]); /* 227 */ void (*reserved228)(void); int (*tclPtrMakeUpvar) (Tcl_Interp *interp, Var *otherP1Ptr, const char *myName, int myFlags, int index); /* 229 */ - Var * (*tclObjLookupVar) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, int flags, const char *msg, const int createPart1, const int createPart2, Var **arrayPtrPtr); /* 230 */ + Var * (*tclObjLookupVar) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, int flags, const char *msg, int createPart1, int createPart2, Var **arrayPtrPtr); /* 230 */ int (*tclGetNamespaceFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr); /* 231 */ int (*tclEvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 232 */ void (*tclGetSrcInfoForPc) (CmdFrame *contextPtr); /* 233 */ Var * (*tclVarHashCreateVar) (TclVarHashTable *tablePtr, const char *key, int *newPtr); /* 234 */ void (*tclInitVarHashTable) (TclVarHashTable *tablePtr, Namespace *nsPtr); /* 235 */ void (*reserved236)(void); int (*tclResetCancellation) (Tcl_Interp *interp, int force); /* 237 */ - int (*tclNRInterpProc) (void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 238 */ - int (*tclNRInterpProcCore) (Tcl_Interp *interp, Tcl_Obj *procNameObj, int skip, ProcErrorProc *errorProc); /* 239 */ + int (*tclNRInterpProc) (void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); /* 238 */ + int (*tclNRInterpProcCore) (Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Size skip, ProcErrorProc *errorProc); /* 239 */ int (*tclNRRunCallbacks) (Tcl_Interp *interp, int result, struct NRE_callback *rootPtr); /* 240 */ int (*tclNREvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 241 */ - int (*tclNREvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags, Command *cmdPtr); /* 242 */ + int (*tclNREvalObjv) (Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int flags, Command *cmdPtr); /* 242 */ void (*tclDbDumpActiveObjects) (FILE *outFile); /* 243 */ Tcl_HashTable * (*tclGetNamespaceChildTable) (Tcl_Namespace *nsPtr); /* 244 */ Tcl_HashTable * (*tclGetNamespaceCommandTable) (Tcl_Namespace *nsPtr); /* 245 */ - int (*tclInitRewriteEnsemble) (Tcl_Interp *interp, size_t numRemoved, size_t numInserted, Tcl_Obj *const *objv); /* 246 */ + int (*tclInitRewriteEnsemble) (Tcl_Interp *interp, Tcl_Size numRemoved, Tcl_Size numInserted, Tcl_Obj *const *objv); /* 246 */ void (*tclResetRewriteEnsemble) (Tcl_Interp *interp, int isRootEnsemble); /* 247 */ - int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr); /* 248 */ + int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, long long toRead, Tcl_Obj *cmdPtr); /* 248 */ char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */ void (*tclSetChildCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */ - int (*tclRegisterLiteral) (void *envPtr, const char *bytes, size_t length, int flags); /* 251 */ - Tcl_Obj * (*tclPtrGetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 252 */ - Tcl_Obj * (*tclPtrSetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, const int flags); /* 253 */ - Tcl_Obj * (*tclPtrIncrObjVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, const int flags); /* 254 */ + int (*tclRegisterLiteral) (void *envPtr, const char *bytes, Tcl_Size length, int flags); /* 251 */ + Tcl_Obj * (*tclPtrGetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 252 */ + Tcl_Obj * (*tclPtrSetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 253 */ + Tcl_Obj * (*tclPtrIncrObjVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, int flags); /* 254 */ int (*tclPtrObjMakeUpvar) (Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags); /* 255 */ - int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 256 */ - void (*tclStaticPackage) (Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 257 */ - Tcl_Obj * (*tclpCreateTemporaryDirectory) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj); /* 258 */ - void (*tclAppendUnicodeToObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, size_t length); /* 259 */ - unsigned char * (*tclGetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, size_t *lengthPtr); /* 260 */ + int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 256 */ + void (*tclStaticLibrary) (Tcl_Interp *interp, const char *prefix, Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc); /* 257 */ + void (*reserved258)(void); + int (*tclMSB) (size_t n); /* 259 */ + void (*reserved260)(void); + void (*tclUnusedStubEntry) (void); /* 261 */ } TclIntStubs; extern const TclIntStubs *tclIntStubsPtr; #ifdef __cplusplus @@ -919,12 +911,11 @@ (tclIntStubsPtr->tclGetFrame) /* 32 */ /* Slot 33 is reserved */ /* Slot 34 is reserved */ /* Slot 35 is reserved */ /* Slot 36 is reserved */ -#define TclGetLoadedPackages \ - (tclIntStubsPtr->tclGetLoadedPackages) /* 37 */ +/* Slot 37 is reserved */ #define TclGetNamespaceForQualName \ (tclIntStubsPtr->tclGetNamespaceForQualName) /* 38 */ #define TclGetObjInterpProc \ (tclIntStubsPtr->tclGetObjInterpProc) /* 39 */ #define TclGetOpenMode \ @@ -931,13 +922,13 @@ (tclIntStubsPtr->tclGetOpenMode) /* 40 */ #define TclGetOriginalCommand \ (tclIntStubsPtr->tclGetOriginalCommand) /* 41 */ #define TclpGetUserHome \ (tclIntStubsPtr->tclpGetUserHome) /* 42 */ -/* Slot 43 is reserved */ -#define TclGuessPackageName \ - (tclIntStubsPtr->tclGuessPackageName) /* 44 */ +#define TclGetObjInterpProc2 \ + (tclIntStubsPtr->tclGetObjInterpProc2) /* 43 */ +/* Slot 44 is reserved */ #define TclHideUnsafeCommands \ (tclIntStubsPtr->tclHideUnsafeCommands) /* 45 */ #define TclInExit \ (tclIntStubsPtr->tclInExit) /* 46 */ /* Slot 47 is reserved */ @@ -945,14 +936,12 @@ /* 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 */ +/* Slot 53 is reserved */ +/* Slot 54 is reserved */ #define TclIsProc \ (tclIntStubsPtr->tclIsProc) /* 55 */ /* Slot 56 is reserved */ /* Slot 57 is reserved */ #define TclLookupVar \ @@ -962,12 +951,11 @@ (tclIntStubsPtr->tclNeedSpace) /* 60 */ #define TclNewProcBodyObj \ (tclIntStubsPtr->tclNewProcBodyObj) /* 61 */ #define TclObjCommandComplete \ (tclIntStubsPtr->tclObjCommandComplete) /* 62 */ -#define TclObjInterpProc \ - (tclIntStubsPtr->tclObjInterpProc) /* 63 */ +/* Slot 63 is reserved */ #define TclObjInvoke \ (tclIntStubsPtr->tclObjInvoke) /* 64 */ /* Slot 65 is reserved */ /* Slot 66 is reserved */ /* Slot 67 is reserved */ @@ -1014,12 +1002,11 @@ (tclIntStubsPtr->tclResetShadowedCmdRefs) /* 97 */ #define TclServiceIdle \ (tclIntStubsPtr->tclServiceIdle) /* 98 */ /* Slot 99 is reserved */ /* Slot 100 is reserved */ -#define TclSetPreInitScript \ - (tclIntStubsPtr->tclSetPreInitScript) /* 101 */ +/* Slot 101 is reserved */ #define TclSetupEnv \ (tclIntStubsPtr->tclSetupEnv) /* 102 */ #define TclSockGetPort \ (tclIntStubsPtr->tclSockGetPort) /* 103 */ /* Slot 104 is reserved */ @@ -1060,12 +1047,11 @@ (tclIntStubsPtr->tcl_PushCallFrame) /* 129 */ #define Tcl_RemoveInterpResolvers \ (tclIntStubsPtr->tcl_RemoveInterpResolvers) /* 130 */ #define Tcl_SetNamespaceResolvers \ (tclIntStubsPtr->tcl_SetNamespaceResolvers) /* 131 */ -#define TclpHasSockets \ - (tclIntStubsPtr->tclpHasSockets) /* 132 */ +/* Slot 132 is reserved */ /* Slot 133 is reserved */ /* Slot 134 is reserved */ /* Slot 135 is reserved */ /* Slot 136 is reserved */ /* Slot 137 is reserved */ @@ -1195,15 +1181,19 @@ (tclIntStubsPtr->tclStackFree) /* 216 */ #define TclPushStackFrame \ (tclIntStubsPtr->tclPushStackFrame) /* 217 */ #define TclPopStackFrame \ (tclIntStubsPtr->tclPopStackFrame) /* 218 */ -/* Slot 219 is reserved */ +#define TclpCreateTemporaryDirectory \ + (tclIntStubsPtr->tclpCreateTemporaryDirectory) /* 219 */ /* Slot 220 is reserved */ -/* Slot 221 is reserved */ -/* Slot 222 is reserved */ -/* Slot 223 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 \ @@ -1264,28 +1254,43 @@ (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 */ +#define TclStaticLibrary \ + (tclIntStubsPtr->tclStaticLibrary) /* 257 */ +/* Slot 258 is reserved */ +#define TclMSB \ + (tclIntStubsPtr->tclMSB) /* 259 */ +/* Slot 260 is reserved */ +#define TclUnusedStubEntry \ + (tclIntStubsPtr->tclUnusedStubEntry) /* 261 */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ #if defined(USE_TCL_STUBS) -#undef Tcl_StaticPackage -#define Tcl_StaticPackage \ - (tclIntStubsPtr->tclStaticPackage) +#undef Tcl_StaticLibrary +#define Tcl_StaticLibrary \ + (tclIntStubsPtr->tclStaticLibrary) #endif /* defined(USE_TCL_STUBS) */ + +#if (TCL_MAJOR_VERSION < 9) && defined(USE_TCL_STUBS) +#undef TclpGetClicks +#define TclpGetClicks() \ + ((unsigned long)tclIntStubsPtr->tclpGetClicks()) +#undef TclpGetSeconds +#define TclpGetSeconds() \ + ((unsigned long)tclIntStubsPtr->tclpGetSeconds()) +#undef TclGetObjInterpProc2 +#define TclGetObjInterpProc2 TclGetObjInterpProc +#endif + +#undef TclUnusedStubEntry +#define TclObjInterpProc TclGetObjInterpProc() +#define TclObjInterpProc2 TclGetObjInterpProc2() #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TCLINTDECLS */ Index: generic/tclIntPlatDecls.h ================================================================== --- generic/tclIntPlatDecls.h +++ generic/tclIntPlatDecls.h @@ -28,11 +28,11 @@ * WARNING: This file is automatically generated by the tools/genStubs.tcl * script. Any modifications to the function declarations below should be made * in the generic/tclInt.decls script. */ -/* !BEGIN!: Do not edit below this line. */ +#if TCL_MAJOR_VERSION < 9 #ifdef __cplusplus extern "C" { #endif @@ -65,14 +65,18 @@ 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 */ +/* 10 */ +EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir); +/* 11 */ +EXTERN struct tm * TclpLocaltime_unix(const time_t *clock); +/* 12 */ +EXTERN struct tm * TclpGmtime_unix(const time_t *clock); +/* 13 */ +EXTERN char * TclpInetNtoa(struct in_addr addr); /* 14 */ EXTERN int TclUnixCopyFile(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 15 */ @@ -112,24 +116,32 @@ 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 */ +EXTERN void TclWinConvertError(DWORD errCode); +/* 1 */ +EXTERN void TclWinConvertWSAError(DWORD errCode); +/* 2 */ +EXTERN struct servent * TclWinGetServByName(const char *nm, + const char *proto); +/* 3 */ +EXTERN int TclWinGetSockOpt(SOCKET s, int level, int optname, + char *optval, int *optlen); /* 4 */ -EXTERN void * TclWinGetTclInstance(void); +EXTERN HINSTANCE TclWinGetTclInstance(void); /* 5 */ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout); -/* Slot 6 is reserved */ -/* Slot 7 is reserved */ +/* 6 */ +EXTERN unsigned short TclWinNToHS(unsigned short ns); +/* 7 */ +EXTERN int TclWinSetSockOpt(SOCKET s, int level, int optname, + const char *optval, int optlen); /* 8 */ -EXTERN size_t TclpGetPid(Tcl_Pid pid); -/* Slot 9 is reserved */ -/* Slot 10 is reserved */ +EXTERN int TclpGetPid(Tcl_Pid pid); +/* 9 */ +EXTERN int TclWinGetPlatformId(void); /* 11 */ EXTERN void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan); /* 12 */ EXTERN int TclpCloseFile(TclFile file); @@ -153,22 +165,25 @@ /* 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 */ +EXTERN void TclWinAddProcess(void *hProcess, Tcl_Size id); +/* 21 */ +EXTERN char * TclpInetNtoa(struct in_addr addr); /* 22 */ EXTERN TclFile TclpCreateTempFile(const char *contents); /* Slot 23 is reserved */ /* 24 */ EXTERN char * TclWinNoBackslash(char *path); /* Slot 25 is reserved */ -/* Slot 26 is reserved */ +/* 26 */ +EXTERN void TclWinSetInterfaces(int wide); /* 27 */ EXTERN void TclWinFlushDirtyChannels(void); -/* Slot 28 is reserved */ +/* 28 */ +EXTERN void TclWinResetInterfaces(void); /* 29 */ EXTERN int TclWinCPUID(int index, int *regs); /* 30 */ EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, @@ -199,14 +214,18 @@ 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 */ +/* 10 */ +EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir); +/* 11 */ +EXTERN struct tm * TclpLocaltime_unix(const time_t *clock); +/* 12 */ +EXTERN struct tm * TclpGmtime_unix(const time_t *clock); +/* 13 */ +EXTERN char * TclpInetNtoa(struct in_addr addr); /* 14 */ EXTERN int TclUnixCopyFile(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 15 */ @@ -260,14 +279,14 @@ 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); + Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */ + struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */ + struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */ + char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ 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 */ int (*tclMacOSXMatchType) (Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 18 */ @@ -283,39 +302,39 @@ 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 */ + void (*tclWinConvertError) (DWORD errCode); /* 0 */ + void (*tclWinConvertWSAError) (DWORD errCode); /* 1 */ + struct servent * (*tclWinGetServByName) (const char *nm, const char *proto); /* 2 */ + int (*tclWinGetSockOpt) (SOCKET s, int level, int optname, char *optval, int *optlen); /* 3 */ + HINSTANCE (*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); + unsigned short (*tclWinNToHS) (unsigned short ns); /* 6 */ + int (*tclWinSetSockOpt) (SOCKET s, int level, int optname, const char *optval, int optlen); /* 7 */ + Tcl_Size (*tclpGetPid) (Tcl_Pid pid); /* 8 */ + int (*tclWinGetPlatformId) (void); /* 9 */ + void *(*tclpReaddir) (void *dir); /* 10 */ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 11 */ int (*tclpCloseFile) (TclFile file); /* 12 */ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 13 */ int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 14 */ int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 15 */ int (*tclpIsAtty) (int fd); /* 16 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 17 */ TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 18 */ TclFile (*tclpOpenFile) (const char *fname, int mode); /* 19 */ - void (*tclWinAddProcess) (void *hProcess, size_t id); /* 20 */ - void (*reserved21)(void); + void (*tclWinAddProcess) (void *hProcess, Tcl_Size id); /* 20 */ + char * (*tclpInetNtoa) (struct in_addr addr); /* 21 */ TclFile (*tclpCreateTempFile) (const char *contents); /* 22 */ void (*reserved23)(void); char * (*tclWinNoBackslash) (char *path); /* 24 */ void (*reserved25)(void); - void (*reserved26)(void); + void (*tclWinSetInterfaces) (int wide); /* 26 */ void (*tclWinFlushDirtyChannels) (void); /* 27 */ - void (*reserved28)(void); + void (*tclWinResetInterfaces) (void); /* 28 */ int (*tclWinCPUID) (int index, int *regs); /* 29 */ int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */ @@ -326,14 +345,14 @@ 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); + Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */ + struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */ + struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */ + char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ 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 */ int (*tclMacOSXMatchType) (Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 18 */ @@ -383,14 +402,18 @@ (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 TclpReaddir \ + (tclIntPlatStubsPtr->tclpReaddir) /* 10 */ +#define TclpLocaltime_unix \ + (tclIntPlatStubsPtr->tclpLocaltime_unix) /* 11 */ +#define TclpGmtime_unix \ + (tclIntPlatStubsPtr->tclpGmtime_unix) /* 12 */ +#define TclpInetNtoa \ + (tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */ #define TclUnixCopyFile \ (tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */ #define TclMacOSXGetFileAttribute \ (tclIntPlatStubsPtr->tclMacOSXGetFileAttribute) /* 15 */ #define TclMacOSXSetFileAttribute \ @@ -417,23 +440,28 @@ (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 TclWinConvertWSAError \ + (tclIntPlatStubsPtr->tclWinConvertWSAError) /* 1 */ +#define TclWinGetServByName \ + (tclIntPlatStubsPtr->tclWinGetServByName) /* 2 */ +#define TclWinGetSockOpt \ + (tclIntPlatStubsPtr->tclWinGetSockOpt) /* 3 */ #define TclWinGetTclInstance \ (tclIntPlatStubsPtr->tclWinGetTclInstance) /* 4 */ #define TclUnixWaitForFile \ (tclIntPlatStubsPtr->tclUnixWaitForFile) /* 5 */ -/* Slot 6 is reserved */ -/* Slot 7 is reserved */ +#define TclWinNToHS \ + (tclIntPlatStubsPtr->tclWinNToHS) /* 6 */ +#define TclWinSetSockOpt \ + (tclIntPlatStubsPtr->tclWinSetSockOpt) /* 7 */ #define TclpGetPid \ (tclIntPlatStubsPtr->tclpGetPid) /* 8 */ -/* Slot 9 is reserved */ -/* Slot 10 is reserved */ +#define TclWinGetPlatformId \ + (tclIntPlatStubsPtr->tclWinGetPlatformId) /* 9 */ #define TclGetAndDetachPids \ (tclIntPlatStubsPtr->tclGetAndDetachPids) /* 11 */ #define TclpCloseFile \ (tclIntPlatStubsPtr->tclpCloseFile) /* 12 */ #define TclpCreateCommandChannel \ @@ -450,21 +478,24 @@ (tclIntPlatStubsPtr->tclpMakeFile) /* 18 */ #define TclpOpenFile \ (tclIntPlatStubsPtr->tclpOpenFile) /* 19 */ #define TclWinAddProcess \ (tclIntPlatStubsPtr->tclWinAddProcess) /* 20 */ -/* Slot 21 is reserved */ +#define TclpInetNtoa \ + (tclIntPlatStubsPtr->tclpInetNtoa) /* 21 */ #define TclpCreateTempFile \ (tclIntPlatStubsPtr->tclpCreateTempFile) /* 22 */ /* Slot 23 is reserved */ #define TclWinNoBackslash \ (tclIntPlatStubsPtr->tclWinNoBackslash) /* 24 */ /* Slot 25 is reserved */ -/* Slot 26 is reserved */ +#define TclWinSetInterfaces \ + (tclIntPlatStubsPtr->tclWinSetInterfaces) /* 26 */ #define TclWinFlushDirtyChannels \ (tclIntPlatStubsPtr->tclWinFlushDirtyChannels) /* 27 */ -/* Slot 28 is reserved */ +#define TclWinResetInterfaces \ + (tclIntPlatStubsPtr->tclWinResetInterfaces) /* 28 */ #define TclWinCPUID \ (tclIntPlatStubsPtr->tclWinCPUID) /* 29 */ #define TclUnixOpenTemporaryFile \ (tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */ #endif /* WIN */ @@ -487,14 +518,18 @@ (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 TclpReaddir \ + (tclIntPlatStubsPtr->tclpReaddir) /* 10 */ +#define TclpLocaltime_unix \ + (tclIntPlatStubsPtr->tclpLocaltime_unix) /* 11 */ +#define TclpGmtime_unix \ + (tclIntPlatStubsPtr->tclpGmtime_unix) /* 12 */ +#define TclpInetNtoa \ + (tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */ #define TclUnixCopyFile \ (tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */ #define TclMacOSXGetFileAttribute \ (tclIntPlatStubsPtr->tclMacOSXGetFileAttribute) /* 15 */ #define TclMacOSXSetFileAttribute \ @@ -521,27 +556,244 @@ (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 size_t 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, size_t 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 */ + size_t (*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, size_t 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 +#undef TclpLocaltime_unix +#undef TclpGmtime_unix +#undef TclWinConvertWSAError #define TclWinConvertWSAError TclWinConvertError +#if !defined(TCL_USE_STUBS) && !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 +# undef TclWinConvertError +# define TclWinConvertError Tcl_WinConvertError +#endif + +#undef TclpInetNtoa +#define TclpInetNtoa inet_ntoa #undef TclpCreateTempFile_ #undef TclUnixWaitForFile_ -#ifndef MAC_OSX_TCL /* not accessable on Win32/UNIX */ +#ifdef MAC_OSX_TCL /* not accessible on Win32/UNIX */ +MODULE_SCOPE int TclMacOSXGetFileAttribute(Tcl_Interp *interp, + int objIndex, Tcl_Obj *fileName, + Tcl_Obj **attributePtrPtr); +/* 16 */ +MODULE_SCOPE int TclMacOSXSetFileAttribute(Tcl_Interp *interp, + int objIndex, Tcl_Obj *fileName, + Tcl_Obj *attributePtr); +/* 17 */ +MODULE_SCOPE int TclMacOSXCopyFileAttributes(const char *src, + const char *dst, + const Tcl_StatBuf *statBufPtr); +/* 18 */ +MODULE_SCOPE int TclMacOSXMatchType(Tcl_Interp *interp, + const char *pathName, const char *fileName, + Tcl_StatBuf *statBufPtr, + Tcl_GlobTypeData *types); +#else #undef TclMacOSXGetFileAttribute /* 15 */ #undef TclMacOSXSetFileAttribute /* 16 */ #undef TclMacOSXCopyFileAttributes /* 17 */ #undef TclMacOSXMatchType /* 18 */ #undef TclMacOSXNotifierAddRunLoopMode /* 19 */ #endif -#if !defined(_WIN32) +#if defined(_WIN32) +# undef TclWinNToHS +# undef TclWinGetServByName +# undef TclWinGetSockOpt +# undef TclWinSetSockOpt +# undef TclWinGetPlatformId +# undef TclWinResetInterfaces +# undef TclWinSetInterfaces +# if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 +# define TclWinNToHS ntohs +# define TclWinGetServByName getservbyname +# define TclWinGetSockOpt getsockopt +# define TclWinSetSockOpt setsockopt +# define TclWinGetPlatformId() (2) /* VER_PLATFORM_WIN32_NT */ +# define TclWinResetInterfaces() /* nop */ +# define TclWinSetInterfaces(dummy) /* nop */ +# endif /* TCL_NO_DEPRECATED */ +#else # undef TclpGetPid # define TclpGetPid(pid) ((size_t)(pid)) #endif #endif /* _TCLINTPLATDECLS */ Index: generic/tclInterp.c ================================================================== --- generic/tclInterp.c +++ generic/tclInterp.c @@ -2,12 +2,12 @@ * tclInterp.c -- * * This file implements the "interp" command which allows creation and * manipulation of Tcl interpreters from within Tcl scripts. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright (c) 2004 Donal K. Fellows + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2004 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -58,11 +58,11 @@ * will be appended to the prefix before the * command is invoked. */ Tcl_Obj *objPtr; /* The first actual prefix object - the target * command name; this has to be at the end of * the structure, which will be extended to - * accomodate the remaining objects in the + * accommodate the remaining objects in the * prefix. */ } Alias; /* * @@ -184,11 +184,11 @@ struct LimitHandler { int flags; /* The state of this particular handler. */ Tcl_LimitHandlerProc *handlerProc; /* The handler callback. */ - ClientData clientData; /* Opaque argument to the handler callback. */ + void *clientData; /* Opaque argument to the handler callback. */ Tcl_LimitHandlerDeleteProc *deleteProc; /* How to delete the clientData. */ LimitHandler *prevPtr; /* Previous item in linked list of * handlers. */ LimitHandler *nextPtr; /* Next item in linked list of handlers. */ @@ -195,11 +195,11 @@ }; /* * Values for the LimitHandler flags field. * LIMIT_HANDLER_ACTIVE - Whether the handler is currently being - * processed; handlers are never to be entered reentrantly. + * 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. */ @@ -263,16 +263,17 @@ 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, +static void CallScriptLimitCallback(void *clientData, Tcl_Interp *interp); -static void DeleteScriptLimitCallback(ClientData clientData); +static void DeleteScriptLimitCallback(void *clientData); +static void MakeSafe(Tcl_Interp *interp); static void RunLimitHandlers(LimitHandler *handlerPtr, Tcl_Interp *interp); -static void TimeLimitCallback(ClientData clientData); +static void TimeLimitCallback(void *clientData); /* NRE enabling */ static Tcl_NRPostProc NRPostInvokeHidden; static Tcl_ObjCmdProc NRInterpCmd; static Tcl_ObjCmdProc NRChildCmd; @@ -279,11 +280,11 @@ /* *---------------------------------------------------------------------- * - * TclSetPreInitScript -- + * Tcl_SetPreInitScript -- * * This routine is used to change the value of the internal variable, * tclPreInitScript. * * Results: @@ -294,16 +295,16 @@ * *---------------------------------------------------------------------- */ const char * -TclSetPreInitScript( +Tcl_SetPreInitScript( const char *string) /* Pointer to a script. */ { const char *prevString = tclPreInitScript; tclPreInitScript = string; - return(prevString); + return prevString; } /* *---------------------------------------------------------------------- * @@ -330,18 +331,18 @@ int Tcl_Init( Tcl_Interp *interp) /* Interpreter to initialize. */ { - PkgName pkgName = {NULL, "Tcl"}; + PkgName pkgName = {NULL, "tcl"}; PkgName **names = (PkgName **)TclInitPkgFiles(interp); int result = TCL_ERROR; pkgName.nextPtr = *names; *names = &pkgName; if (tclPreInitScript != NULL) { - if (Tcl_EvalEx(interp, tclPreInitScript, -1, 0) == TCL_ERROR) { + if (Tcl_EvalEx(interp, tclPreInitScript, TCL_INDEX_NONE, 0) == TCL_ERROR) { goto end; } } /* @@ -399,16 +400,16 @@ " lappend scripts {\n" "if {[regexp ^tcl(.*)$ [file tail $env(TCL_LIBRARY)] -> tail] == 0} continue\n" "if {$tail eq [info tclversion]} continue\n" "file join [file dirname $env(TCL_LIBRARY)] tcl[info tclversion]}\n" " }\n" +" lappend scripts {::tcl::zipfs::tcl_library_init}\n" " if {[info exists tclDefaultLibrary]} {\n" " lappend scripts {set tclDefaultLibrary}\n" " } else {\n" " lappend scripts {::tcl::pkgconfig get scriptdir,runtime}\n" " }\n" -" lappend scripts {::tcl::zipfs::tcl_library_init}\n" " lappend scripts {\n" "set parentDir [file dirname [file dirname [info nameofexecutable]]]\n" "set grandParentDir [file dirname $parentDir]\n" "file join $parentDir lib tcl[info tclversion]} \\\n" " {file join $grandParentDir lib tcl[info tclversion]} \\\n" @@ -447,11 +448,11 @@ " append msg \"$errors\n\n\"\n" " append msg \"This probably means that Tcl wasn't installed properly.\n\"\n" " error $msg\n" " }\n" "}\n" -"tclInit", -1, 0); +"tclInit", TCL_INDEX_NONE, 0); end: *names = (*names)->nextPtr; return result; } @@ -599,11 +600,11 @@ *---------------------------------------------------------------------- */ int Tcl_InterpObjCmd( - ClientData clientData, + 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); @@ -615,11 +616,10 @@ 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", @@ -647,11 +647,11 @@ 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; } @@ -660,11 +660,11 @@ /* Don't report the "slaves" option as possibility */ Tcl_GetIndexFromObj(interp, objv[1], optionsNoSlaves, "option", 0, &index); return TCL_ERROR; } - switch ((enum interpOptionEnum)index) { + switch (index) { case OPT_ALIAS: { Tcl_Interp *parentInterp; if (objc < 4) { aliasArgs: @@ -715,24 +715,24 @@ static const char *const cancelOptions[] = { "-unwind", "--", NULL }; enum optionCancelEnum { OPT_UNWIND, OPT_LAST - }; + } idx; flags = 0; for (i = 2; i < objc; i++) { if (TclGetString(objv[i])[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], cancelOptions, "option", - 0, &index) != TCL_OK) { + 0, &idx) != TCL_OK) { return TCL_ERROR; } - switch ((enum optionCancelEnum) index) { + switch (idx) { case OPT_UNWIND: /* * The evaluation stack in the target interp is to be unwound. */ @@ -788,11 +788,11 @@ 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. @@ -801,14 +801,14 @@ childPtr = NULL; last = 0; for (i = 2; i < objc; i++) { if ((last == 0) && (TclGetString(objv[i])[0] == '-')) { if (Tcl_GetIndexFromObj(interp, objv[i], createOptions, - "option", 0, &index) != TCL_OK) { + "option", 0, &idx) != TCL_OK) { return TCL_ERROR; } - if (index == OPT_SAFE) { + if (idx == OPT_SAFE) { safe = 1; continue; } i++; last = 1; @@ -831,11 +831,11 @@ */ for (i = 0; ; i++) { Tcl_CmdInfo cmdInfo; - sprintf(buf, "interp%d", i); + snprintf(buf, sizeof(buf), "interp%d", i); if (Tcl_GetCommandInfo(interp, buf, &cmdInfo) == 0) { break; } } childPtr = Tcl_NewStringObj(buf, -1); @@ -873,11 +873,11 @@ return TCL_ERROR; } else if (childInterp == interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot delete the current interpreter", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", - "DELETESELF", NULL); + "DELETESELF", (void *)NULL); return TCL_ERROR; } iiPtr = (InterpInfo *) ((Interp *) childInterp)->interpInfo; Tcl_DeleteCommandFromToken(iiPtr->child.parentInterp, iiPtr->child.interpCmd); @@ -947,24 +947,24 @@ static const char *const hiddenOptions[] = { "-global", "-namespace", "--", NULL }; enum hiddenOption { OPT_GLOBAL, OPT_NAMESPACE, OPT_LAST - }; + } idx; namespaceName = NULL; for (i = 3; i < objc; i++) { if (TclGetString(objv[i])[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option", - 0, &index) != TCL_OK) { + 0, &idx) != TCL_OK) { return TCL_ERROR; } - if (index == OPT_GLOBAL) { + if (idx == OPT_GLOBAL) { namespaceName = "::"; - } else if (index == OPT_NAMESPACE) { + } else if (idx == OPT_NAMESPACE) { if (++i == objc) { /* There must be more arguments. */ break; } else { namespaceName = TclGetString(objv[i]); } @@ -989,12 +989,11 @@ static const char *const limitTypes[] = { "commands", "time", NULL }; enum LimitTypes { LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME - }; - int limitType; + } limitType; if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "path limitType ?-option value ...?"); return TCL_ERROR; @@ -1005,11 +1004,11 @@ } if (Tcl_GetIndexFromObj(interp, objv[3], limitTypes, "limit type", 0, &limitType) != TCL_OK) { return TCL_ERROR; } - switch ((enum LimitTypes) limitType) { + switch (limitType) { case LIMIT_TYPE_COMMANDS: return ChildCommandLimitCmd(interp, childInterp, 4, objc,objv); case LIMIT_TYPE_TIME: return ChildTimeLimitCmd(interp, childInterp, 4, objc, objv); } @@ -1119,20 +1118,20 @@ 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); + (void *)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); + "TARGETSHROUDED", (void *)NULL); return TCL_ERROR; } return TCL_OK; } } @@ -1197,16 +1196,16 @@ Tcl_CreateAlias( Tcl_Interp *childInterp, /* Interpreter for source command. */ const char *childCmd, /* Command to install in child. */ Tcl_Interp *targetInterp, /* Interpreter for target command. */ const char *targetCmd, /* Name of target command. */ - int argc, /* How many additional arguments? */ + Tcl_Size argc, /* How many additional arguments? */ const char *const *argv) /* These are the additional args. */ { Tcl_Obj *childObjPtr, *targetObjPtr; Tcl_Obj **objv; - int i; + Tcl_Size i; int result; objv = (Tcl_Obj **)TclStackAlloc(childInterp, sizeof(Tcl_Obj *) * argc); for (i = 0; i < argc; i++) { objv[i] = Tcl_NewStringObj(argv[i], -1); @@ -1252,11 +1251,11 @@ Tcl_CreateAliasObj( Tcl_Interp *childInterp, /* Interpreter for source command. */ const char *childCmd, /* Command to install in child. */ Tcl_Interp *targetInterp, /* Interpreter for target command. */ const char *targetCmd, /* Name of target command. */ - int objc, /* How many additional arguments? */ + Tcl_Size objc, /* How many additional arguments? */ Tcl_Obj *const objv[]) /* Argument vector. */ { Tcl_Obj *childObjPtr, *targetObjPtr; int result; @@ -1308,11 +1307,11 @@ hPtr = Tcl_FindHashEntry(&iiPtr->child.aliasTable, aliasName); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "alias \"%s\" not found", aliasName)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, (void *)NULL); return TCL_ERROR; } aliasPtr = (Alias *)Tcl_GetHashValue(hPtr); objc = aliasPtr->objc; objv = &aliasPtr->objPtr; @@ -1370,11 +1369,11 @@ hPtr = Tcl_FindHashEntry(&iiPtr->child.aliasTable, aliasName); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "alias \"%s\" not found", aliasName)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, (void *)NULL); return TCL_ERROR; } aliasPtr = (Alias *)Tcl_GetHashValue(hPtr); objc = aliasPtr->objc; objv = &aliasPtr->objPtr; @@ -1477,11 +1476,11 @@ if (aliasCmdPtr == cmdPtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "cannot define or rename alias \"%s\": would create a loop", Tcl_GetCommandName(cmdInterp, cmd))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", - "ALIASLOOP", NULL); + "ALIASLOOP", (void *)NULL); return TCL_ERROR; } /* * Otherwise, follow the chain one step further. See if the target @@ -1698,11 +1697,11 @@ hPtr = Tcl_FindHashEntry(&childPtr->aliasTable, TclGetString(namePtr)); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "alias \"%s\" not found", TclGetString(namePtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", - TclGetString(namePtr), NULL); + TclGetString(namePtr), (void *)NULL); return TCL_ERROR; } aliasPtr = (Alias *)Tcl_GetHashValue(hPtr); Tcl_DeleteCommandFromToken(childInterp, aliasPtr->childCmd); return TCL_OK; @@ -1820,20 +1819,20 @@ *---------------------------------------------------------------------- */ static int AliasNRCmd( - ClientData clientData, /* Alias record. */ + void *clientData, /* Alias record. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument vector. */ { Alias *aliasPtr = (Alias *)clientData; int prefc, cmdc, i; Tcl_Obj **prefv, **cmdv; Tcl_Obj *listPtr; - List *listRep; + ListRep listRep; int flags = TCL_EVAL_INVOKE; /* * Append the arguments to the command prefix and invoke the command in * the target interp's global namespace. @@ -1841,18 +1840,23 @@ prefc = aliasPtr->objc; prefv = &aliasPtr->objPtr; cmdc = prefc + objc - 1; + /* TODO - encapsulate this into tclListObj.c */ listPtr = Tcl_NewListObj(cmdc, NULL); - listRep = ListRepPtr(listPtr); - listRep->elemCount = cmdc; - cmdv = &listRep->elements; + 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 *))); + memcpy(cmdv, prefv, prefc * sizeof(Tcl_Obj *)); + memcpy(cmdv+prefc, objv+1, (objc-1) * sizeof(Tcl_Obj *)); for (i=0; i= 1", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", - "BGERRORFORMAT", NULL); + "BGERRORFORMAT", (void *)NULL); return TCL_ERROR; } TclSetBgErrorHandler(childInterp, objv[0]); } Tcl_SetObjResult(interp, TclGetBgErrorHandler(childInterp)); @@ -2422,14 +2426,15 @@ Tcl_Interp *parentInterp, *childInterp; Child *childPtr; InterpInfo *parentInfoPtr; Tcl_HashEntry *hPtr; const char *path; - int isNew, objc; + int isNew; + Tcl_Size objc; Tcl_Obj **objv; - if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) { + if (TclListObjGetElementsM(interp, pathPtr, &objc, &objv) != TCL_OK) { return NULL; } if (objc < 2) { parentInterp = interp; path = TclGetString(pathPtr); @@ -2475,13 +2480,11 @@ ((Interp *) childInterp)->maxNestingDepth = ((Interp *) parentInterp)->maxNestingDepth; if (safe) { - if (Tcl_MakeSafe(childInterp) == TCL_ERROR) { - goto error; - } + MakeSafe(childInterp); } else { if (Tcl_Init(childInterp) == TCL_ERROR) { goto error; } @@ -2546,27 +2549,26 @@ *---------------------------------------------------------------------- */ int TclChildObjCmd( - ClientData clientData, /* Child interpreter. */ + void *clientData, /* Child interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, NRChildCmd, clientData, objc, objv); } static int NRChildCmd( - ClientData clientData, /* Child interpreter. */ + void *clientData, /* Child interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Interp *childInterp = (Tcl_Interp *)clientData; - int index; static const char *const options[] = { "alias", "aliases", "bgerror", "debug", "eval", "expose", "hide", "hidden", "issafe", "invokehidden", "limit", "marktrusted", "recursionlimit", NULL @@ -2574,11 +2576,11 @@ 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"); } @@ -2589,11 +2591,11 @@ if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum childCmdOptionsEnum) index) { + switch (index) { case OPT_ALIAS: if (objc > 2) { if (objc == 3) { return AliasDescribe(interp, childInterp, objv[2]); } @@ -2667,24 +2669,24 @@ static const char *const hiddenOptions[] = { "-global", "-namespace", "--", NULL }; enum hiddenOption { OPT_GLOBAL, OPT_NAMESPACE, OPT_LAST - }; + } idx; namespaceName = NULL; for (i = 2; i < objc; i++) { if (TclGetString(objv[i])[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option", - 0, &index) != TCL_OK) { + 0, &idx) != TCL_OK) { return TCL_ERROR; } - if (index == OPT_GLOBAL) { + if (idx == OPT_GLOBAL) { namespaceName = "::"; - } else if (index == OPT_NAMESPACE) { + } else if (idx == OPT_NAMESPACE) { if (++i == objc) { /* There must be more arguments. */ break; } else { namespaceName = TclGetString(objv[i]); } @@ -2705,22 +2707,21 @@ static const char *const limitTypes[] = { "commands", "time", NULL }; enum LimitTypes { LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME - }; - int limitType; + } limitType; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "limitType ?-option value ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], limitTypes, "limit type", 0, &limitType) != TCL_OK) { return TCL_ERROR; } - switch ((enum LimitTypes) limitType) { + switch (limitType) { case LIMIT_TYPE_COMMANDS: return ChildCommandLimitCmd(interp, childInterp, 3, objc,objv); case LIMIT_TYPE_TIME: return ChildTimeLimitCmd(interp, childInterp, 3, objc, objv); } @@ -2762,11 +2763,11 @@ *---------------------------------------------------------------------- */ static void ChildObjCmdDeleteProc( - ClientData clientData) /* The ChildRecord for the command. */ + void *clientData) /* The ChildRecord for the command. */ { Child *childPtr; /* Interim storage for Child record. */ Tcl_Interp *childInterp = (Tcl_Interp *)clientData; /* And for a child interp. */ @@ -2954,11 +2955,11 @@ 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); + (void *)NULL); return TCL_ERROR; } name = TclGetString(objv[(objc == 1) ? 0 : 1]); if (Tcl_ExposeCommand(childInterp, TclGetString(objv[0]), @@ -2992,36 +2993,36 @@ 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; + Tcl_WideInt limit; if (objc) { if (Tcl_IsSafe(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("permission denied: " "safe interpreters cannot change recursion limit", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE", - NULL); + (void *)NULL); return TCL_ERROR; } - if (TclGetIntFromObj(interp, objv[0], &limit) == TCL_ERROR) { + if (TclGetWideIntFromObj(interp, objv[0], &limit) == TCL_ERROR) { return TCL_ERROR; } if (limit <= 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "recursion limit must be > 0", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "BADLIMIT", - NULL); + (void *)NULL); return TCL_ERROR; } Tcl_SetRecursionLimit(childInterp, limit); iPtr = (Interp *) childInterp; if (interp == childInterp && iPtr->numLevels > limit) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "falling back due to new recursion limit", -1)); - Tcl_SetErrorCode(interp, "TCL", "RECURSION", NULL); + Tcl_SetErrorCode(interp, "TCL", "RECURSION", (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, objv[0]); return TCL_OK; } else { @@ -3060,11 +3061,11 @@ 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); + (void *)NULL); return TCL_ERROR; } name = TclGetString(objv[(objc == 1) ? 0 : 1]); if (Tcl_HideCommand(childInterp, TclGetString(objv[0]), name) != TCL_OK) { @@ -3145,11 +3146,11 @@ 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); + (void *)NULL); return TCL_ERROR; } Tcl_Preserve(childInterp); Tcl_AllowExceptions(childInterp); @@ -3179,11 +3180,11 @@ return result; } static int NRPostInvokeHidden( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Interp *childInterp = (Tcl_Interp *)data[0]; NRE_callback *rootPtr = (NRE_callback *)data[1]; @@ -3222,11 +3223,11 @@ 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); + (void *)NULL); return TCL_ERROR; } ((Interp *) childInterp)->flags &= ~SAFE_INTERP; return TCL_OK; } @@ -3260,11 +3261,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_MakeSafe -- + * MakeSafe -- * * Makes its argument interpreter contain only functionality that is * defined to be part of Safe Tcl. Unsafe commands are hidden, the env * array is unset, and the standard channels are removed. * @@ -3276,12 +3277,12 @@ * channels. * *---------------------------------------------------------------------- */ -int -Tcl_MakeSafe( +void +MakeSafe( Tcl_Interp *interp) /* Interpreter to be made safe. */ { Tcl_Channel chan; /* Channel to remove from safe interpreter. */ Interp *iPtr = (Interp *) interp; Tcl_Interp *parent = ((InterpInfo*) iPtr->interpInfo)->child.parentInterp; @@ -3295,11 +3296,11 @@ * defined by init.tcl which is not sourced by safe interpreters. * Assume these functions all work. [Bug 2895741] */ (void) Tcl_EvalEx(interp, - "namespace eval ::tcl {namespace eval mathfunc {}}", -1, 0); + "namespace eval ::tcl {namespace eval mathfunc {}}", TCL_INDEX_NONE, 0); } iPtr->flags |= SAFE_INTERP; /* @@ -3321,11 +3322,11 @@ Tcl_UnsetVar2(interp, "tcl_platform", "osVersion", TCL_GLOBAL_ONLY); Tcl_UnsetVar2(interp, "tcl_platform", "machine", TCL_GLOBAL_ONLY); Tcl_UnsetVar2(interp, "tcl_platform", "user", TCL_GLOBAL_ONLY); /* - * Unset path informations variables (the only one remaining is [info + * Unset path information variables (the only one remaining is [info * nameofexecutable]) */ Tcl_UnsetVar2(interp, "tclDefaultLibrary", NULL, TCL_GLOBAL_ONLY); Tcl_UnsetVar2(interp, "tcl_library", NULL, TCL_GLOBAL_ONLY); @@ -3351,12 +3352,10 @@ } chan = Tcl_GetStdChannel(TCL_STDERR); if (chan != NULL) { Tcl_UnregisterChannel(interp, chan); } - - return TCL_OK; } /* *---------------------------------------------------------------------- * @@ -3476,11 +3475,11 @@ if (iPtr->limit.cmdCount >= iPtr->cmdCount) { iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS; } else if (iPtr->limit.exceeded & TCL_LIMIT_COMMANDS) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command count limit exceeded", -1)); - Tcl_SetErrorCode(interp, "TCL", "LIMIT", "COMMANDS", NULL); + Tcl_SetErrorCode(interp, "TCL", "LIMIT", "COMMANDS", (void *)NULL); Tcl_Release(interp); return TCL_ERROR; } Tcl_Release(interp); } @@ -3502,11 +3501,11 @@ iPtr->limit.time.usec >= now.usec)) { iPtr->limit.exceeded &= ~TCL_LIMIT_TIME; } else if (iPtr->limit.exceeded & TCL_LIMIT_TIME) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "time limit exceeded", -1)); - Tcl_SetErrorCode(interp, "TCL", "LIMIT", "TIME", NULL); + Tcl_SetErrorCode(interp, "TCL", "LIMIT", "TIME", (void *)NULL); Tcl_Release(interp); return TCL_ERROR; } Tcl_Release(interp); } @@ -3604,22 +3603,22 @@ void Tcl_LimitAddHandler( Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, - ClientData clientData, + void *clientData, Tcl_LimitHandlerDeleteProc *deleteProc) { Interp *iPtr = (Interp *) interp; LimitHandler *handlerPtr; /* * Convert everything into a real deletion callback. */ - if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_DYNAMIC) { - deleteProc = (Tcl_LimitHandlerDeleteProc *) TclpFree; + if (deleteProc == TCL_DYNAMIC) { + deleteProc = TclpFree; } /* * Allocate a handler record. */ @@ -3678,11 +3677,11 @@ void Tcl_LimitRemoveHandler( Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, - ClientData clientData) + void *clientData) { Interp *iPtr = (Interp *) interp; LimitHandler *handlerPtr; switch (type) { @@ -3981,11 +3980,11 @@ */ void Tcl_LimitSetCommands( Tcl_Interp *interp, - int commandLimit) + Tcl_Size commandLimit) { Interp *iPtr = (Interp *) interp; iPtr->limit.cmdCount = commandLimit; iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS; @@ -4077,11 +4076,11 @@ *---------------------------------------------------------------------- */ static void TimeLimitCallback( - ClientData clientData) + void *clientData) { Tcl_Interp *interp = (Tcl_Interp *)clientData; Interp *iPtr = (Interp *)clientData; int code; @@ -4221,11 +4220,11 @@ *---------------------------------------------------------------------- */ static void DeleteScriptLimitCallback( - ClientData clientData) + void *clientData) { ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *)clientData; Tcl_DecrRefCount(limitCBPtr->scriptObj); if (limitCBPtr->entryPtr != NULL) { @@ -4252,11 +4251,11 @@ *---------------------------------------------------------------------- */ static void CallScriptLimitCallback( - ClientData clientData, + void *clientData, TCL_UNUSED(Tcl_Interp *)) { ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *)clientData; int code; @@ -4285,11 +4284,11 @@ * * Results: * None. * * Side effects: - * A limit callback implemented as an invokation of a Tcl script in + * A limit callback implemented as an invocation of a Tcl script in * another interpreter is either installed or removed. * *---------------------------------------------------------------------- */ @@ -4312,11 +4311,11 @@ key.interp = targetInterp; key.type = type; if (scriptObj == NULL) { - hashPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key); + hashPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key); if (hashPtr != NULL) { Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback, Tcl_GetHashValue(hashPtr)); } return; @@ -4489,13 +4488,12 @@ static const char *const options[] = { "-command", "-granularity", "-value", NULL }; enum Options { OPT_CMD, OPT_GRAN, OPT_VAL - }; + } index; Interp *iPtr = (Interp *) interp; - int index; ScriptLimitCallbackKey key; ScriptLimitCallback *limitCBPtr; Tcl_HashEntry *hPtr; /* @@ -4506,21 +4504,21 @@ */ if (interp == childInterp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "limits on current interpreter inaccessible", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF", NULL); + Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF", (void *)NULL); return TCL_ERROR; } if (objc == consumedObjc) { Tcl_Obj *dictPtr; TclNewObj(dictPtr); key.interp = childInterp; key.type = TCL_LIMIT_COMMANDS; - hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key); + hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key); if (hPtr != NULL) { limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr); if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) { Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1), limitCBPtr->scriptObj); @@ -4554,15 +4552,15 @@ } else if (objc == consumedObjc+1) { if (Tcl_GetIndexFromObj(interp, objv[consumedObjc], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum Options) index) { + switch (index) { case OPT_CMD: key.interp = childInterp; key.type = TCL_LIMIT_COMMANDS; - hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key); + hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key); if (hPtr != NULL) { limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr); if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) { Tcl_SetObjResult(interp, limitCBPtr->scriptObj); } @@ -4583,23 +4581,23 @@ } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) { Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?"); return TCL_ERROR; } else { int i; - size_t scriptLen = 0, limitLen = 0; + Tcl_Size scriptLen = 0, limitLen = 0; Tcl_Obj *scriptObj = NULL, *granObj = NULL, *limitObj = NULL; int gran = 0, limit = 0; for (i=consumedObjc ; ilimit.callbacks, (char *) &key); + 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); @@ -4749,15 +4746,15 @@ } else if (objc == consumedObjc+1) { if (Tcl_GetIndexFromObj(interp, objv[consumedObjc], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum Options) index) { + switch (index) { case OPT_CMD: key.interp = childInterp; key.type = TCL_LIMIT_TIME; - hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key); + hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key); if (hPtr != NULL) { limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr); if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) { Tcl_SetObjResult(interp, limitCBPtr->scriptObj); } @@ -4789,27 +4786,27 @@ } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) { Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?"); return TCL_ERROR; } else { int i; - size_t scriptLen = 0, milliLen = 0, secLen = 0; + Tcl_Size scriptLen = 0, milliLen = 0, secLen = 0; Tcl_Obj *scriptObj = NULL, *granObj = NULL; Tcl_Obj *milliObj = NULL, *secObj = NULL; int gran = 0; Tcl_Time limitMoment; - int tmp; + Tcl_WideInt tmp; Tcl_LimitGetTime(childInterp, &limitMoment); for (i=consumedObjc ; i 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may only set -milliseconds if -seconds is not " "also being reset", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", - "BADUSAGE", NULL); + "BADUSAGE", (void *)NULL); return TCL_ERROR; } if (milliLen == 0 && (secObj == NULL || secLen > 0)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may only reset -milliseconds if -seconds is " "also being reset", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", - "BADUSAGE", NULL); + "BADUSAGE", (void *)NULL); return TCL_ERROR; } } if (milliLen > 0 || secLen > 0) { Index: generic/tclLink.c ================================================================== --- generic/tclLink.c +++ generic/tclLink.c @@ -4,14 +4,14 @@ * This file implements linked variables (a C variable that is tied to a * Tcl variable). The idea of linked variables was first suggested by * Andreas Stolcke and this implementation is based heavily on a * prototype implementation provided by him. * - * Copyright (c) 1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2008 Rene Zaumseil - * Copyright (c) 2019 Donal K. Fellows + * Copyright © 1993 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2008 Rene Zaumseil + * Copyright © 2019 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -31,14 +31,14 @@ Tcl_Obj *varName; /* Name of variable (must be global). This is * needed during trace callbacks, since the * actual variable may be aliased at that time * via upvar. */ void *addr; /* Location of C variable. */ - size_t bytes; /* Size of C variable array. This is 0 when + Tcl_Size bytes; /* Size of C variable array. This is 0 when * single variables, and >0 used for array * variables. */ - size_t numElems; /* Number of elements in C variable array. + Tcl_Size numElems; /* Number of elements in C variable array. * Zero for single variables. */ int type; /* Type of link (TCL_LINK_INT, etc.). */ union { char c; unsigned char uc; @@ -93,11 +93,11 @@ /* * Forward references to functions defined later in this file: */ -static char * LinkTraceProc(ClientData clientData,Tcl_Interp *interp, +static char * LinkTraceProc(void *clientData,Tcl_Interp *interp, const char *name1, const char *name2, int flags); static Tcl_Obj * ObjValue(Link *linkPtr); static void LinkFree(Link *linkPtr); static int GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr); static int GetInvalidDoubleFromObj(Tcl_Obj *objPtr, @@ -112,11 +112,12 @@ static Tcl_ObjType invalidRealType = { "invalidReal", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ NULL, /* updateStringProc */ - NULL /* setFromAnyProc */ + 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 @@ -243,11 +244,11 @@ * varName. If NULL then the necessary space * will be allocated and returned as the * interpreter result. */ int type, /* Type of C variable: TCL_LINK_INT, etc. Also * may have TCL_LINK_READ_ONLY OR'ed in. */ - size_t size) /* Size of C variable array, >1 if array */ + Tcl_Size size) /* Size of C variable array, >1 if array */ { Tcl_Obj *objPtr; Link *linkPtr; Namespace *dummy; const char *name; @@ -524,60 +525,18 @@ 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; + 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( @@ -586,11 +545,11 @@ { if (Tcl_GetDoubleFromObj(NULL, objPtr, dblPtr) == TCL_OK) { return 0; } else { #ifdef ACCEPT_NAN - Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &tclDoubleType); + Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &tclDoubleType); if (irPtr != NULL) { *dblPtr = irPtr->doubleValue; return 0; } @@ -604,22 +563,22 @@ double a, double b) { return (a == b) #ifdef ACCEPT_NAN - || (TclIsNaN(a) && TclIsNaN(b)) + || (isnan(a) && isnan(b)) #endif /* ACCEPT_NAN */ ; } static inline int IsSpecial( double a) { - return TclIsInfinite(a) + return isinf(a) #ifdef ACCEPT_NAN - || TclIsNaN(a) + || isnan(a) #endif /* ACCEPT_NAN */ ; } /* @@ -629,24 +588,25 @@ static int SetInvalidRealFromAny( TCL_UNUSED(Tcl_Interp *), Tcl_Obj *objPtr) { - size_t length; - const char *str, *endPtr; + const char *str; + const char *endPtr; + Tcl_Size length; - str = TclGetStringFromObj(objPtr, &length); + str = Tcl_GetStringFromObj(objPtr, &length); if ((length == 1) && (str[0] == '.')) { objPtr->typePtr = &invalidRealType; objPtr->internalRep.doubleValue = 0.0; return TCL_OK; } if (TclParseNumber(NULL, objPtr, NULL, str, length, &endPtr, TCL_PARSE_DECIMAL_ONLY) == TCL_OK) { /* - * If number is followed by [eE][+-]?, then it is an invalid double, - * but it could be the start of a valid double. + * If number is followed by [eE][+-]?, then it is an invalid + * double, but it could be the start of a valid double. */ if (*endPtr == 'e' || *endPtr == 'E') { ++endPtr; if (*endPtr == '+' || *endPtr == '-') { @@ -654,11 +614,11 @@ } if (*endPtr == 0) { double doubleValue = 0.0; Tcl_GetDoubleFromObj(NULL, objPtr, &doubleValue); - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); objPtr->typePtr = &invalidRealType; objPtr->internalRep.doubleValue = doubleValue; return TCL_OK; } } @@ -665,26 +625,26 @@ } return TCL_ERROR; } /* - * This function checks for integer representations, which are valid when - * linking with C variables, but which are invalid in other contexts in Tcl. - * Handled are "+", "-", "", "0x", "0b", "0d" and "0o" (upper- and - * lower-case). See bug [39f6304c2e]. + * This function checks for integer representations, which are valid + * when linking with C variables, but which are invalid in other + * contexts in Tcl. Handled are "+", "-", "", "0x", "0b", "0d" and "0o" + * (upperand lowercase). See bug [39f6304c2e]. */ static int GetInvalidIntFromObj( Tcl_Obj *objPtr, int *intPtr) { - size_t length; - const char *str = TclGetStringFromObj(objPtr, &length); + Tcl_Size length; + const char *str = Tcl_GetStringFromObj(objPtr, &length); - if ((length == 0) || - ((length == 2) && (str[0] == '0') && strchr("xXbBoOdD", str[1]))) { + if ((length == 0) || ((length == 2) && (str[0] == '0') + && strchr("xXbBoOdD", str[1]))) { *intPtr = 0; return TCL_OK; } else if ((length == 1) && strchr("+-", str[0])) { *intPtr = (str[0] == '+'); return TCL_OK; @@ -691,24 +651,24 @@ } return TCL_ERROR; } /* - * This function checks for double representations, which are valid when - * linking with C variables, but which are invalid in other contexts in Tcl. - * Handled are "+", "-", "", ".", "0x", "0b" and "0o" (upper- and lower-case) - * and sequences like "1e-". See bug [39f6304c2e]. + * This function checks for double representations, which are valid + * when linking with C variables, but which are invalid in other + * contexts in Tcl. Handled are "+", "-", "", ".", "0x", "0b" and "0o" + * (upper- and lowercase) and sequences like "1e-". See bug [39f6304c2e]. */ static int GetInvalidDoubleFromObj( Tcl_Obj *objPtr, double *doublePtr) { int intValue; - if (TclHasIntRep(objPtr, &invalidRealType)) { + if (TclHasInternalRep(objPtr, &invalidRealType)) { goto gotdouble; } if (GetInvalidIntFromObj(objPtr, &intValue) == TCL_OK) { *doublePtr = (double) intValue; return TCL_OK; @@ -742,11 +702,11 @@ *---------------------------------------------------------------------- */ static char * LinkTraceProc( - ClientData clientData, /* Contains information about the link. */ + void *clientData, /* Contains information about the link. */ Tcl_Interp *interp, /* Interpreter containing Tcl variable. */ TCL_UNUSED(const char *) /*name1*/, TCL_UNUSED(const char *) /*name2*/, /* Links can only be made to global variables, * so we can find them with need to resolve @@ -753,21 +713,20 @@ * caller-supplied name in caller context. */ int flags) /* Miscellaneous additional information. */ { Link *linkPtr = (Link *)clientData; int changed; - size_t valueLength = 0; + Tcl_Size valueLength = 0; const char *value; char **pp; Tcl_Obj *valueObj; int valueInt; Tcl_WideInt valueWide; Tcl_WideUInt valueUWide; double valueDouble; - int objc; + Tcl_Size objc, i; Tcl_Obj **objv; - int i; /* * If the variable is being unset, then just re-create it (with a trace) * unless the whole interpreter is going away. */ @@ -869,11 +828,11 @@ } /* * For writes, first make sure that the variable is writable. Then convert * the Tcl value to C if possible. If the variable isn't writable or can't - * be converted, then restore the varaible's old value and return an + * be converted, then restore the variable's old value and return an * error. Another tricky thing: we have to save and restore the interp's * result, since the variable access could occur when the result has been * partially set. */ @@ -895,19 +854,19 @@ * Special cases. */ switch (linkPtr->type) { case TCL_LINK_STRING: - value = TclGetStringFromObj(valueObj, &valueLength); + value = Tcl_GetStringFromObj(valueObj, &valueLength); pp = (char **) linkPtr->addr; *pp = (char *)Tcl_Realloc(*pp, ++valueLength); memcpy(*pp, value, valueLength); return NULL; case TCL_LINK_CHARS: - value = (char *) TclGetStringFromObj(valueObj, &valueLength); + value = (char *) Tcl_GetStringFromObj(valueObj, &valueLength); valueLength++; /* include end of string char */ if (valueLength > linkPtr->bytes) { return (char *) "wrong size of char* value"; } if (linkPtr->flags & LINK_ALLOC_LAST) { @@ -918,12 +877,14 @@ LinkedVar(char) = linkPtr->lastValue.c; } return NULL; case TCL_LINK_BINARY: - value = (char *) TclGetByteArrayFromObj(valueObj, &valueLength); - if (valueLength != linkPtr->bytes) { + value = (char *) Tcl_GetByteArrayFromObj(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); @@ -945,20 +906,20 @@ /* * If we're working with an array of numbers, extract the Tcl list. */ if (linkPtr->flags & LINK_ALLOC_LAST) { - if (Tcl_ListObjGetElements(NULL, (valueObj), &objc, &objv) == TCL_ERROR - || (size_t)objc != linkPtr->numElems) { + if (TclListObjGetElementsM(NULL, (valueObj), &objc, &objv) == TCL_ERROR + || objc != linkPtr->numElems) { return (char *) "wrong dimension"; } } switch (linkPtr->type) { case TCL_LINK_INT: if (linkPtr->flags & LINK_ALLOC_LAST) { - for (i=0; i < objc; i++) { + for (i = 0; i < objc; i++) { int *varPtr = &linkPtr->lastValue.iPtr[i]; if (GetInt(objv[i], varPtr)) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); @@ -1069,21 +1030,21 @@ case TCL_LINK_UCHAR: if (linkPtr->flags & LINK_ALLOC_LAST) { for (i=0; i < objc; i++) { if (GetInt(objv[i], &valueInt) - || !InRange(0, valueInt, UCHAR_MAX)) { + || !InRange(0, valueInt, (int)UCHAR_MAX)) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable array must have unsigned char value"; } linkPtr->lastValue.ucPtr[i] = (unsigned char) valueInt; } } else { if (GetInt(valueObj, &valueInt) - || !InRange(0, valueInt, UCHAR_MAX)) { + || !InRange(0, valueInt, (int)UCHAR_MAX)) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have unsigned char value"; } LinkedVar(unsigned char) = linkPtr->lastValue.uc = @@ -1115,21 +1076,21 @@ case TCL_LINK_USHORT: if (linkPtr->flags & LINK_ALLOC_LAST) { for (i=0; i < objc; i++) { if (GetInt(objv[i], &valueInt) - || !InRange(0, valueInt, USHRT_MAX)) { + || !InRange(0, valueInt, (int)USHRT_MAX)) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable array must have unsigned short value"; } linkPtr->lastValue.usPtr[i] = (unsigned short) valueInt; } } else { if (GetInt(valueObj, &valueInt) - || !InRange(0, valueInt, USHRT_MAX)) { + || !InRange(0, valueInt, (int)USHRT_MAX)) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have unsigned short value"; } LinkedVar(unsigned short) = linkPtr->lastValue.us = @@ -1139,21 +1100,21 @@ case TCL_LINK_UINT: if (linkPtr->flags & LINK_ALLOC_LAST) { for (i=0; i < objc; i++) { if (GetWide(objv[i], &valueWide) - || !InRange(0, valueWide, UINT_MAX)) { + || !InRange(0, valueWide, (Tcl_WideInt)UINT_MAX)) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable array must have unsigned int value"; } linkPtr->lastValue.uiPtr[i] = (unsigned int) valueWide; } } else { if (GetWide(valueObj, &valueWide) - || !InRange(0, valueWide, UINT_MAX)) { + || !InRange(0, valueWide, (Tcl_WideInt)UINT_MAX)) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have unsigned int value"; } LinkedVar(unsigned int) = linkPtr->lastValue.ui = @@ -1286,11 +1247,11 @@ ObjValue( Link *linkPtr) /* Structure describing linked variable. */ { char *p; Tcl_Obj *resultObj, **objv; - size_t i; + Tcl_Size i; switch (linkPtr->type) { case TCL_LINK_INT: if (linkPtr->flags & LINK_ALLOC_LAST) { memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes); @@ -1320,11 +1281,11 @@ case TCL_LINK_DOUBLE: if (linkPtr->flags & LINK_ALLOC_LAST) { memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes); objv = (Tcl_Obj **)Tcl_Alloc(linkPtr->numElems * sizeof(Tcl_Obj *)); for (i=0; i < linkPtr->numElems; i++) { - objv[i] = Tcl_NewDoubleObj(linkPtr->lastValue.dPtr[i]); + TclNewDoubleObj(objv[i], linkPtr->lastValue.dPtr[i]); } resultObj = Tcl_NewListObj(linkPtr->numElems, objv); Tcl_Free(objv); return resultObj; } @@ -1439,32 +1400,34 @@ case TCL_LINK_FLOAT: if (linkPtr->flags & LINK_ALLOC_LAST) { memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes); objv = (Tcl_Obj **)Tcl_Alloc(linkPtr->numElems * sizeof(Tcl_Obj *)); for (i=0; i < linkPtr->numElems; i++) { - objv[i] = Tcl_NewDoubleObj(linkPtr->lastValue.fPtr[i]); + TclNewDoubleObj(objv[i], linkPtr->lastValue.fPtr[i]); } resultObj = Tcl_NewListObj(linkPtr->numElems, objv); Tcl_Free(objv); return resultObj; } linkPtr->lastValue.f = LinkedVar(float); return Tcl_NewDoubleObj(linkPtr->lastValue.f); - case TCL_LINK_WIDE_UINT: + case TCL_LINK_WIDE_UINT: { if (linkPtr->flags & LINK_ALLOC_LAST) { memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes); objv = (Tcl_Obj **)Tcl_Alloc(linkPtr->numElems * sizeof(Tcl_Obj *)); for (i=0; i < linkPtr->numElems; i++) { - TclNewIntObj(objv[i], (Tcl_WideInt) - linkPtr->lastValue.uwPtr[i]); + TclNewUIntObj(objv[i], linkPtr->lastValue.uwPtr[i]); } resultObj = Tcl_NewListObj(linkPtr->numElems, objv); Tcl_Free(objv); return resultObj; } linkPtr->lastValue.uw = LinkedVar(Tcl_WideUInt); - return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.uw); + Tcl_Obj *uwObj; + TclNewUIntObj(uwObj, linkPtr->lastValue.uw); + return uwObj; + } case TCL_LINK_STRING: p = LinkedVar(char *); if (p == NULL) { TclNewLiteralStringObj(resultObj, "NULL"); Index: generic/tclListObj.c ================================================================== --- generic/tclListObj.c +++ generic/tclListObj.c @@ -1,423 +1,1573 @@ /* * tclListObj.c -- * * This file contains functions that implement the Tcl list object type. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright (c) 1998 by Scriptics Corporation. - * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. + * Copyright © 2022 Ashok P. Nadkarni. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tclInt.h" #include +#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 functions defined later in this file: + * Prototypes for non-inline static functions defined later in this file: */ - -static List * AttemptNewList(Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); -static List * NewListIntRep(int objc, Tcl_Obj *const objv[], int p); -static void DupListInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); -static void FreeListInternalRep(Tcl_Obj *listPtr); -static int SetListFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); -static void UpdateStringOfList(Tcl_Obj *listPtr); +static int MemoryAllocationError(Tcl_Interp *, size_t size); +static int ListLimitExceededError(Tcl_Interp *); +static ListStore *ListStoreNew(Tcl_Size objc, Tcl_Obj *const objv[], int flags); +static int ListRepInit(Tcl_Size objc, Tcl_Obj *const objv[], int flags, ListRep *); +static int ListRepInitAttempt(Tcl_Interp *, + Tcl_Size objc, + Tcl_Obj *const objv[], + ListRep *); +static void ListRepClone(ListRep *fromRepPtr, ListRep *toRepPtr, int flags); +static void ListRepUnsharedFreeUnreferenced(const ListRep *repPtr); +static int TclListObjGetRep(Tcl_Interp *, Tcl_Obj *listPtr, ListRep *repPtr); +static void ListRepRange(ListRep *srcRepPtr, + Tcl_Size rangeStart, + Tcl_Size rangeEnd, + int preserveSrcRep, + ListRep *rangeRepPtr); +static ListStore *ListStoreReallocate(ListStore *storePtr, Tcl_Size numSlots); +static void ListRepValidate(const ListRep *repPtr, const char *file, + int lineNum); +static void DupListInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); +static void FreeListInternalRep(Tcl_Obj *listPtr); +static int SetListFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); +static void UpdateStringOfList(Tcl_Obj *listPtr); +static Tcl_Size ListLength(Tcl_Obj *listPtr); /* * The structure below defines the list Tcl object type by means of functions * that can be invoked by generic object code. * - * The internal representation of a list object is a two-pointer - * 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. + * 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 */ + SetListFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V1(ListLength) }; /* 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 *) +#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__); +} /* *---------------------------------------------------------------------- * - * 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. + * 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 List * -NewListIntRep( - int objc, +static ListStore * +ListStoreNew( + Tcl_Size objc, Tcl_Obj *const objv[], - int p) + int flags) { - List *listRepPtr; - - if (objc <= 0) { - Tcl_Panic("NewListIntRep: expects postive element count"); - } + 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. 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. + * larger than our memory allocator allows. */ - - if ((size_t)objc > LIST_MAX) { - if (p) { - Tcl_Panic("max length of a Tcl list (%d elements) exceeded", - LIST_MAX); + if (objc > LIST_MAX) { + if (flags & LISTREP_PANIC_ON_FAIL) { + Tcl_Panic("max length of a Tcl list exceeded"); } 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", + 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; } - listRepPtr->canonicalFlag = 0; - listRepPtr->refCount = 0; - listRepPtr->maxElemCount = objc; + storePtr->refCount = 0; + storePtr->flags = 0; + storePtr->numAllocated = capacity; + if (capacity == objc) { + storePtr->firstUsed = 0; + } else { + Tcl_Size extra = capacity - objc; + int spaceFlags = flags & LISTREP_SPACE_FLAGS; + if (spaceFlags == LISTREP_SPACE_ONLY_BACK) { + storePtr->firstUsed = 0; + } else if (spaceFlags == LISTREP_SPACE_FAVOR_FRONT) { + /* Leave more space in the front */ + storePtr->firstUsed = + extra - (extra / 4); /* NOT same as 3*extra/4 */ + } else if (spaceFlags == LISTREP_SPACE_FAVOR_BACK) { + /* Leave more space in the back */ + storePtr->firstUsed = extra / 4; + } else { + /* Apportion equally */ + storePtr->firstUsed = extra / 2; + } + } if (objv) { - Tcl_Obj **elemPtrs; - int i; - - listRepPtr->elemCount = objc; - elemPtrs = &listRepPtr->elements; - for (i = 0; i < objc; i++) { - elemPtrs[i] = objv[i]; - Tcl_IncrRefCount(elemPtrs[i]); - } + storePtr->numUsed = objc; + ObjArrayCopy(&storePtr->slots[storePtr->firstUsed], objc, objv); } else { - listRepPtr->elemCount = 0; + storePtr->numUsed = 0; } - return listRepPtr; + + 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. + * + * + *------------------------------------------------------------------------ + */ +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; } /* *---------------------------------------------------------------------- * - * AttemptNewList -- + * ListRepInitAttempt -- * - * Like NewListIntRep, but additionally sets an error message on failure. + * Creates a list internal rep with space for objc elements. See + * ListRepInit for requirements for parameters (in particular objc must + * be > 0). This function only adds error messages to the interpreter if + * not NULL. + * + * The reference counts of the ListStore and ListSpan (if present) + * pointed to by the initialized repPtr are set to zero. + * Caller has to manage them as necessary. + * + * Results: + * On success, TCL_OK is returned with *listRepPtr initialized. + * On allocation failure, returnes TCL_ERROR with an error message + * in the interpreter if non-NULL. + * + * Side effects: + * The ref counts of the elements in objv are incremented since the + * resulting list now refers to them. * *---------------------------------------------------------------------- */ - -static List * -AttemptNewList( +static int +ListRepInitAttempt( Tcl_Interp *interp, - int objc, - Tcl_Obj *const objv[]) + Tcl_Size objc, + Tcl_Obj *const objv[], + ListRep *repPtr) { - List *listRepPtr = NewListIntRep(objc, objv, 0); + int result = ListRepInit(objc, objv, 0, repPtr); - if (interp != NULL && listRepPtr == NULL) { + if (result != TCL_OK && interp != NULL) { if (objc > LIST_MAX) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "max length of a Tcl list (%d elements) exceeded", - LIST_MAX)); + ListLimitExceededError(interp); } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "list creation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes", - LIST_SIZE(objc))); + MemoryAllocationError(interp, LIST_SIZE(objc)); } - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } - return listRepPtr; + 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 -- * - * 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. + * 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( - int objc, /* Count of objects referenced by objv. */ + Tcl_Size objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[]) /* An array of pointers to Tcl objects. */ { return Tcl_DbNewListObj(objc, objv, "unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewListObj( - int objc, /* Count of objects referenced by objv. */ + Tcl_Size objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[]) /* An array of pointers to Tcl objects. */ { - List *listRepPtr; - Tcl_Obj *listPtr; + ListRep listRep; + Tcl_Obj *listObj; - TclNewObj(listPtr); + TclNewObj(listObj); if (objc <= 0) { - return listPtr; - } - - /* - * Create the internal rep. - */ - - listRepPtr = NewListIntRep(objc, objv, 1); - - /* - * Now create the object. - */ - - TclInvalidateStringRep(listPtr); - ListSetIntRep(listPtr, listRepPtr); - return listPtr; + return listObj; + } + + ListRepInit(objc, objv, LISTREP_PANIC_ON_FAIL, &listRep); + ListObjReplaceRepAndInvalidate(listObj, &listRep); + + return listObj; } #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. + * 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( - int objc, /* Count of objects referenced by objv. */ + Tcl_Size objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[], /* An array of pointers to Tcl objects. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { - Tcl_Obj *listPtr; - List *listRepPtr; + Tcl_Obj *listObj; + ListRep listRep; - TclDbNewObj(listPtr, file, line); + TclDbNewObj(listObj, file, line); if (objc <= 0) { - return listPtr; - } - - /* - * Create the internal rep. - */ - - listRepPtr = NewListIntRep(objc, objv, 1); - - /* - * Now create the object. - */ - - TclInvalidateStringRep(listPtr); - ListSetIntRep(listPtr, listRepPtr); - - return listPtr; + 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( - int objc, /* Count of objects referenced by objv. */ + Tcl_Size objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[], /* An array of pointers to Tcl objects. */ TCL_UNUSED(const char *) /*file*/, TCL_UNUSED(int) /*line*/) { return Tcl_NewListObj(objc, objv); } #endif /* TCL_MEM_DEBUG */ + +/* + *------------------------------------------------------------------------ + * + * TclNewListObj2 -- + * + * Create a new Tcl_Obj list comprising of the concatenation of two + * Tcl_Obj* arrays. + * TODO - currently this function is not used within tclListObj but + * need to see if it would be useful in other files that preallocate + * lists and then append. + * + * Results: + * Non-NULL pointer to the allocate Tcl_Obj. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ +Tcl_Obj * +TclNewListObj2( + Tcl_Size objc1, /* Count of objects referenced by objv1. */ + Tcl_Obj *const objv1[], /* First array of pointers to Tcl objects. */ + Tcl_Size objc2, /* Count of objects referenced by objv2. */ + Tcl_Obj *const objv2[] /* Second array of pointers to Tcl objects. */ +) +{ + Tcl_Obj *listObj; + ListStore *storePtr; + Tcl_Size objc = objc1 + objc2; + + listObj = Tcl_NewListObj(objc, NULL); + if (objc == 0) { + return listObj; /* An empty object */ + } + LIST_ASSERT_TYPE(listObj); + + storePtr = ListObjStorePtr(listObj); + + LIST_ASSERT(ListObjSpanPtr(listObj) == NULL); + LIST_ASSERT(storePtr->firstUsed == 0); + LIST_ASSERT(storePtr->numUsed == 0); + LIST_ASSERT(storePtr->numAllocated >= objc); + + if (objc1) { + ObjArrayCopy(storePtr->slots, objc1, objv1); + } + if (objc2) { + ObjArrayCopy(&storePtr->slots[objc1], objc2, objv2); + } + storePtr->numUsed = objc; + return listObj; +} + +/* + *---------------------------------------------------------------------- + * + * TclListObjGetRep -- + * + * This function returns a copy of the ListRep stored + * as the internal representation of an object. The reference + * counts of the (ListStore, ListSpan) contained in the representation + * are NOT incremented. + * + * Results: + * The return value is normally TCL_OK; in this case *listRepP + * is set to a copy of the descriptor stored as the internal + * representation of the Tcl_Obj containing a list. if listPtr does not + * refer to a list object and the object can not be converted to one, + * TCL_ERROR is returned and an error message will be left in the + * interpreter's result if interp is not NULL. + * + * Side effects: + * The possible conversion of the object referenced by listPtr + * to a list object. *repPtr is initialized to the internal rep + * if result is TCL_OK, or set to NULL on error. + *---------------------------------------------------------------------- + */ + +static int +TclListObjGetRep( + Tcl_Interp *interp, /* Used to report errors if not NULL. */ + Tcl_Obj *listObj, /* List object for which an element array is + * to be returned. */ + ListRep *repPtr) /* Location to store descriptor */ +{ + if (!TclHasInternalRep(listObj, &tclListType)) { + int result; + result = SetListFromAny(interp, listObj); + if (result != TCL_OK) { + /* Init to keep gcc happy wrt uninitialized fields at call site */ + repPtr->storePtr = NULL; + repPtr->spanPtr = NULL; + return result; + } + } + ListObjGetRep(listObj, repPtr); + LISTREP_CHECK(repPtr); + return TCL_OK; +} /* *---------------------------------------------------------------------- * * Tcl_SetListObj -- * - * Like 'Tcl_NewListObj', but operates on an existing 'Tcl_Obj'instead of - * creating a new one. + * Modify an object to be a list containing each of the objc elements of + * the object array referenced by objv. + * + * Results: + * None. + * + * Side effects: + * The object is made a list object and is initialized from the object + * pointers in objv. If objc is less than or equal to zero, an empty + * object is returned. The new object's string representation is left + * NULL. The ref counts of the elements in objv are incremented since the + * list now refers to them. The object's old string and internal + * representations are freed and its type is set NULL. * *---------------------------------------------------------------------- */ - void Tcl_SetListObj( Tcl_Obj *objPtr, /* Object whose internal rep to init. */ - int objc, /* Count of objects referenced by objv. */ + Tcl_Size objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[]) /* An array of pointers to Tcl objects. */ { - List *listRepPtr; - if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetListObj"); } - /* - * Free any old string rep and any internal rep for the old type. - */ - - TclFreeIntRep(objPtr); - TclInvalidateStringRep(objPtr); - /* * Set the object's type to "list" and initialize the internal rep. * However, if there are no elements to put in the list, just give the - * object an empty string rep and a NULL type. + * object an empty string rep and a NULL type. NOTE ListRepInit must + * not be called with objc == 0! */ if (objc > 0) { - listRepPtr = NewListIntRep(objc, objv, 1); - ListSetIntRep(objPtr, listRepPtr); + 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 -- * - * 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. + * 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 *listPtr) /* List object for which an element array is + Tcl_Obj *listObj) /* List object for which an element array is * to be returned. */ { - Tcl_Obj *copyPtr; - List *listRepPtr; + Tcl_Obj *copyObj; - ListGetIntRep(listPtr, listRepPtr); - if (NULL == listRepPtr) { - if (SetListFromAny(interp, listPtr) != TCL_OK) { + if (!TclHasInternalRep(listObj, &tclListType)) { + if (TclObjTypeHasProc(listObj, lengthProc)) { + return Tcl_DuplicateObj(listObj); + } + if (SetListFromAny(interp, listObj) != TCL_OK) { return NULL; } } - TclNewObj(copyPtr); - TclInvalidateStringRep(copyPtr); - DupListInternalRep(listPtr, copyPtr); - return copyPtr; + TclNewObj(copyObj); + TclInvalidateStringRep(copyObj); + DupListInternalRep(listObj, copyObj); + return copyObj; +} + +/* + *------------------------------------------------------------------------ + * + * ListRepRange -- + * + * Initializes a ListRep as a range within the passed ListRep. + * The range limits are clamped to the list boundaries. + * + * Results: + * None. + * + * Side effects: + * The ListStore and ListSpan referenced by in the returned ListRep + * may or may not be the same as those passed in. For example, the + * ListStore may differ because the range is small enough that a new + * ListStore is more memory-optimal. The ListSpan may differ because + * it is NULL or shared. Regardless, reference counts on the returned + * values are not incremented. Generally, ListObjReplaceRepAndInvalidate + * may be used to store the new ListRep back into an object or a + * ListRepIncrRefs followed by ListRepDecrRefs to free in case of errors. + * Any other use should be carefully reconsidered. + * TODO WARNING:- this is an awkward interface and easy for caller + * to get wrong. Mostly due to refcount combinations. Perhaps passing + * in the source listObj instead of source listRep might simplify. + * + *------------------------------------------------------------------------ + */ +static void +ListRepRange( + ListRep *srcRepPtr, /* Contains source of the range */ + Tcl_Size rangeStart, /* Index of first element to include */ + Tcl_Size rangeEnd, /* Index of last element to include */ + int preserveSrcRep, /* If true, srcRepPtr contents must not be + modified (generally because a shared Tcl_Obj + references it) */ + ListRep *rangeRepPtr) /* Output. Must NOT be == srcRepPtr */ +{ + Tcl_Obj **srcElems; + Tcl_Size numSrcElems = ListRepLength(srcRepPtr); + Tcl_Size rangeLen; + Tcl_Size numAfterRangeEnd; + + LISTREP_CHECK(srcRepPtr); + + /* Take the opportunity to garbage collect */ + /* TODO - we probably do not need the preserveSrcRep here unlike later */ + if (!preserveSrcRep) { + /* T:listrep-1.{4,5,8,9},2.{4:7},3.{15:18},4.{7,8} */ + ListRepFreeUnreferenced(srcRepPtr); + } /* else T:listrep-2.{4.2,4.3,5.2,5.3,6.2,7.2,8.1} */ + + if (rangeStart < 0) { + rangeStart = 0; + } + if (rangeEnd >= numSrcElems) { + rangeEnd = numSrcElems - 1; + } + if (rangeStart > rangeEnd) { + /* Empty list of capacity 1. */ + ListRepInit(1, NULL, LISTREP_PANIC_ON_FAIL, rangeRepPtr); + return; + } + + rangeLen = rangeEnd - rangeStart + 1; + + /* + * We can create a range one of four ways: + * (0) Range encapsulates entire list + * (1) Special case: deleting in-place from end of an unshared object + * (2) Use a ListSpan referencing the current ListStore + * (3) Creating a new ListStore + * (4) Removing all elements outside the range in the current ListStore + * Option (4) may only be done if caller has not disallowed it AND + * the ListStore is not shared. + * + * The choice depends on heuristics related to speed and memory. + * TODO - heuristics below need to be measured and tuned. + * + * Note: Even if nothing below cause any changes, we still want the + * string-canonizing effect of [lrange 0 end] so the Tcl_Obj should not + * be returned as is even if the range encompasses the whole list. + */ + if (rangeStart == 0 && rangeEnd == (numSrcElems-1)) { + /* Option 0 - entire list. This may be used to canonicalize */ + /* T:listrep-1.10.1,2.8.1 */ + *rangeRepPtr = *srcRepPtr; /* Not ref counts not incremented */ + } else if (rangeStart == 0 && (!preserveSrcRep) + && (!ListRepIsShared(srcRepPtr) && srcRepPtr->spanPtr == NULL)) { + /* Option 1 - Special case unshared, exclude end elements, no span */ + LIST_ASSERT(srcRepPtr->storePtr->firstUsed == 0); /* If no span */ + ListRepElements(srcRepPtr, numSrcElems, srcElems); + numAfterRangeEnd = numSrcElems - (rangeEnd + 1); + /* Assert: Because numSrcElems > rangeEnd earlier */ + if (numAfterRangeEnd != 0) { + /* T:listrep-1.{8,9} */ + ObjArrayDecrRefs(srcElems, rangeEnd + 1, numAfterRangeEnd); + } + /* srcRepPtr->storePtr->firstUsed,numAllocated unchanged */ + srcRepPtr->storePtr->numUsed = rangeLen; + srcRepPtr->storePtr->flags = 0; + rangeRepPtr->storePtr = srcRepPtr->storePtr; /* Note no incr ref */ + rangeRepPtr->spanPtr = NULL; + } else if (ListSpanMerited(rangeLen, + srcRepPtr->storePtr->numUsed, + srcRepPtr->storePtr->numAllocated)) { + /* Option 2 - because span would be most efficient */ + Tcl_Size spanStart = ListRepStart(srcRepPtr) + rangeStart; + if (!preserveSrcRep && srcRepPtr->spanPtr + && srcRepPtr->spanPtr->refCount <= 1) { + /* If span is not shared reuse it */ + /* T:listrep-2.7.3,3.{16,18} */ + srcRepPtr->spanPtr->spanStart = spanStart; + srcRepPtr->spanPtr->spanLength = rangeLen; + *rangeRepPtr = *srcRepPtr; + } else { + /* Span not present or is shared. */ + /* T:listrep-1.5,2.{5,7},4.{7,8} */ + rangeRepPtr->storePtr = srcRepPtr->storePtr; + rangeRepPtr->spanPtr = ListSpanNew(spanStart, rangeLen); + } + /* + * We have potentially created a new internal representation that + * references the same storage as srcRep but not yet incremented its + * reference count. So do NOT call freezombies if preserveSrcRep + * is mandated. + */ + if (!preserveSrcRep) { + /* T:listrep-1.{5.1,5.2,5.4},2.{5,7},3.{16,18},4.{7,8} */ + ListRepFreeUnreferenced(rangeRepPtr); + } + } else if (preserveSrcRep || ListRepIsShared(srcRepPtr)) { + /* Option 3 - span or modification in place not allowed/desired */ + /* T:listrep-2.{4,6} */ + ListRepElements(srcRepPtr, numSrcElems, srcElems); + /* TODO - allocate extra space? */ + ListRepInit(rangeLen, + &srcElems[rangeStart], + LISTREP_PANIC_ON_FAIL, + rangeRepPtr); + } else { + /* + * Option 4 - modify in place. Note that because of the invariant + * that spanless list stores must start at 0, we have to move + * everything to the front. + * TODO - perhaps if a span already exists, no need to move to front? + * or maybe no need to move all the way to the front? + * TODO - if range is small relative to allocation, allocate new? + */ + + /* Asserts follow from call to ListRepFreeUnreferenced earlier */ + LIST_ASSERT(!preserveSrcRep); + LIST_ASSERT(!ListRepIsShared(srcRepPtr)); + LIST_ASSERT(ListRepStart(srcRepPtr) == srcRepPtr->storePtr->firstUsed); + LIST_ASSERT(ListRepLength(srcRepPtr) == srcRepPtr->storePtr->numUsed); + + ListRepElements(srcRepPtr, numSrcElems, srcElems); + + /* Free leading elements outside range */ + if (rangeStart != 0) { + /* T:listrep-1.4,3.15 */ + ObjArrayDecrRefs(srcElems, 0, rangeStart); + } + /* Ditto for trailing */ + numAfterRangeEnd = numSrcElems - (rangeEnd + 1); + /* Assert: Because numSrcElems > rangeEnd earlier */ + if (numAfterRangeEnd != 0) { + /* T:listrep-3.17 */ + ObjArrayDecrRefs(srcElems, rangeEnd + 1, numAfterRangeEnd); + } + memmove(&srcRepPtr->storePtr->slots[0], + &srcRepPtr->storePtr + ->slots[srcRepPtr->storePtr->firstUsed + rangeStart], + rangeLen * sizeof(Tcl_Obj *)); + srcRepPtr->storePtr->firstUsed = 0; + srcRepPtr->storePtr->numUsed = rangeLen; + srcRepPtr->storePtr->flags = 0; + if (srcRepPtr->spanPtr) { + /* In case the source has a span, update it for consistency */ + /* T:listrep-3.{15,17} */ + srcRepPtr->spanPtr->spanStart = srcRepPtr->storePtr->firstUsed; + srcRepPtr->spanPtr->spanLength = srcRepPtr->storePtr->numUsed; + } + rangeRepPtr->storePtr = srcRepPtr->storePtr; + rangeRepPtr->spanPtr = NULL; + } + + /* TODO - call freezombies here if !preserveSrcRep? */ + + /* Note ref counts intentionally not incremented */ + LISTREP_CHECK(rangeRepPtr); + return; } /* *---------------------------------------------------------------------- * * TclListObjRange -- * * Makes a slice of a list value. - * *listPtr must be known to be a valid list. + * *listObj must be known to be a valid list. * * Results: * Returns a pointer to the sliced list. * This may be a new object or the same object if not shared. + * Returns NULL if passed listObj was not a list and could not be + * converted to one. * * Side effects: * The possible conversion of the object referenced by listPtr * to a list object. * @@ -424,198 +1574,303 @@ *---------------------------------------------------------------------- */ 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_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 -- * - * 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. + * 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 *listPtr, /* List object for which an element array is + Tcl_Obj *objPtr, /* List object for which an element array is * to be returned. */ - int *objcPtr, /* Where to store the count of objects + Tcl_Size *objcPtr, /* Where to store the count of objects * referenced by objv. */ Tcl_Obj ***objvPtr) /* Where to store the pointer to an array of * pointers to the list's objects. */ { - List *listRepPtr; - - 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; + 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 -- * - * 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. + * 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 *listPtr, /* List object to append elements to. */ - Tcl_Obj *elemListPtr) /* List obj with elements to append. */ + Tcl_Obj *toObj, /* List object to append elements to. */ + Tcl_Obj *fromObj) /* List obj with elements to append. */ { - int objc; + Tcl_Size objc; Tcl_Obj **objv; - if (Tcl_IsShared(listPtr)) { + if (Tcl_IsShared(toObj)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList"); } - /* - * Pull the elements to append from elemListPtr. - */ - - if (TCL_OK != TclListObjGetElements(interp, elemListPtr, &objc, &objv)) { + if (TclListObjGetElementsM(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 Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, objc, objv); + 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) + return TCL_ERROR; /* Cannot be converted to a list */ + + if (elemCount <= 0) + return TCL_OK; /* Nothing to do. Note AFTER check for list above */ + + 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; + 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; } /* *---------------------------------------------------------------------- * @@ -637,164 +1892,27 @@ * * Effect * * If 'listPtr' is not already of type 'tclListType', it is converted. * The 'refCount' of 'objPtr' is incremented as it is added to 'listPtr'. - * Appending the new element may cause the the array of element pointers + * Appending the new element may cause the array of element pointers * in 'listObj' to grow. Any preexisting string representation of * 'listPtr' is invalidated. * *---------------------------------------------------------------------- */ - int Tcl_ListObjAppendElement( Tcl_Interp *interp, /* Used to report errors if not NULL. */ - Tcl_Obj *listPtr, /* List object to append objPtr to. */ - Tcl_Obj *objPtr) /* Object to append to listPtr's list. */ -{ - 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_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); } /* *---------------------------------------------------------------------- * @@ -813,50 +1931,48 @@ * 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 + * '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 *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)) { + 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 (TclListObjGetElementsM(interp, listObj, &numElems, &elemObjs) + != TCL_OK) { + return TCL_ERROR; + } + if ((index < 0) || (index >= numElems)) { *objPtrPtr = NULL; } else { - *objPtrPtr = (&listRepPtr->elements)[index]; + *objPtrPtr = elemObjs[index]; } return TCL_OK; } @@ -863,397 +1979,615 @@ /* *---------------------------------------------------------------------- * * 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. + * 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 *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_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; +} + +Tcl_Size +ListLength(Tcl_Obj *listPtr) +{ + ListRep listRep; + ListObjGetRep(listPtr, &listRep); + + return ListRepLength(&listRep); } /* *---------------------------------------------------------------------- * * 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. + * 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 *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_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"); } - 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 (TclObjTypeHasProc(listObj, replaceProc)) { + return TclObjTypeReplace(interp, listObj, first, + numToDelete, numToInsert, insertObjs); + } + + if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) + return TCL_ERROR; /* Cannot be converted to a list */ + + /* Make limits sane */ + origListLen = ListRepLength(&listRep); 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 ; ielemCount = 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); + 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 -- * - * 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 + * 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 *listPtr, /* List being unpacked. */ - Tcl_Obj *argPtr) /* Index or index list. */ + Tcl_Obj *listObj, /* List being unpacked. */ + Tcl_Obj *argObj) /* Index or index list. */ { - - size_t index; /* Index into the list. */ + Tcl_Size index; /* Index into the list. */ Tcl_Obj *indexListCopy; - List *listRepPtr; + Tcl_Obj **indexObjs; + Tcl_Size numIndexObjs; /* * Determine whether argPtr designates a list or a single index. We have * to be careful about the order of the checks to avoid repeated - * shimmering; see TIP#22 and TIP#33 for the details. + * shimmering; if internal rep is already a list do not shimmer it. + * 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) { + if (!TclHasInternalRep(argObj, &tclListType) + && TclGetIntForIndexM(NULL, argObj, TCL_SIZE_MAX - 1, &index) + == TCL_OK) { /* * argPtr designates a single index. */ - - return TclLindexFlat(interp, listPtr, 1, &argPtr); + return TclLindexFlat(interp, listObj, 1, &argObj); } /* * Here we make a private copy of the index list argument to avoid any * shimmering issues that might invalidate the indices array below while @@ -1264,188 +2598,242 @@ * implementation changes in some unexpected way, or some new form of * trace or callback permits things to happen that the current * implementation does not. */ - indexListCopy = TclListObjCopy(NULL, argPtr); + indexListCopy = TclListObjCopy(NULL, argObj); if (indexListCopy == NULL) { /* - * argPtr designates something that is neither an index nor a - * well-formed list. Report the error via TclLindexFlat. + * The argument is neither an index nor a well-formed list. + * Report the error via TclLindexFlat. + * TODO - This is as original code. why not directly return an error? */ - - return TclLindexFlat(interp, listPtr, 1, &argPtr); - } - - ListGetIntRep(indexListCopy, listRepPtr); - - assert(listRepPtr != NULL); - - listPtr = TclLindexFlat(interp, listPtr, listRepPtr->elemCount, - &listRepPtr->elements); + return TclLindexFlat(interp, listObj, 1, &argObj); + } + TclListObjGetElementsM(interp, indexListCopy, &numIndexObjs, &indexObjs); + listObj = TclLindexFlat(interp, listObj, numIndexObjs, indexObjs); Tcl_DecrRefCount(indexListCopy); - return listPtr; + return listObj; } /* *---------------------------------------------------------------------- * - * 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); - * + * 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 *listPtr, /* Tcl object representing the list. */ - int indexCount, /* Count of indices. */ + Tcl_Obj *listObj, /* Tcl object representing the list. */ + Tcl_Size indexCount, /* Count of indices. */ Tcl_Obj *const indexArray[])/* Array of pointers to Tcl objects that * represent the indices in the list. */ { - int i; - - Tcl_IncrRefCount(listPtr); - - for (i=0 ; i error. - */ - - break; - } - TclListObjGetElements(NULL, sublistCopy, &listLen, &elemPtrs); + 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 = NULL; + for (i=0 ; i 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= (size_t)listLen) { + if (index < 0 || index >= listLen) { /* * Index is out of range. Break out of loop with empty result. * First check remaining indices for validity */ while (++i < indexCount) { - if (TclGetIntForIndexM(interp, indexArray[i], (size_t)WIDE_MAX - 1, &index) + if (TclGetIntForIndexM( + interp, indexArray[i], TCL_SIZE_MAX - 1, &index) != TCL_OK) { - Tcl_DecrRefCount(sublistCopy); + 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; } } - TclNewObj(listPtr); - } else { - /* - * Extract the pointer to the appropriate element. + + ListObjGetElements(listObj, listLen, elemPtrs); + /* increment this reference count first before decrementing + * just in case they are the same Tcl_Obj */ - - listPtr = elemPtrs[index]; - } - Tcl_IncrRefCount(listPtr); - } - Tcl_DecrRefCount(sublistCopy); - } - - return listPtr; + itemObj = elemPtrs[index]; + Tcl_IncrRefCount(itemObj); + Tcl_DecrRefCount(listObj); + /* Extract the pointer to the appropriate element. */ + listObj = itemObj; + } + } else { + Tcl_DecrRefCount(listObj); + listObj = NULL; + } + } + return listObj; } /* *---------------------------------------------------------------------- * * TclLsetList -- * - * The core of [lset] when objc == 4. Objv[2] may be either a + * Core of the 'lset' command when objc == 4. Objv[2] may be either a * scalar index or a list of indices. * It also handles 'lpop' when given a NULL value. * - * Implemented entirely as a wrapper around 'TclLindexFlat', as described - * for 'TclLindexList'. + * Results: + * Returns the new value of the list variable, or NULL if there was an + * error. The returned object includes one reference count for the + * pointer returned. * - * Value + * Side effects: + * None. * - * The new list, with the 'refCount' of 'valuPtr' incremented, or NULL if - * there was an error. + * Notes: + * This procedure is implemented entirely as a wrapper around + * TclLsetFlat. All it does is reconfigure the argument format into the + * form required by TclLsetFlat, while taking care to manage shimmering + * in such a way that we tend to keep the most useful internalreps and/or + * avoid the most expensive conversions. * *---------------------------------------------------------------------- */ - Tcl_Obj * TclLsetList( Tcl_Interp *interp, /* Tcl interpreter. */ - Tcl_Obj *listPtr, /* Pointer to the list being modified. */ - Tcl_Obj *indexArgPtr, /* Index or index-list arg to 'lset'. */ - Tcl_Obj *valuePtr) /* Value arg to 'lset' or NULL to 'lpop'. */ + Tcl_Obj *listObj, /* Pointer to the list being modified. */ + Tcl_Obj *indexArgObj, /* Index or index-list arg to 'lset'. */ + Tcl_Obj *valueObj) /* Value arg to 'lset' or NULL to 'lpop'. */ { - int indexCount = 0; /* Number of indices in the index list. */ + Tcl_Size indexCount = 0; /* Number of indices in the index list. */ Tcl_Obj **indices = NULL; /* Vector of indices in the index list. */ - Tcl_Obj *retValuePtr; /* Pointer to the list to be returned. */ - size_t index; /* Current index in the list - discarded. */ + Tcl_Obj *retValueObj; /* Pointer to the list to be returned. */ + Tcl_Size index; /* Current index in the list - discarded. */ Tcl_Obj *indexListCopy; - List *listRepPtr; /* * Determine whether the index arg designates a list or a single index. * We have to be careful about the order of the checks to avoid repeated * shimmering; see TIP #22 and #23 for details. */ - ListGetIntRep(indexArgPtr, listRepPtr); - if (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; + 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 != TclListObjGetElementsM( + 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; } /* *---------------------------------------------------------------------- * @@ -1452,113 +2840,110 @@ * 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. + * 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 *listPtr, /* Pointer to the list being modified. */ - int indexCount, /* Number of index args. */ + Tcl_Obj *listObj, /* Pointer to the list being modified. */ + Tcl_Size indexCount, /* Number of index args. */ Tcl_Obj *const indexArray[], /* Index args. */ - Tcl_Obj *valuePtr) /* Value arg to 'lset' or NULL to 'lpop'. */ + Tcl_Obj *valueObj) /* Value arg to 'lset' or NULL to 'lpop'. */ { - size_t index; - int result, len; - Tcl_Obj *subListPtr, *retValuePtr, *chainPtr; - Tcl_ObjIntRep *irPtr; + Tcl_Size index, len; + int result; + Tcl_Obj *subListObj, *retValueObj; + Tcl_Obj *pendingInvalidates[10]; + Tcl_Obj **pendingInvalidatesPtr = pendingInvalidates; + Tcl_Size numPendingInvalidates = 0; /* * If there are no indices, simply return the new value. (Without * indices, [lset] is a synonym for [set]. - * [lpop] does not use this but protect for NULL valuePtr just in case. + * [lpop] does not use this but protect for NULL valueObj just in case. */ if (indexCount == 0) { - if (valuePtr != NULL) { - Tcl_IncrRefCount(valuePtr); + if (valueObj != NULL) { + Tcl_IncrRefCount(valueObj); } - return valuePtr; + return valueObj; } /* * If the list is shared, make a copy we can modify (copy-on-write). We * use Tcl_DuplicateObj() instead of TclListObjCopy() for a few reasons: - * 1) we have not yet confirmed listPtr is actually a list; 2) We make a + * 1) we have not yet confirmed listObj is actually a list; 2) We make a * verbatim copy of any existing string rep, and when we combine that with * the delayed invalidation of string reps of modified Tcl_Obj's * implemented below, the outcome is that any error condition that causes - * this routine to return NULL, will leave the string rep of listPtr and + * this routine to return NULL, will leave the string rep of listObj and * all elements to be unchanged. */ - subListPtr = Tcl_IsShared(listPtr) ? Tcl_DuplicateObj(listPtr) : listPtr; + subListObj = Tcl_IsShared(listObj) ? Tcl_DuplicateObj(listObj) : listObj; /* * Anchor the linked list of Tcl_Obj's whose string reps must be * invalidated if the operation succeeds. */ - retValuePtr = subListPtr; - chainPtr = NULL; + 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 { - int elemCount; + Tcl_Size elemCount; Tcl_Obj *parentList, **elemPtrs; /* * Check for the possible error conditions... */ - if (TclListObjGetElements(interp, subListPtr, &elemCount, &elemPtrs) - != TCL_OK) { + if (TclListObjGetElementsM(interp, subListObj, &elemCount, &elemPtrs) + != TCL_OK) { /* ...the sublist we're indexing into isn't a list at all. */ result = TCL_ERROR; break; } @@ -1566,429 +2951,365 @@ * WARNING: the macro TclGetIntForIndexM is not safe for * post-increments, avoid '*indexArray++' here. */ if (TclGetIntForIndexM(interp, *indexArray, elemCount - 1, &index) - != TCL_OK) { + != TCL_OK) { /* ...the index we're trying to use isn't an index at all. */ result = TCL_ERROR; - indexArray++; + indexArray++; /* Why bother with this increment? TBD */ break; } indexArray++; - if (index > (size_t)elemCount - || (valuePtr == NULL && index >= (size_t)elemCount)) { + /* + * 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", 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. + * determine the next sublist for the next pass through the loop, + * and take steps to make sure it is an unshared copy, as we intend + * to modify it. */ if (--indexCount) { - parentList = subListPtr; - if (index == (size_t)elemCount) { - TclNewObj(subListPtr); + parentList = subListObj; + if (index == elemCount) { + TclNewObj(subListObj); } else { - subListPtr = elemPtrs[index]; + subListObj = elemPtrs[index]; } - if (Tcl_IsShared(subListPtr)) { - subListPtr = Tcl_DuplicateObj(subListPtr); + if (Tcl_IsShared(subListObj)) { + subListObj = Tcl_DuplicateObj(subListObj); } /* * Replace the original elemPtr[index] in parentList with a copy * we know to be unshared. This call will also deal with the - * situation where parentList shares its intrep with other - * Tcl_Obj's. Dealing with the shared intrep case can cause - * subListPtr to become shared again, so detect that case and make - * and store another copy. + * situation where parentList shares its internalrep with other + * Tcl_Obj's. Dealing with the shared internalrep case can + * cause subListObj to become shared again, so detect that case + * and make and store another copy. */ - if (index == (size_t)elemCount) { - Tcl_ListObjAppendElement(NULL, parentList, subListPtr); + if (index == elemCount) { + Tcl_ListObjAppendElement(NULL, parentList, subListObj); } else { - TclListObjSetElement(NULL, parentList, index, subListPtr); + TclListObjSetElement(NULL, parentList, index, subListObj); } - if (Tcl_IsShared(subListPtr)) { - subListPtr = Tcl_DuplicateObj(subListPtr); - TclListObjSetElement(NULL, parentList, index, subListPtr); + if (Tcl_IsShared(subListObj)) { + subListObj = Tcl_DuplicateObj(subListObj); + TclListObjSetElement(NULL, parentList, index, subListObj); } /* - * The TclListObjSetElement() calls do not spoil the string rep of - * parentList, and that's fine for now, since all we've done so - * far is replace a list element with an unshared copy. The list - * value remains the same, so the string rep. is still valid, and - * unchanged, which is good because if this whole routine returns - * NULL, we'd like to leave no change to the value of the lset - * variable. Later on, when we set valuePtr in its proper place, - * then all containing lists will have their values changed, and - * will need their string reps spoiled. We maintain a list of all - * those Tcl_Obj's (via a little intrep surgery) so we can spoil - * them at that time. + * The TclListObjSetElement() calls do not spoil the string rep + * of parentList, and that's fine for now, since all we've done + * so far is replace a list element with an unshared copy. The + * list value remains the same, so the string rep. is still + * valid, and unchanged, which is good because if this whole + * routine returns NULL, we'd like to leave no change to the + * value of the lset variable. Later on, when we set valueObj + * in its proper place, then all containing lists will have + * their values changed, and will need their string reps + * spoiled. We maintain a list of all those Tcl_Obj's (via a + * little internalrep surgery) so we can spoil them at that + * time. */ - irPtr = TclFetchIntRep(parentList, &tclListType); - irPtr->twoPtrValue.ptr2 = chainPtr; - chainPtr = parentList; + pendingInvalidatesPtr[numPendingInvalidates] = parentList; + ++numPendingInvalidates; } } while (indexCount > 0); /* * Either we've detected and error condition, and exited the loop with * result == TCL_ERROR, or we've successfully reached the last index, and - * we're ready to store valuePtr. In either case, we need to clean up our - * string spoiling list of Tcl_Obj's. - */ - - 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; - } - } + * 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 (retValuePtr != listPtr) { - Tcl_DecrRefCount(retValuePtr); + if (retValueObj != listObj) { + Tcl_DecrRefCount(retValueObj); } return NULL; } /* - * Store valuePtr in proper sublist and return. The -1 is to avoid a + * Store valueObj in proper sublist and return. The -1 is to avoid a * compiler warning (not a problem because we checked that we have a * proper list - or something convertible to one - above). */ len = -1; - TclListObjLength(NULL, subListPtr, &len); - if (valuePtr == NULL) { - Tcl_ListObjReplace(NULL, subListPtr, index, 1, 0, NULL); - } else if (index == (size_t)len) { - Tcl_ListObjAppendElement(NULL, subListPtr, valuePtr); + TclListObjLengthM(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 { - TclListObjSetElement(NULL, subListPtr, index, valuePtr); - TclInvalidateStringRep(subListPtr); + /* T:listrep-1.{12.1,15.1,19.1},2.{10,13,16}.1 */ + TclListObjSetElement(NULL, subListObj, index, valueObj); + TclInvalidateStringRep(subListObj); } - Tcl_IncrRefCount(retValuePtr); - return retValuePtr; + Tcl_IncrRefCount(retValueObj); + return retValueObj; } /* *---------------------------------------------------------------------- * * TclListObjSetElement -- * - * Set a single element of a list to a specified value. - * - * 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); + * 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 "u\" 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 the internal representation of a - * a list object. + * Deallocate the storage associated with a list object's internal + * representation. + * + * Results: + * None. * - * Effect - * + * Side effects: * Frees listPtr's List* internal representation, if no longer shared. * May decrement the ref counts of element objects, which may free them. * *---------------------------------------------------------------------- */ - static void FreeListInternalRep( - Tcl_Obj *listPtr) /* List object with internal rep to free. */ -{ - 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); + 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 + * Initialize the internal representation of a list Tcl_Obj to share the * internal representation of an existing list object. * - * Effect + * Results: + * None. * - * The 'refCount' of the List internal rep is incremented. + * Side effects: + * The reference count of the List internal rep is incremented. * *---------------------------------------------------------------------- */ - static void DupListInternalRep( - Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ - Tcl_Obj *copyPtr) /* Object with internal rep to set. */ -{ - List *listRepPtr; - - ListGetIntRep(srcPtr, listRepPtr); - assert(listRepPtr != NULL); - ListSetIntRep(copyPtr, listRepPtr); + 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 -- * - * 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. - * + * 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. */ { - List *listRepPtr; Tcl_Obj **elemPtrs; + ListRep listRep; /* * Dictionaries are a special case; they have a string representation such * that *all* valid dictionaries are valid lists. Hence we can convert * more directly. Only do this when there's no existing string rep; if * there is, it is the string rep that's authoritative (because it could * describe duplicate keys). */ - if (!TclHasStringRep(objPtr) && TclHasIntRep(objPtr, &tclDictType)) { + if (!TclHasStringRep(objPtr) && TclHasInternalRep(objPtr, &tclDictType)) { Tcl_Obj *keyPtr, *valuePtr; Tcl_DictSearch search; - int done, size; + int done; + Tcl_Size size; /* * Create the new list representation. Note that we do not need to do * anything with the string representation as the transformation (and * the reverse back to a dictionary) are both order-preserving. Also @@ -1996,65 +3317,98 @@ * 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) { + /* TODO - leave space in front and/or back? */ + if (ListRepInitAttempt( + interp, size > 0 ? 2 * size : 1, NULL, &listRep) + != TCL_OK) { return TCL_ERROR; } - listRepPtr->elemCount = 2 * size; + + LIST_ASSERT(listRep.spanPtr == NULL); /* Guard against future changes */ + LIST_ASSERT(listRep.storePtr->firstUsed == 0); + LIST_ASSERT((listRep.storePtr->flags & LISTSTORE_CANONICAL) == 0); + + listRep.storePtr->numUsed = 2 * size; - /* - * Populate the list representation. - */ + /* Populate the list representation. */ - elemPtrs = &listRepPtr->elements; + elemPtrs = listRep.storePtr->slots; Tcl_DictObjFirst(NULL, objPtr, &search, &keyPtr, &valuePtr, &done); while (!done) { *elemPtrs++ = keyPtr; *elemPtrs++ = valuePtr; Tcl_IncrRefCount(keyPtr); Tcl_IncrRefCount(valuePtr); Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done); } + } else if (TclObjTypeHasProc(objPtr,indexProc)) { + Tcl_Size elemCount, i; + + elemCount = TclObjTypeLength(objPtr); + + if (ListRepInitAttempt(interp, elemCount, NULL, &listRep) != TCL_OK) { + return TCL_ERROR; + } + + LIST_ASSERT(listRep.spanPtr == NULL); /* Guard against future changes */ + LIST_ASSERT(listRep.storePtr->firstUsed == 0); + + elemPtrs = listRep.storePtr->slots; + + /* Each iteration, store a list element */ + for (i = 0; i < elemCount; i++) { + if (TclObjTypeIndex(interp, objPtr, i, elemPtrs) != TCL_OK) { + return TCL_ERROR; + } + Tcl_IncrRefCount(*elemPtrs++);/* Since list now holds ref to it. */ + } + + LIST_ASSERT((Tcl_Size)(elemPtrs - listRep.storePtr->slots) == elemCount); + + listRep.storePtr->numUsed = elemCount; + } else { - int estCount; - size_t length; - const char *limit, *nextElem = TclGetStringFromObj(objPtr, &length); + Tcl_Size estCount, length; + const char *limit, *nextElem = Tcl_GetStringFromObj(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) { + /* TODO - allocate additional space? */ + if (ListRepInitAttempt(interp, estCount, NULL, &listRep) + != TCL_OK) { return TCL_ERROR; } - elemPtrs = &listRepPtr->elements; + + LIST_ASSERT(listRep.spanPtr == NULL); /* Guard against future changes */ + LIST_ASSERT(listRep.storePtr->firstUsed == 0); + + elemPtrs = listRep.storePtr->slots; - /* - * Each iteration, parse and store a list element. - */ + /* Each iteration, parse and store a list element. */ while (nextElem < limit) { const char *elemStart; char *check; - size_t elemSize; + Tcl_Size elemSize; int literal; if (TCL_OK != TclFindElement(interp, nextElem, limit - nextElem, &elemStart, &nextElem, &elemSize, &literal)) { - fail: - while (--elemPtrs >= &listRepPtr->elements) { +fail: + while (--elemPtrs >= listRep.storePtr->slots) { Tcl_DecrRefCount(*elemPtrs); } - Tcl_Free(listRepPtr); + Tcl_Free(listRep.storePtr); return TCL_ERROR; } if (elemStart == limit) { break; } @@ -2062,15 +3416,11 @@ 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); - } + MemoryAllocationError(interp, elemSize); goto fail; } if (!literal) { Tcl_InitStringRep(*elemPtrs, NULL, TclCopyAndCollapse(elemSize, elemStart, check)); @@ -2077,20 +3427,33 @@ } Tcl_IncrRefCount(*elemPtrs++);/* Since list now holds ref to it. */ } - listRepPtr->elemCount = elemPtrs - &listRepPtr->elements; + 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. */ - ListSetIntRep(objPtr, listRepPtr); + /* + * 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; } /* *---------------------------------------------------------------------- @@ -2097,11 +3460,11 @@ * * UpdateStringOfList -- * * Update the string representation for a list object. * - * Any previously-exising string representation is not invalidated, so + * Any previously-existing string representation is not invalidated, so * storage is lost if this has not been taken care of. * * Effect * * The string representation of 'listPtr' is set to the resulting string. @@ -2108,91 +3471,151 @@ * This string will be empty if the list has no elements. It is assumed * that the list internal representation is not NULL. * *---------------------------------------------------------------------- */ - static void UpdateStringOfList( - Tcl_Obj *listPtr) /* List object with string rep to update. */ + Tcl_Obj *listObj) /* List object with string rep to update. */ { # define LOCAL_SIZE 64 char localFlags[LOCAL_SIZE], *flagPtr = NULL; - int numElems, i; - size_t length, bytesNeeded = 0; + Tcl_Size numElems, i, length; + size_t bytesNeeded = 0; const char *elem, *start; char *dst; Tcl_Obj **elemPtrs; - List *listRepPtr; + ListRep listRep; - ListGetIntRep(listPtr, listRepPtr); + ListObjGetRep(listObj, &listRep); + LISTREP_CHECK(&listRep); - assert(listRepPtr != NULL); - - numElems = listRepPtr->elemCount; + ListRepElements(&listRep, numElems, elemPtrs); /* * Mark the list as being canonical; although it will now have a string * rep, it is one we derived through proper "canonical" quoting and so * it's known to be free from nasties relating to [concat] and [eval]. - */ - - listRepPtr->canonicalFlag = 1; - - /* - * Handle empty list case first, so rest of the routine is simpler. + * 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(listPtr, NULL, 0); + Tcl_InitStringRep(listObj, NULL, 0); return; } - /* - * Pass 1: estimate space, gather flags. - */ + /* Pass 1: estimate space, gather flags. */ if (numElems <= LOCAL_SIZE) { flagPtr = localFlags; } else { - /* - * We know numElems <= LIST_MAX, so this is safe. - */ - + /* We know numElems <= LIST_MAX, so this is safe. */ flagPtr = (char *)Tcl_Alloc(numElems); } - elemPtrs = &listRepPtr->elements; for (i = 0; i < numElems; i++) { flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0); - elem = TclGetStringFromObj(elemPtrs[i], &length); + elem = Tcl_GetStringFromObj(elemPtrs[i], &length); bytesNeeded += TclScanElement(elem, length, flagPtr+i); + if (bytesNeeded > SIZE_MAX - numElems) { + Tcl_Panic("max size for a Tcl value (%" TCL_Z_MODIFIER "u bytes) exceeded", SIZE_MAX); + } } bytesNeeded += numElems - 1; /* * Pass 2: copy into string rep buffer. */ - start = dst = Tcl_InitStringRep(listPtr, NULL, bytesNeeded); + start = dst = Tcl_InitStringRep(listObj, NULL, bytesNeeded); TclOOM(dst, bytesNeeded); for (i = 0; i < numElems; i++) { flagPtr[i] |= (i ? TCL_DONT_QUOTE_HASH : 0); - elem = TclGetStringFromObj(elemPtrs[i], &length); + elem = Tcl_GetStringFromObj(elemPtrs[i], &length); dst += TclConvertElement(elem, length, dst, flagPtr[i]); *dst++ = ' '; } /* Set the string length to what was actually written, the safe choice */ - (void) Tcl_InitStringRep(listPtr, NULL, dst - 1 - start); + (void) Tcl_InitStringRep(listObj, NULL, dst - 1 - start); if (flagPtr != localFlags) { Tcl_Free(flagPtr); } } + +/* + *------------------------------------------------------------------------ + * + * TclListTestObj -- + * + * Returns a list object with a specific internal rep and content. + * Used specifically for testing so span can be controlled explicitly. + * + * Results: + * Pointer to the Tcl_Obj containing the list. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ +Tcl_Obj * +TclListTestObj(size_t length, size_t leadingSpace, size_t endSpace) +{ + ListRep listRep; + size_t capacity; + Tcl_Obj *listObj; + + TclNewObj(listObj); + + /* Only a test object so ignoring overflow checks */ + capacity = length + leadingSpace + endSpace; + if (capacity == 0) { + return listObj; + } + if (capacity > LIST_MAX) { + return NULL; + } + + ListRepInit(capacity, NULL, LISTREP_PANIC_ON_FAIL, &listRep); + + ListStore *storePtr = listRep.storePtr; + size_t i; + for (i = 0; i < length; ++i) { + TclNewUIntObj(storePtr->slots[i + leadingSpace], i); + Tcl_IncrRefCount(storePtr->slots[i + leadingSpace]); + } + storePtr->firstUsed = leadingSpace; + storePtr->numUsed = length; + if (leadingSpace != 0) { + listRep.spanPtr = ListSpanNew(leadingSpace, length); + } + ListObjReplaceRepAndInvalidate(listObj, &listRep); + return listObj; +} + /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tclLiteral.c ================================================================== --- generic/tclLiteral.c +++ generic/tclLiteral.c @@ -5,12 +5,12 @@ * manage the Tcl objects created for literal values during compilation * of Tcl scripts. This implementation borrows heavily from the more * general hashtable implementation of Tcl hash tables that appears in * tclHash.c. * - * Copyright (c) 1997-1998 Sun Microsystems, Inc. - * Copyright (c) 2004 by Kevin B. Kenny. All rights reserved. + * Copyright © 1997-1998 Sun Microsystems, Inc. + * Copyright © 2004 Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -26,14 +26,15 @@ /* * Function prototypes for static functions in this file: */ -static int AddLocalLiteralEntry(CompileEnv *envPtr, - Tcl_Obj *objPtr, int localHash); +static Tcl_Obj * CreateLiteral(Interp *iPtr, const char *bytes, + Tcl_Size length, int *newPtr, Namespace *nsPtr, + int flags, LiteralEntry **globalPtrPtr); static void ExpandLocalLiteralArray(CompileEnv *envPtr); -static size_t HashString(const char *string, size_t length); +static size_t HashString(const char *string, Tcl_Size length); #ifdef TCL_COMPILE_DEBUG static LiteralEntry * LookupLiteralEntry(Tcl_Interp *interp, Tcl_Obj *objPtr); #endif static void RebuildLiteralTable(LiteralTable *tablePtr); @@ -156,12 +157,11 @@ * table that has a string representation matching the argument * string. If nsPtr!=NULL then only literals stored for the namespace are * considered. * * Results: - * The literal object. If it was created in this call *newPtr is set to - * 1, else 0. NULL is returned if newPtr==NULL and no literal is found. + * The literal object. * * Side effects: * Increments the ref count of the global LiteralEntry since the caller * now holds a reference. If LITERAL_ON_HEAP is set in flags, this * function is given ownership of the string: if an object is created @@ -176,13 +176,22 @@ Tcl_Obj * TclCreateLiteral( Interp *iPtr, const char *bytes, /* The start of the string. Note that this is * not a NUL-terminated string. */ - size_t length, /* Number of bytes in the string. */ - size_t hash, /* The string's hash. If -1, it will be - * computed here. */ + Tcl_Size length) /* Number of bytes in the string. */ +{ + int isNew; + return CreateLiteral(iPtr, bytes, length, &isNew, NULL, 0, NULL); +} + +static Tcl_Obj * +CreateLiteral( + 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. */ int *newPtr, Namespace *nsPtr, int flags, LiteralEntry **globalPtrPtr) { @@ -193,14 +202,30 @@ /* * Is it in the interpreter's global literal table? */ - if (hash == TCL_INDEX_NONE) { - hash = HashString(bytes, length); + if (length == -1) { + length = strlen(bytes); + } + + /* + * If the literal 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; + } else { + nsPtr = iPtr->varFramePtr->nsPtr; + } } - globalHash = (hash & globalTablePtr->mask); + + globalHash = (HashString(bytes, length) & globalTablePtr->mask); for (globalPtr=globalTablePtr->buckets[globalHash] ; globalPtr!=NULL; globalPtr = globalPtr->nextPtr) { objPtr = globalPtr->objPtr; if (globalPtr->nsPtr == nsPtr) { /* @@ -208,12 +233,12 @@ * 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); + Tcl_Size objLength; + const char *objBytes = Tcl_GetStringFromObj(objPtr, &objLength); if ((objLength == length) && ((length == 0) || ((objBytes[0] == bytes[0]) && (memcmp(objBytes, bytes, length) == 0)))) { /* @@ -221,24 +246,32 @@ */ if (newPtr) { *newPtr = 0; } - if (globalPtrPtr) { - *globalPtrPtr = globalPtr; - } - if (flags & LITERAL_ON_HEAP) { + if ((flags & LITERAL_ON_HEAP)) { Tcl_Free((void *)bytes); } - if (globalPtr->refCount != TCL_INDEX_NONE) { - globalPtr->refCount++; + if (globalPtrPtr) { + *globalPtrPtr = globalPtr; + } else { + if (globalPtr->refCount != TCL_INDEX_NONE) { + globalPtr->refCount++; + } +#ifdef TCL_COMPILE_DEBUG + if (globalPtr->refCount + 1 < 2) { + Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %" + TCL_Z_MODIFIER "u", "TclRegisterLiteral", + (length>60? 60 : length), bytes, globalPtr->refCount); + } +#endif } return objPtr; } } } - if (!newPtr) { + if (newPtr == NULL) { if ((flags & LITERAL_ON_HEAP)) { Tcl_Free((void *)bytes); } return NULL; } @@ -299,11 +332,11 @@ #ifdef TCL_COMPILE_DEBUG TclVerifyGlobalLiteralTable(iPtr); { LiteralEntry *entryPtr; int found; - size_t i; + Tcl_Size i; found = 0; for (i=0 ; inumBuckets ; i++) { for (entryPtr=globalTablePtr->buckets[i]; entryPtr!=NULL ; entryPtr=entryPtr->nextPtr) { @@ -349,17 +382,17 @@ Tcl_Obj * TclFetchLiteral( CompileEnv *envPtr, /* Points to the CompileEnv from which to * fetch the registered literal value. */ - size_t index) /* Index of the desired literal, as returned + Tcl_Size index) /* Index of the desired literal, as returned * by prior call to TclRegisterLiteral() */ { - if (index >= (size_t) envPtr->literalArrayNext) { + if (index >= envPtr->literalArrayNext) { return NULL; } - return envPtr->literalArrayPtr[index].objPtr; + return envPtr->literalArrayPtr[index]; } /* *---------------------------------------------------------------------- * @@ -385,98 +418,51 @@ * buffer holding the result of backslash substitutions. * *---------------------------------------------------------------------- */ -int +int /* Do NOT change this type. Should not be wider than TclEmitPush operand*/ TclRegisterLiteral( void *ePtr, /* Points to the CompileEnv in whose object * array an object is found or created. */ const char *bytes, /* Points to string for which to find or * create an object in CompileEnv's object * array. */ - size_t length, /* Number of bytes in the string. If -1, the + Tcl_Size length, /* Number of bytes in the string. If -1, the * string consists of all bytes up to the * first null character. */ int flags) /* If LITERAL_ON_HEAP then the caller already * malloc'd bytes and ownership is passed to * this function. If LITERAL_CMD_NAME then - * the literal should not be shared accross + * the literal should not be shared across * namespaces. */ { CompileEnv *envPtr = (CompileEnv *)ePtr; Interp *iPtr = envPtr->iPtr; - LiteralTable *localTablePtr = &envPtr->localLitTable; - LiteralEntry *globalPtr, *localPtr; - Tcl_Obj *objPtr; - size_t hash, localHash, objIndex; - int isNew; - Namespace *nsPtr; - - if (length == TCL_INDEX_NONE) { - 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. - */ - - localHash = (hash & localTablePtr->mask); - for (localPtr=localTablePtr->buckets[localHash] ; localPtr!=NULL; - localPtr = localPtr->nextPtr) { - objPtr = localPtr->objPtr; - if ((objPtr->length == length) && ((length == 0) - || ((objPtr->bytes[0] == bytes[0]) - && (memcmp(objPtr->bytes, bytes, length) == 0)))) { - if ((flags & LITERAL_ON_HEAP)) { - 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; - } else { - nsPtr = iPtr->varFramePtr->nsPtr; - } - } else { - nsPtr = NULL; - } - - /* - * Is it in the interpreter's global literal table? If not, create it. - */ - - globalPtr = NULL; - objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &isNew, nsPtr, flags, - &globalPtr); - objIndex = AddLocalLiteralEntry(envPtr, objPtr, localHash); - -#ifdef TCL_COMPILE_DEBUG - 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*/ + Namespace *nsPtr = NULL; + Tcl_Obj *objPtr; + LiteralEntry *globalPtr; + Tcl_HashEntry *hePtr; + int objIndex, globalNew, isNew = 0; + + objPtr = CreateLiteral(iPtr, bytes, length, &globalNew, nsPtr, + flags, &globalPtr); + + hePtr = Tcl_CreateHashEntry(&envPtr->litMap, objPtr, &isNew); + if (isNew) { + objIndex = TclAddLiteralObj(envPtr, objPtr, NULL); + Tcl_SetHashValue(hePtr, INT2PTR(objIndex)); + if (!globalNew && globalPtr) { + globalPtr->refCount++; + } + } else { + objIndex = PTR2INT(Tcl_GetHashValue(hePtr)); + } + if (objIndex > INT_MAX) { + Tcl_Panic( + "Literal table index too large. Cannot be handled by TclEmitPush"); + } return objIndex; } #ifdef TCL_COMPILE_DEBUG /* @@ -506,13 +492,14 @@ { Interp *iPtr = (Interp *) interp; LiteralTable *globalTablePtr = &iPtr->literalTable; LiteralEntry *entryPtr; const char *bytes; - size_t globalHash, length; + size_t globalHash; + Tcl_Size length; - bytes = TclGetStringFromObj(objPtr, &length); + bytes = Tcl_GetStringFromObj(objPtr, &length); globalHash = (HashString(bytes, length) & globalTablePtr->mask); for (entryPtr=globalTablePtr->buckets[globalHash] ; entryPtr!=NULL; entryPtr=entryPtr->nextPtr) { if (entryPtr->objPtr == objPtr) { return entryPtr; @@ -549,15 +536,13 @@ 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 **lPtr; Tcl_Obj *newObjPtr; + Tcl_HashEntry *hePtr; lPtr = &envPtr->literalArrayPtr[index]; /* * To avoid unwanted sharing we need to copy the object and remove it from @@ -564,28 +549,18 @@ * the local and global literal tables. It still has a slot in the literal * array so it can be referred to by byte codes, but it will not be * matched by literal searches. */ - newObjPtr = Tcl_DuplicateObj(lPtr->objPtr); + hePtr = Tcl_FindHashEntry(&envPtr->litMap, *lPtr); + if (hePtr) { + Tcl_DeleteHashEntry(hePtr); + } + + newObjPtr = Tcl_DuplicateObj(*lPtr); Tcl_IncrRefCount(newObjPtr); - TclReleaseLiteral(interp, lPtr->objPtr); - lPtr->objPtr = newObjPtr; - - bytes = TclGetStringFromObj(newObjPtr, &length); - localHash = HashString(bytes, length) & localTablePtr->mask; - nextPtrPtr = &localTablePtr->buckets[localHash]; - - for (entryPtr=*nextPtrPtr ; entryPtr!=NULL ; entryPtr=*nextPtrPtr) { - if (entryPtr == lPtr) { - *nextPtrPtr = lPtr->nextPtr; - lPtr->nextPtr = NULL; - localTablePtr->numEntries--; - break; - } - nextPtrPtr = &entryPtr->nextPtr; - } + TclReleaseLiteral(interp, *lPtr); } /* *---------------------------------------------------------------------- * @@ -595,12 +570,11 @@ * not add the literal to the local or global literal tables. The caller * is expected to add the entry to whatever tables are appropriate. * * Results: * The index in the CompileEnv's literal array that references the - * literal. Stores the pointer to the new literal entry in the location - * referenced by the localPtrPtr argument. + * literal. * * Side effects: * Expands the literal array if necessary. Increments the refcount on the * literal object. * @@ -610,110 +584,32 @@ int TclAddLiteralObj( CompileEnv *envPtr,/* Points to CompileEnv in whose literal array * 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 **litPtrPtr) /* UNUSED. Still in place due to publication + * in the internal stubs table, and use by + * tclcompiler. */ { - LiteralEntry *lPtr; - int objIndex; + Tcl_Size 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; - - if (litPtrPtr) { - *litPtrPtr = lPtr; - } - - return objIndex; -} - -/* - *---------------------------------------------------------------------- - * - * AddLocalLiteralEntry -- - * - * Insert a new literal into a CompileEnv's local literal array. - * - * Results: - * The index in the CompileEnv's literal array that references the - * literal. - * - * 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. - */ - - localPtr->nextPtr = localTablePtr->buckets[localHash]; - localTablePtr->buckets[localHash] = localPtr; - localTablePtr->numEntries++; - - /* - * If the CompileEnv's local literal table has exceeded a decent size, - * rebuild it with more buckets. - */ - - if (localTablePtr->numEntries >= localTablePtr->rebuildSize) { - RebuildLiteralTable(localTablePtr); - } - -#ifdef TCL_COMPILE_DEBUG - TclVerifyLocalLiteralTable(envPtr); - { - char *bytes; - int found; - size_t length, i; - - found = 0; - for (i=0 ; inumBuckets ; i++) { - for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL ; - localPtr=localPtr->nextPtr) { - if (localPtr->objPtr == objPtr) { - found = 1; - } - } - } - - if (!found) { - bytes = TclGetStringFromObj(objPtr, &length); - Tcl_Panic("%s: literal \"%.*s\" wasn't found locally", - "AddLocalLiteralEntry", (length>60? 60 : (int)length), bytes); - } - } -#endif /*TCL_COMPILE_DEBUG*/ - - return objIndex; + if (objIndex > INT_MAX) { + Tcl_Panic( + "Literal table index too large. Cannot be handled by TclEmitPush"); + } + + envPtr->literalArrayPtr[objIndex] = objPtr; + Tcl_IncrRefCount(objPtr); + + return objIndex; + + (void)litPtrPtr; } /* *---------------------------------------------------------------------- * @@ -742,53 +638,32 @@ /* * The current allocated local literal entries are stored between elements * 0 and (envPtr->literalArrayNext - 1) [inclusive]. */ - LiteralTable *localTablePtr = &envPtr->localLitTable; - size_t currElems = envPtr->literalArrayNext; - size_t currBytes = (currElems * sizeof(LiteralEntry)); - LiteralEntry *currArrayPtr = envPtr->literalArrayPtr; - LiteralEntry *newArrayPtr; - size_t i; - size_t newSize = (currBytes <= UINT_MAX / 2) ? 2*currBytes : UINT_MAX; + Tcl_Size currElems = envPtr->literalArrayNext; + Tcl_Size currBytes = (currElems * sizeof(Tcl_Obj *)); + Tcl_Obj **currArrayPtr = envPtr->literalArrayPtr; + Tcl_Obj **newArrayPtr; + Tcl_Size newSize = (currBytes <= UINT_MAX / 2) ? 2*currBytes : UINT_MAX; if (currBytes == newSize) { Tcl_Panic("max size of Tcl literal array (%" TCL_Z_MODIFIER "u literals) exceeded", currElems); } if (envPtr->mallocedLiteralArray) { - newArrayPtr = (LiteralEntry *)Tcl_Realloc(currArrayPtr, newSize); + newArrayPtr = (Tcl_Obj **)Tcl_Realloc(currArrayPtr, newSize); } else { /* * envPtr->literalArrayPtr isn't a Tcl_Alloc'd pointer, so we must * code a Tcl_Realloc equivalent for ourselves. */ - newArrayPtr = (LiteralEntry *)Tcl_Alloc(newSize); + newArrayPtr = (Tcl_Obj **)Tcl_Alloc(newSize); memcpy(newArrayPtr, currArrayPtr, currBytes); envPtr->mallocedLiteralArray = 1; - } - - /* - * Update the local literal table's bucket array. - */ - - if (currArrayPtr != newArrayPtr) { - for (i=0 ; inumBuckets ; i++) { - if (localTablePtr->buckets[i] != NULL) { - localTablePtr->buckets[i] = newArrayPtr - + (localTablePtr->buckets[i] - currArrayPtr); - } - } } envPtr->literalArrayPtr = newArrayPtr; envPtr->literalArrayEnd = newSize / sizeof(LiteralEntry); } @@ -824,18 +699,19 @@ { Interp *iPtr = (Interp *) interp; LiteralTable *globalTablePtr; LiteralEntry *entryPtr, *prevPtr; const char *bytes; - size_t length, index; + size_t index; + Tcl_Size length; if (iPtr == NULL) { goto done; } globalTablePtr = &iPtr->literalTable; - bytes = TclGetStringFromObj(objPtr, &length); + bytes = Tcl_GetStringFromObj(objPtr, &length); index = HashString(bytes, length) & globalTablePtr->mask; /* * Check to see if the object is in the global literal table and remove * this reference. The object may not be in the table if it is a hidden @@ -896,11 +772,11 @@ */ static size_t HashString( const char *string, /* String for which to compute hash value. */ - size_t length) /* Number of bytes in the string. */ + Tcl_Size length) /* Number of bytes in the string. */ { size_t result = 0; /* * I tried a zillion different hash functions and asked many other people @@ -967,11 +843,12 @@ LiteralEntry **oldBuckets; LiteralEntry **oldChainPtr, **newChainPtr; LiteralEntry *entryPtr; LiteralEntry **bucketPtr; const char *bytes; - size_t oldSize, count, index, length; + size_t oldSize, count, index; + Tcl_Size length; oldSize = tablePtr->numBuckets; oldBuckets = tablePtr->buckets; /* @@ -1003,11 +880,11 @@ * Rehash all of the existing entries into the new bucket array. */ for (oldChainPtr=oldBuckets ; oldSize>0 ; oldSize--,oldChainPtr++) { for (entryPtr=*oldChainPtr ; entryPtr!=NULL ; entryPtr=*oldChainPtr) { - bytes = TclGetStringFromObj(entryPtr->objPtr, &length); + bytes = Tcl_GetStringFromObj(entryPtr->objPtr, &length); index = (HashString(bytes, length) & tablePtr->mask); *oldChainPtr = entryPtr->nextPtr; bucketPtr = &tablePtr->buckets[index]; entryPtr->nextPtr = *bucketPtr; @@ -1039,11 +916,11 @@ * Results: * None. * * Side effects: * Resets the internal representation of the CmdName Tcl_Obj - * using TclFreeIntRep(). + * using TclFreeInternalRep(). * *---------------------------------------------------------------------- */ void @@ -1054,20 +931,15 @@ * 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); + Tcl_Obj *literalObjPtr = CreateLiteral(iPtr, name, strlen(name), + NULL, nsPtr, 0, NULL); + + if (literalObjPtr && TclHasInternalRep(literalObjPtr, &tclCmdNameType)) { + TclFreeInternalRep(literalObjPtr); } } #ifdef TCL_COMPILE_STATS /* @@ -1091,11 +963,11 @@ char * TclLiteralStats( LiteralTable *tablePtr) /* Table for which to produce stats. */ { #define NUM_COUNTERS 10 - size_t count[NUM_COUNTERS], overflow, i, j; + Tcl_Size count[NUM_COUNTERS], overflow, i, j; double average, tmp; LiteralEntry *entryPtr; char *result, *p; /* @@ -1117,31 +989,32 @@ if (j < NUM_COUNTERS) { count[j]++; } else { overflow++; } + /* TODO: This is going to be trouble for large enough j */ tmp = j; average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0; } /* * Print out the histogram and a few other pieces of information. */ result = (char *)Tcl_Alloc(NUM_COUNTERS*60 + 300); - sprintf(result, "%" TCL_Z_MODIFIER "u entries in table, %" TCL_Z_MODIFIER "u buckets\n", + snprintf(result, 60, "%" TCL_Z_MODIFIER "u entries in table, %" TCL_Z_MODIFIER "u buckets\n", tablePtr->numEntries, tablePtr->numBuckets); p = result + strlen(result); for (i=0 ; ilocalLitTable; - LiteralEntry *localPtr; - char *bytes; - size_t i, length, count = 0; - - for (i=0 ; inumBuckets ; i++) { - for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL; - localPtr=localPtr->nextPtr) { - count++; - if (localPtr->refCount != TCL_INDEX_NONE) { - bytes = TclGetStringFromObj(localPtr->objPtr, &length); - Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %" TCL_Z_MODIFIER "u", - "TclVerifyLocalLiteralTable", - (length>60? 60 : (int) length), bytes, localPtr->refCount); - } - if (localPtr->objPtr->bytes == NULL) { - Tcl_Panic("%s: literal has NULL string rep", - "TclVerifyLocalLiteralTable"); - } - } - } - if (count != localTablePtr->numEntries) { - Tcl_Panic("%s: local literal table had %" TCL_Z_MODIFIER "u entries, should be %" TCL_Z_MODIFIER "u", - "TclVerifyLocalLiteralTable", count, - localTablePtr->numEntries); + Tcl_HashTable *mapPtr = &envPtr->litMap; + Tcl_HashSearch search; + Tcl_HashEntry *hePtr = Tcl_FirstHashEntry(mapPtr, &search); + + while (hePtr) { + Tcl_Obj *objPtr = Tcl_GetHashKey(mapPtr, hePtr); + + if (objPtr->bytes == NULL) { + Tcl_Panic("%s: literal has NULL string rep", + "TclVerifyLocalLiteralTable"); + } + hePtr = Tcl_NextHashEntry(&search); } } /* *---------------------------------------------------------------------- @@ -1216,18 +1076,18 @@ * table is to be validated. */ { LiteralTable *globalTablePtr = &iPtr->literalTable; LiteralEntry *globalPtr; char *bytes; - size_t i, length, count = 0; + Tcl_Size i, length, count = 0; for (i=0 ; inumBuckets ; i++) { for (globalPtr=globalTablePtr->buckets[i] ; globalPtr!=NULL; globalPtr=globalPtr->nextPtr) { count++; if (globalPtr->refCount + 1 < 2) { - bytes = TclGetStringFromObj(globalPtr->objPtr, &length); + bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length); Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %" TCL_Z_MODIFIER "u", "TclVerifyGlobalLiteralTable", (length>60? 60 : (int)length), bytes, globalPtr->refCount); } if (globalPtr->objPtr->bytes == NULL) { Index: generic/tclLoad.c ================================================================== --- generic/tclLoad.c +++ generic/tclLoad.c @@ -2,101 +2,110 @@ * tclLoad.c -- * * This file provides the generic portion (those that are the same on all * platforms) of Tcl's dynamic loading facilities. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright © 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" + /* - * The following structure describes a package that has been loaded either + * The following structure describes a library that has been loaded either * dynamically (with the "load" command) or statically (as indicated by a call - * to TclGetLoadedPackages). All such packages are linked together into a - * single list for the process. Packages are never unloaded, until the - * application exits, when TclFinalizeLoad is called, and these structures are - * freed. + * to Tcl_StaticLibrary). All such libraries are linked together into a + * single list for the process. */ -typedef struct LoadedPackage { - char *fileName; /* Name of the file from which the package was - * loaded. An empty string means the package +typedef struct LoadedLibrary { + char *fileName; /* Name of the file from which the library was + * loaded. An empty string means the library * is loaded statically. Malloc-ed. */ - char *packageName; /* Name of package prefix for the package, - * properly capitalized (first letter UC, - * others LC), no "_", as in "Net". + 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_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 + 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 package cannot be unloaded. */ - Tcl_PackageUnloadProc *safeUnloadProc; - /* Finalisation function to unload a package + * the library cannot be unloaded. */ + Tcl_LibraryUnloadProc *safeUnloadProc; + /* Finalization function to unload a library * from a safe interpreter. NULL means that - * the package cannot be unloaded. */ - int interpRefCount; /* How many times the package has been loaded + * the library cannot be unloaded. */ + int interpRefCount; /* How many times the library has been loaded * in trusted interpreters. */ - int safeInterpRefCount; /* How many times the package has been loaded + int safeInterpRefCount; /* How many times the library has been loaded * in safe interpreters. */ - struct LoadedPackage *nextPtr; - /* Next in list of all packages loaded into + struct LoadedLibrary *nextPtr; + /* Next in list of all libraries loaded into * this application process. NULL means end of * list. */ -} LoadedPackage; +} LoadedLibrary; /* * TCL_THREADS - * There is a global list of packages that is anchored at firstPackagePtr. + * There is a global list of libraries that is anchored at firstLibraryPtr. * Access to this list is governed by a mutex. */ -static LoadedPackage *firstPackagePtr = NULL; - /* First in list of all packages loaded into +static LoadedLibrary *firstLibraryPtr = NULL; + /* First in list of all libraries loaded into * this process. */ -TCL_DECLARE_MUTEX(packageMutex) +TCL_DECLARE_MUTEX(libraryMutex) /* - * The following structure represents a particular package that has been + * The following structure represents a particular library that has been * incorporated into a particular interpreter (by calling its initialization * function). There is a list of these structures for each interpreter, with * an AssocData value (key "load") for the interpreter that points to the - * first package (if any). + * first library (if any). */ -typedef struct InterpPackage { - LoadedPackage *pkgPtr; /* Points to detailed information about - * package. */ - struct InterpPackage *nextPtr; - /* Next package in this interpreter, or NULL +typedef struct InterpLibrary { + LoadedLibrary *libraryPtr; /* Points to detailed information about + * library. */ + struct InterpLibrary *nextPtr; + /* Next library in this interpreter, or NULL * for end of list. */ -} InterpPackage; +} InterpLibrary; /* * Prototypes for functions that are private to this file: */ -static void LoadCleanupProc(ClientData clientData, - Tcl_Interp *interp); +static void LoadCleanupProc(void *clientData, + Tcl_Interp *interp); +static int IsStatic (LoadedLibrary *libraryPtr); +static int UnloadLibrary(Tcl_Interp *interp, Tcl_Interp *target, + LoadedLibrary *library, int keepLibrary, + const char *fullFileName, int interpExiting); + + +static int +IsStatic (LoadedLibrary *libraryPtr) { + int res; + res = (libraryPtr->fileName[0] == '\0'); + return res; +} /* *---------------------------------------------------------------------- * * Tcl_LoadObjCmd -- @@ -119,29 +128,29 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Interp *target; - LoadedPackage *pkgPtr, *defaultPtr; - Tcl_DString pkgName, tmp, initName, safeInitName; + LoadedLibrary *libraryPtr, *defaultPtr; + Tcl_DString pfx, tmp, initName, safeInitName; Tcl_DString unloadName, safeUnloadName; - InterpPackage *ipFirstPtr, *ipPtr; + InterpLibrary *ipFirstPtr, *ipPtr; int code, namesMatch, filesMatch, offset; const char *symbols[2]; - Tcl_PackageInitProc *initProc; - const char *p, *fullFileName, *packageName; + Tcl_LibraryInitProc *initProc; + const char *p, *fullFileName, *prefix; Tcl_LoadHandle loadHandle; Tcl_UniChar ch = 0; size_t len; - int index, flags = 0; + int flags = 0; Tcl_Obj *const *savedobjv = objv; static const char *const options[] = { "-global", "-lazy", "--", NULL }; enum loadOptionsEnum { LOAD_GLOBAL, LOAD_LAZY, LOAD_LAST - }; + } index; while (objc > 2) { if (TclGetString(objv[1])[0] != '-') { break; } @@ -148,52 +157,52 @@ if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } ++objv; --objc; - if (LOAD_GLOBAL == (enum loadOptionsEnum) index) { + if (LOAD_GLOBAL == index) { flags |= TCL_LOAD_GLOBAL; - } else if (LOAD_LAZY == (enum loadOptionsEnum) index) { + } else if (LOAD_LAZY == index) { flags |= TCL_LOAD_LAZY; } else { break; } } if ((objc < 2) || (objc > 4)) { - Tcl_WrongNumArgs(interp, 1, savedobjv, "?-global? ?-lazy? ?--? fileName ?packageName? ?interp?"); + Tcl_WrongNumArgs(interp, 1, savedobjv, "?-global? ?-lazy? ?--? fileName ?prefix? ?interp?"); return TCL_ERROR; } if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) { return TCL_ERROR; } fullFileName = TclGetString(objv[1]); - Tcl_DStringInit(&pkgName); + Tcl_DStringInit(&pfx); Tcl_DStringInit(&initName); Tcl_DStringInit(&safeInitName); Tcl_DStringInit(&unloadName); Tcl_DStringInit(&safeUnloadName); Tcl_DStringInit(&tmp); - packageName = NULL; + prefix = NULL; if (objc >= 3) { - packageName = TclGetString(objv[2]); - if (packageName[0] == '\0') { - packageName = NULL; + prefix = TclGetString(objv[2]); + if (prefix[0] == '\0') { + prefix = NULL; } } - if ((fullFileName[0] == 0) && (packageName == NULL)) { + if ((fullFileName[0] == 0) && (prefix == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "must specify either file name or package name", -1)); + "must specify either file name or prefix", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOLIBRARY", - NULL); + (void *)NULL); code = TCL_ERROR; goto done; } /* - * Figure out which interpreter we're going to load the package into. + * Figure out which interpreter we're going to load the library into. */ target = interp; if (objc == 4) { const char *childIntName = TclGetString(objv[3]); @@ -204,230 +213,231 @@ goto done; } } /* - * Scan through the packages that are currently loaded to see if the - * package we want is already loaded. We'll use a loaded package if it + * Scan through the libraries that are currently loaded to see if the + * library we want is already loaded. We'll use a loaded library if it * meets any of the following conditions: * - Its name and file match the once we're looking for. * - Its file matches, and we weren't given a name. * - Its name matches, the file name was specified as empty, and there is - * only no statically loaded package with the same name. + * only no statically loaded library with the same prefix. */ - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); defaultPtr = NULL; - for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { - if (packageName == NULL) { + for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) { + if (prefix == NULL) { namesMatch = 0; } else { - TclDStringClear(&pkgName); - Tcl_DStringAppend(&pkgName, packageName, -1); + TclDStringClear(&pfx); + Tcl_DStringAppend(&pfx, prefix, -1); TclDStringClear(&tmp); - Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1); - Tcl_UtfToLower(Tcl_DStringValue(&pkgName)); - Tcl_UtfToLower(Tcl_DStringValue(&tmp)); + Tcl_DStringAppend(&tmp, libraryPtr->prefix, -1); if (strcmp(Tcl_DStringValue(&tmp), - Tcl_DStringValue(&pkgName)) == 0) { + Tcl_DStringValue(&pfx)) == 0) { namesMatch = 1; } else { namesMatch = 0; } } - TclDStringClear(&pkgName); + TclDStringClear(&pfx); - filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0); - if (filesMatch && (namesMatch || (packageName == NULL))) { + filesMatch = (strcmp(libraryPtr->fileName, fullFileName) == 0); + if (filesMatch && (namesMatch || (prefix == NULL))) { break; } if (namesMatch && (fullFileName[0] == 0)) { - defaultPtr = pkgPtr; + defaultPtr = libraryPtr; } if (filesMatch && !namesMatch && (fullFileName[0] != 0)) { /* - * Can't have two different packages loaded from the same file. + * Can't have two different libraries loaded from the same file. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "file \"%s\" is already loaded for package \"%s\"", - fullFileName, pkgPtr->packageName)); + "file \"%s\" is already loaded for prefix \"%s\"", + fullFileName, libraryPtr->prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", - "SPLITPERSONALITY", NULL); + "SPLITPERSONALITY", (void *)NULL); code = TCL_ERROR; - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); goto done; } } - Tcl_MutexUnlock(&packageMutex); - if (pkgPtr == NULL) { - pkgPtr = defaultPtr; + Tcl_MutexUnlock(&libraryMutex); + if (libraryPtr == NULL) { + libraryPtr = defaultPtr; } /* - * Scan through the list of packages already loaded in the target - * interpreter. If the package we want is already loaded there, then + * Scan through the list of libraries already loaded in the target + * interpreter. If the library we want is already loaded there, then * there's nothing for us to do. */ - if (pkgPtr != NULL) { - ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL); + if (libraryPtr != NULL) { + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - if (ipPtr->pkgPtr == pkgPtr) { + if (ipPtr->libraryPtr == libraryPtr) { code = TCL_OK; goto done; } } } - if (pkgPtr == NULL) { + if (libraryPtr == NULL) { /* * The desired file isn't currently loaded, so load it. It's an error - * if the desired package is a static one. + * if the desired library is a static one. */ if (fullFileName[0] == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "package \"%s\" isn't loaded statically", packageName)); + "no library with prefix \"%s\" is loaded statically", prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOTSTATIC", - NULL); + (void *)NULL); code = TCL_ERROR; goto done; } /* - * Figure out the module name if it wasn't provided explicitly. + * Figure out the prefix if it wasn't provided explicitly. */ - if (packageName != NULL) { - Tcl_DStringAppend(&pkgName, packageName, -1); + if (prefix != NULL) { + Tcl_DStringAppend(&pfx, prefix, -1); } else { - int retc; + Tcl_Obj *splitPtr, *pkgGuessPtr; + Tcl_Size pElements; + const char *pkgGuess; /* * Threading note - this call used to be protected by a mutex. */ - retc = TclGuessPackageName(fullFileName, &pkgName); - if (!retc) { - Tcl_Obj *splitPtr, *pkgGuessPtr; - int pElements; - const char *pkgGuess; - - /* - * The platform-specific code couldn't figure out the module - * name. Make a guess by taking the last element of the file - * name, stripping off any leading "lib", and then using all - * of the alphabetic and underline characters that follow - * that. - */ - - 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))); + /* + * 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", (void *)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 - * package name. + * prefix. */ - TclDStringAppendDString(&initName, &pkgName); + TclDStringAppendDString(&initName, &pfx); TclDStringAppendLiteral(&initName, "_Init"); - TclDStringAppendDString(&safeInitName, &pkgName); + TclDStringAppendDString(&safeInitName, &pfx); TclDStringAppendLiteral(&safeInitName, "_SafeInit"); - TclDStringAppendDString(&unloadName, &pkgName); + TclDStringAppendDString(&unloadName, &pfx); TclDStringAppendLiteral(&unloadName, "_Unload"); - TclDStringAppendDString(&safeUnloadName, &pkgName); + TclDStringAppendDString(&safeUnloadName, &pfx); TclDStringAppendLiteral(&safeUnloadName, "_SafeUnload"); /* - * Call platform-specific code to load the package and find the two + * Call platform-specific code to load the library and find the two * initialization functions. */ symbols[0] = Tcl_DStringValue(&initName); symbols[1] = NULL; - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); code = Tcl_LoadFile(interp, objv[1], symbols, flags, &initProc, &loadHandle); - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); if (code != TCL_OK) { goto done; } /* - * Create a new record to describe this package. + * Create a new record to describe this library. */ - pkgPtr = (LoadedPackage *)Tcl_Alloc(sizeof(LoadedPackage)); + libraryPtr = (LoadedLibrary *)Tcl_Alloc(sizeof(LoadedLibrary)); len = strlen(fullFileName) + 1; - pkgPtr->fileName = (char *)Tcl_Alloc(len); - memcpy(pkgPtr->fileName, fullFileName, len); - len = Tcl_DStringLength(&pkgName) + 1; - pkgPtr->packageName = (char *)Tcl_Alloc(len); - memcpy(pkgPtr->packageName, Tcl_DStringValue(&pkgName), len); - pkgPtr->loadHandle = loadHandle; - pkgPtr->initProc = initProc; - pkgPtr->safeInitProc = (Tcl_PackageInitProc *) + libraryPtr->fileName = (char *)Tcl_Alloc(len); + memcpy(libraryPtr->fileName, fullFileName, len); + len = Tcl_DStringLength(&pfx) + 1; + libraryPtr->prefix = (char *)Tcl_Alloc(len); + memcpy(libraryPtr->prefix, Tcl_DStringValue(&pfx), len); + libraryPtr->loadHandle = loadHandle; + libraryPtr->initProc = initProc; + libraryPtr->safeInitProc = (Tcl_LibraryInitProc *) Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&safeInitName)); - pkgPtr->unloadProc = (Tcl_PackageUnloadProc *) + libraryPtr->unloadProc = (Tcl_LibraryUnloadProc *) Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&unloadName)); - pkgPtr->safeUnloadProc = (Tcl_PackageUnloadProc *) + libraryPtr->safeUnloadProc = (Tcl_LibraryUnloadProc *) Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&safeUnloadName)); - pkgPtr->interpRefCount = 0; - pkgPtr->safeInterpRefCount = 0; + libraryPtr->interpRefCount = 0; + libraryPtr->safeInterpRefCount = 0; - Tcl_MutexLock(&packageMutex); - pkgPtr->nextPtr = firstPackagePtr; - firstPackagePtr = pkgPtr; - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexLock(&libraryMutex); + libraryPtr->nextPtr = firstLibraryPtr; + firstLibraryPtr = libraryPtr; + Tcl_MutexUnlock(&libraryMutex); /* * The Tcl_FindSymbol calls may have left a spurious error message in * the interpreter result. */ @@ -434,36 +444,36 @@ Tcl_ResetResult(interp); } /* - * Invoke the package's initialization function (either the normal one or + * Invoke the library's initialization function (either the normal one or * the safe one, depending on whether or not the interpreter is safe). */ if (Tcl_IsSafe(target)) { - if (pkgPtr->safeInitProc == NULL) { + if (libraryPtr->safeInitProc == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't use package in a safe interpreter: no" - " %s_SafeInit procedure", pkgPtr->packageName)); + "can't use library in a safe interpreter: no" + " %s_SafeInit procedure", libraryPtr->prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "UNSAFE", - NULL); + (void *)NULL); code = TCL_ERROR; goto done; } - code = pkgPtr->safeInitProc(target); + code = libraryPtr->safeInitProc(target); } else { - if (pkgPtr->initProc == NULL) { + if (libraryPtr->initProc == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't attach package to interpreter: no %s_Init procedure", - pkgPtr->packageName)); + "can't attach library to interpreter: no %s_Init procedure", + libraryPtr->prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "ENTRYPOINT", - NULL); + (void *)NULL); code = TCL_ERROR; goto done; } - code = pkgPtr->initProc(target); + code = libraryPtr->initProc(target); } /* * Test for whether the initialization failed. If so, transfer the error * from the target interpreter to the originating one. @@ -484,37 +494,37 @@ Tcl_TransferResult(target, code, interp); goto done; } /* - * Record the fact that the package has been loaded in the target + * Record the fact that the library has been loaded in the target * interpreter. * * Update the proper reference count. */ - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); if (Tcl_IsSafe(target)) { - pkgPtr->safeInterpRefCount++; + libraryPtr->safeInterpRefCount++; } else { - pkgPtr->interpRefCount++; + libraryPtr->interpRefCount++; } - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); /* - * Refetch ipFirstPtr: loading the package may have introduced additional - * static packages at the head of the linked list! + * Refetch ipFirstPtr: loading the library may have introduced additional + * static libraries at the head of the linked list! */ - ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL); - ipPtr = (InterpPackage *)Tcl_Alloc(sizeof(InterpPackage)); - ipPtr->pkgPtr = pkgPtr; + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); + ipPtr = (InterpLibrary *)Tcl_Alloc(sizeof(InterpLibrary)); + ipPtr->libraryPtr = libraryPtr; ipPtr->nextPtr = ipFirstPtr; Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipPtr); done: - Tcl_DStringFree(&pkgName); + Tcl_DStringFree(&pfx); Tcl_DStringFree(&initName); Tcl_DStringFree(&safeInitName); Tcl_DStringFree(&unloadName); Tcl_DStringFree(&safeUnloadName); Tcl_DStringFree(&tmp); @@ -524,11 +534,11 @@ /* *---------------------------------------------------------------------- * * Tcl_UnloadObjCmd -- * - * This function is invoked to process the "unload" Tcl command. See the + * Implements the the "unload" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * @@ -544,24 +554,22 @@ 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; + LoadedLibrary *libraryPtr; + Tcl_DString pfx, tmp; + InterpLibrary *ipFirstPtr, *ipPtr; + int i, code, complain = 1, keepLibrary = 0; const char *fullFileName = ""; - const char *packageName; + const char *prefix; static const char *const options[] = { "-nocomplain", "-keeplibrary", "--", NULL }; enum unloadOptionsEnum { UNLOAD_NOCOMPLAIN, UNLOAD_KEEPLIB, UNLOAD_LAST - }; + } index; for (i = 1; i < objc; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index) != TCL_OK) { fullFileName = TclGetString(objv[i]); @@ -580,11 +588,11 @@ Tcl_ResetResult(interp); break; } } - switch ((enum unloadOptionsEnum)index) { + switch (index) { case UNLOAD_NOCOMPLAIN: /* -nocomplain */ complain = 0; break; case UNLOAD_KEEPLIB: /* -keeplibrary */ keepLibrary = 1; @@ -595,39 +603,39 @@ } } endOfForLoop: if ((objc-i < 1) || (objc-i > 3)) { Tcl_WrongNumArgs(interp, 1, objv, - "?-switch ...? fileName ?packageName? ?interp?"); + "?-switch ...? fileName ?prefix? ?interp?"); return TCL_ERROR; } if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) { return TCL_ERROR; } fullFileName = TclGetString(objv[i]); - Tcl_DStringInit(&pkgName); + Tcl_DStringInit(&pfx); Tcl_DStringInit(&tmp); - packageName = NULL; + prefix = NULL; if (objc - i >= 2) { - packageName = TclGetString(objv[i+1]); - if (packageName[0] == '\0') { - packageName = NULL; + prefix = TclGetString(objv[i+1]); + if (prefix[0] == '\0') { + prefix = NULL; } } - if ((fullFileName[0] == 0) && (packageName == NULL)) { + if ((fullFileName[0] == 0) && (prefix == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "must specify either file name or package name", -1)); + "must specify either file name or prefix", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NOLIBRARY", - NULL); + (void *)NULL); code = TCL_ERROR; goto done; } /* - * Figure out which interpreter we're going to load the package into. + * Figure out which interpreter we're going to load the library into. */ target = interp; if (objc - i == 3) { const char *childIntName = TclGetString(objv[i + 2]); @@ -637,208 +645,286 @@ return TCL_ERROR; } } /* - * Scan through the packages that are currently loaded to see if the - * package we want is already loaded. We'll use a loaded package if it + * Scan through the libraries that are currently loaded to see if the + * library we want is already loaded. We'll use a loaded library if it * meets any of the following conditions: - * - Its name and file match the once we're looking for. - * - Its file matches, and we weren't given a name. - * - Its name matches, the file name was specified as empty, and there is - * only no statically loaded package with the same name. + * - Its prefix and file match the once we're looking for. + * - Its file matches, and we weren't given a prefix. + * - Its prefix matches, the file name was specified as empty, and there is + * no statically loaded library with the same prefix. */ - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); - defaultPtr = NULL; - for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { + for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) { int namesMatch, filesMatch; - if (packageName == NULL) { + if (prefix == NULL) { namesMatch = 0; } else { - TclDStringClear(&pkgName); - Tcl_DStringAppend(&pkgName, packageName, -1); + TclDStringClear(&pfx); + Tcl_DStringAppend(&pfx, prefix, -1); TclDStringClear(&tmp); - Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1); - Tcl_UtfToLower(Tcl_DStringValue(&pkgName)); - Tcl_UtfToLower(Tcl_DStringValue(&tmp)); + Tcl_DStringAppend(&tmp, libraryPtr->prefix, -1); if (strcmp(Tcl_DStringValue(&tmp), - Tcl_DStringValue(&pkgName)) == 0) { + Tcl_DStringValue(&pfx)) == 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; + TclDStringClear(&pfx); + + filesMatch = (strcmp(libraryPtr->fileName, fullFileName) == 0); + if (filesMatch && (namesMatch || (prefix == NULL))) { + break; } if (filesMatch && !namesMatch && (fullFileName[0] != 0)) { break; } } - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); if (fullFileName[0] == 0) { /* - * It's an error to try unload a static package. + * It's an error to try unload a static library. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "package \"%s\" is loaded statically and cannot be unloaded", - packageName)); + "library with prefix \"%s\" is loaded statically and cannot be unloaded", + prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "STATIC", - NULL); + (void *)NULL); code = TCL_ERROR; goto done; } - if (pkgPtr == NULL) { + if (libraryPtr == NULL) { /* * The DLL pointed by the provided filename has never been loaded. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" has never been loaded", fullFileName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NEVERLOADED", - NULL); + (void *)NULL); code = TCL_ERROR; goto done; } /* - * Scan through the list of packages already loaded in the target - * interpreter. If the package we want is already loaded there, then we + * Scan through the list of libraries already loaded in the target + * interpreter. If the library we want is already loaded there, then we * should proceed with unloading. */ code = TCL_ERROR; - if (pkgPtr != NULL) { - ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL); + if (libraryPtr != NULL) { + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - if (ipPtr->pkgPtr == pkgPtr) { + if (ipPtr->libraryPtr == libraryPtr) { code = TCL_OK; break; } } } if (code != TCL_OK) { /* - * The package has not been loaded in this interpreter. + * The library has not been loaded in this interpreter. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" has never been loaded in this interpreter", fullFileName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NEVERLOADED", - NULL); - 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 + (void *)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", + (void *)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", + (void *)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. */ - 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 (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 executed fine. Examine the reference count to see - * if we unload the DLL. + * The unload function was called succesfully. */ - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); if (Tcl_IsSafe(target)) { - pkgPtr->safeInterpRefCount--; + libraryPtr->safeInterpRefCount--; /* * Do not let counter get negative. */ - if (pkgPtr->safeInterpRefCount < 0) { - pkgPtr->safeInterpRefCount = 0; + if (libraryPtr->safeInterpRefCount < 0) { + libraryPtr->safeInterpRefCount = 0; } } else { - pkgPtr->interpRefCount--; + libraryPtr->interpRefCount--; /* * Do not let counter get negative. */ - if (pkgPtr->interpRefCount < 0) { - pkgPtr->interpRefCount = 0; + if (libraryPtr->interpRefCount < 0) { + libraryPtr->interpRefCount = 0; } } - trustedRefCount = pkgPtr->interpRefCount; - safeRefCount = pkgPtr->safeInterpRefCount; - Tcl_MutexUnlock(&packageMutex); + trustedRefCount = libraryPtr->interpRefCount; + safeRefCount = libraryPtr->safeInterpRefCount; + Tcl_MutexUnlock(&libraryMutex); code = TCL_OK; - if (pkgPtr->safeInterpRefCount <= 0 && pkgPtr->interpRefCount <= 0 - && !keepLibrary) { + if (libraryPtr->safeInterpRefCount <= 0 && libraryPtr->interpRefCount <= 0 + && (unloadProc != NULL) && !keepLibrary) { /* * Unload the shared library from the application memory... */ #if defined(TCL_UNLOAD_DLLS) || defined(_WIN32) @@ -847,56 +933,34 @@ * 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); + 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 @@ -908,202 +972,184 @@ code = TCL_ERROR; #endif } done: - Tcl_DStringFree(&pkgName); - Tcl_DStringFree(&tmp); - if (!complain && (code != TCL_OK)) { - code = TCL_OK; - Tcl_ResetResult(interp); - } return code; } /* *---------------------------------------------------------------------- * - * Tcl_StaticPackage -- + * Tcl_StaticLibrary -- * - * This function is invoked to indicate that a particular package has + * This function is invoked to indicate that a particular library has * been linked statically with an application. * * Results: * None. * * Side effects: - * Once this function completes, the package becomes loadable via the + * Once this function completes, the library becomes loadable via the * "load" command with an empty file name. * *---------------------------------------------------------------------- */ void -Tcl_StaticPackage( - Tcl_Interp *interp, /* If not NULL, it means that the package has +Tcl_StaticLibrary( + Tcl_Interp *interp, /* If not NULL, it means that the library has * already been loaded into the given * interpreter by calling the appropriate init * proc. */ - const char *pkgName, /* Name of package (must be properly - * 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 + 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. */ { - LoadedPackage *pkgPtr; - InterpPackage *ipPtr, *ipFirstPtr; + LoadedLibrary *libraryPtr; + InterpLibrary *ipPtr, *ipFirstPtr; /* - * Check to see if someone else has already reported this package as + * Check to see if someone else has already reported this library as * statically loaded in the process. */ - Tcl_MutexLock(&packageMutex); - for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { - if ((pkgPtr->initProc == initProc) - && (pkgPtr->safeInitProc == safeInitProc) - && (strcmp(pkgPtr->packageName, pkgName) == 0)) { + Tcl_MutexLock(&libraryMutex); + for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) { + if ((libraryPtr->initProc == initProc) + && (libraryPtr->safeInitProc == safeInitProc) + && (strcmp(libraryPtr->prefix, prefix) == 0)) { break; } } - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); /* - * If the package is not yet recorded as being loaded statically, add it + * If the library is not yet recorded as being loaded statically, add it * to the list now. */ - if (pkgPtr == NULL) { - pkgPtr = (LoadedPackage *)Tcl_Alloc(sizeof(LoadedPackage)); - pkgPtr->fileName = (char *)Tcl_Alloc(1); - pkgPtr->fileName[0] = 0; - pkgPtr->packageName = (char *)Tcl_Alloc(strlen(pkgName) + 1); - strcpy(pkgPtr->packageName, pkgName); - pkgPtr->loadHandle = NULL; - pkgPtr->initProc = initProc; - pkgPtr->safeInitProc = safeInitProc; - Tcl_MutexLock(&packageMutex); - pkgPtr->nextPtr = firstPackagePtr; - firstPackagePtr = pkgPtr; - Tcl_MutexUnlock(&packageMutex); + if (libraryPtr == NULL) { + libraryPtr = (LoadedLibrary *)Tcl_Alloc(sizeof(LoadedLibrary)); + libraryPtr->fileName = (char *)Tcl_Alloc(1); + libraryPtr->fileName[0] = 0; + libraryPtr->prefix = (char *)Tcl_Alloc(strlen(prefix) + 1); + strcpy(libraryPtr->prefix, prefix); + libraryPtr->loadHandle = NULL; + libraryPtr->initProc = initProc; + libraryPtr->safeInitProc = safeInitProc; + libraryPtr->unloadProc = NULL; + libraryPtr->safeUnloadProc = NULL; + Tcl_MutexLock(&libraryMutex); + libraryPtr->nextPtr = firstLibraryPtr; + firstLibraryPtr = libraryPtr; + Tcl_MutexUnlock(&libraryMutex); } if (interp != NULL) { /* - * If we're loading the package into an interpreter, determine whether + * If we're loading the library into an interpreter, determine whether * it's already loaded. */ - ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(interp, "tclLoad", NULL); + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(interp, "tclLoad", NULL); for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - if (ipPtr->pkgPtr == pkgPtr) { + if (ipPtr->libraryPtr == libraryPtr) { return; } } /* - * Package isn't loaded in the current interp yet. Mark it as now being + * Library isn't loaded in the current interp yet. Mark it as now being * loaded. */ - ipPtr = (InterpPackage *)Tcl_Alloc(sizeof(InterpPackage)); - ipPtr->pkgPtr = pkgPtr; + ipPtr = (InterpLibrary *)Tcl_Alloc(sizeof(InterpLibrary)); + ipPtr->libraryPtr = libraryPtr; ipPtr->nextPtr = ipFirstPtr; Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc, ipPtr); } } /* *---------------------------------------------------------------------- * - * TclGetLoadedPackages, TclGetLoadedPackagesEx -- + * TclGetLoadedLibraries -- * * This function returns information about all of the files that are * loaded (either in a particular interpreter, or for all interpreters). * * Results: * The return value is a standard Tcl completion code. If successful, a * list of lists is placed in the interp's result. Each sublist * corresponds to one loaded file; its first element is the name of the * file (or an empty string for something that's statically loaded) and - * the second element is the name of the package in that file. + * the second element is the prefix of the library in that file. * * Side effects: * None. * *---------------------------------------------------------------------- */ int -TclGetLoadedPackages( - 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( +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 *packageName) /* Package name or NULL. If NULL, return info - * for all packages. + const char *prefix) /* Prefix or NULL. If NULL, return info + * for all prefixes. */ { Tcl_Interp *target; - LoadedPackage *pkgPtr; - InterpPackage *ipPtr; + LoadedLibrary *libraryPtr; + InterpLibrary *ipPtr; Tcl_Obj *resultObj, *pkgDesc[2]; if (targetName == NULL) { TclNewObj(resultObj); - Tcl_MutexLock(&packageMutex); - for (pkgPtr = firstPackagePtr; pkgPtr != NULL; - pkgPtr = pkgPtr->nextPtr) { - pkgDesc[0] = Tcl_NewStringObj(pkgPtr->fileName, -1); - pkgDesc[1] = Tcl_NewStringObj(pkgPtr->packageName, -1); + Tcl_MutexLock(&libraryMutex); + for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; + libraryPtr = libraryPtr->nextPtr) { + pkgDesc[0] = Tcl_NewStringObj(libraryPtr->fileName, -1); + pkgDesc[1] = Tcl_NewStringObj(libraryPtr->prefix, -1); Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewListObj(2, pkgDesc)); } - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); Tcl_SetObjResult(interp, resultObj); return TCL_OK; } target = Tcl_GetChild(interp, targetName); if (target == NULL) { return TCL_ERROR; } - ipPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL); + ipPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); /* - * Return information about all of the available packages. + * Return information about all of the available libraries. */ - if (packageName) { + if (prefix) { resultObj = NULL; for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - pkgPtr = ipPtr->pkgPtr; + libraryPtr = ipPtr->libraryPtr; - if (!strcmp(packageName, pkgPtr->packageName)) { - resultObj = Tcl_NewStringObj(pkgPtr->fileName, -1); + if (!strcmp(prefix, libraryPtr->prefix)) { + resultObj = Tcl_NewStringObj(libraryPtr->fileName, -1); break; } } if (resultObj) { @@ -1111,19 +1157,19 @@ } return TCL_OK; } /* - * Return information about only the packages that are loaded in a given + * Return information about only the libraries that are loaded in a given * interpreter. */ TclNewObj(resultObj); for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - pkgPtr = ipPtr->pkgPtr; - pkgDesc[0] = Tcl_NewStringObj(pkgPtr->fileName, -1); - pkgDesc[1] = Tcl_NewStringObj(pkgPtr->packageName, -1); + libraryPtr = ipPtr->libraryPtr; + pkgDesc[0] = Tcl_NewStringObj(libraryPtr->fileName, -1); + pkgDesc[1] = Tcl_NewStringObj(libraryPtr->prefix, -1); Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewListObj(2, pkgDesc)); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } @@ -1131,46 +1177,49 @@ /* *---------------------------------------------------------------------- * * LoadCleanupProc -- * - * This function is called to delete all of the InterpPackage structures + * This function is called to delete all of the InterpLibrary structures * for an interpreter when the interpreter is deleted. It gets invoked * via the Tcl AssocData mechanism. * * Results: * None. * * Side effects: - * Storage for all of the InterpPackage functions for interp get deleted. + * Storage for all of the InterpLibrary functions for interp get deleted. * *---------------------------------------------------------------------- */ static void LoadCleanupProc( - ClientData clientData, /* Pointer to first InterpPackage structure - * for interp. */ - TCL_UNUSED(Tcl_Interp *)) -{ - InterpPackage *ipPtr, *nextPtr; - - ipPtr = (InterpPackage *)clientData; - while (ipPtr != NULL) { - nextPtr = ipPtr->nextPtr; - Tcl_Free(ipPtr); - ipPtr = nextPtr; + 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 LoadedPackage structures. + * all of the LoadedLibrary structures. * * Results: * None. * * Side effects: @@ -1180,39 +1229,39 @@ */ void TclFinalizeLoad(void) { - LoadedPackage *pkgPtr; + LoadedLibrary *libraryPtr; /* * No synchronization here because there should just be one thread alive - * at this point. Logically, packageMutex should be grabbed at this point, + * at this point. Logically, libraryMutex should be grabbed at this point, * but the Mutexes get finalized before the call to this routine. The only * subsystem left alive at this point is the memory allocator. */ - while (firstPackagePtr != NULL) { - pkgPtr = firstPackagePtr; - firstPackagePtr = pkgPtr->nextPtr; + while (firstLibraryPtr != NULL) { + libraryPtr = firstLibraryPtr; + firstLibraryPtr = libraryPtr->nextPtr; #if defined(TCL_UNLOAD_DLLS) || defined(_WIN32) /* * Some Unix dlls are poorly behaved - registering things like atexit * calls that can't be unregistered. If you unload such dlls, you get * a core on exit because it wants to call a function in the dll after * it has been unloaded. */ - if (pkgPtr->fileName[0] != '\0') { - Tcl_FSUnloadFile(NULL, pkgPtr->loadHandle); + if (!IsStatic(libraryPtr)) { + Tcl_FSUnloadFile(NULL, libraryPtr->loadHandle); } #endif - Tcl_Free(pkgPtr->fileName); - Tcl_Free(pkgPtr->packageName); - Tcl_Free(pkgPtr); + Tcl_Free(libraryPtr->fileName); + Tcl_Free(libraryPtr->prefix); + Tcl_Free(libraryPtr); } } /* * Local Variables: Index: generic/tclLoadNone.c ================================================================== --- generic/tclLoadNone.c +++ generic/tclLoadNone.c @@ -2,11 +2,11 @@ * tclLoadNone.c -- * * This procedure provides a version of the TclpDlopen for use in * systems that don't support dynamic loading; it just returns an error. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright © 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -50,40 +50,10 @@ "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. @@ -91,27 +61,25 @@ #ifdef TCL_LOAD_FROM_MEMORY MODULE_SCOPE void * TclpLoadMemoryGetBuffer( - Tcl_Interp *interp, /* Dummy: unused by this implementation */ - int size) /* Dummy: unused by this implementation */ + TCL_UNUSED(Tcl_Interp *), + TCL_UNUSED(int)) { 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 */ + 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)); } Index: generic/tclMain.c ================================================================== --- generic/tclMain.c +++ generic/tclMain.c @@ -6,13 +6,13 @@ * Tcl-based applications. It can be used as-is for many applications, * just by supplying a different appInitProc function for each specific * application. Or, it can be used as a template for creating new main * programs for Tcl applications. * - * Copyright (c) 1988-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2000 Ajuba Solutions. + * Copyright © 1988-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2000 Ajuba Solutions. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -26,11 +26,12 @@ /* * The default prompt used when the user has not overridden it. */ -#define DEFAULT_PRIMARY_PROMPT "% " +static const char DEFAULT_PRIMARY_PROMPT[] = "% "; +static const char ENCODING_ERROR[] = "\n\t(encoding error in stderr)"; /* * This file can be compiled on Windows in UNICODE mode, as well as on all * other platforms using the native encoding. This is done by using the normal * Windows functions like _tcscmp, but on platforms which don't have @@ -41,36 +42,31 @@ # define TCHAR char # define TEXT(arg) arg # define _tcscmp strcmp #endif -static Tcl_Obj * +static inline Tcl_Obj * NewNativeObj( TCHAR *string) { Tcl_DString ds; #ifdef UNICODE Tcl_DStringInit(&ds); Tcl_WCharToUtfDString(string, -1, &ds); #else - Tcl_ExternalToUtfDString(NULL, (char *)string, -1, &ds); + (void)Tcl_ExternalToUtfDString(NULL, (char *)string, -1, &ds); #endif - return TclDStringToObj(&ds); + return Tcl_DStringToObj(&ds); } /* * Declarations for various library functions and variables (don't want to * include tclPort.h here, because people might copy this file out of the Tcl * source directory to make their own modified versions). */ -#if defined _MSC_VER && _MSC_VER < 1900 -/* isatty is always defined on MSVC 14.0, but not necessarily as CRTIMPORT. */ -extern CRTIMPORT int isatty(int fd); -#endif - /* * The thread-local variables for this file's functions. */ typedef struct { @@ -113,12 +109,12 @@ * Forward declarations for functions defined later in this file. */ MODULE_SCOPE Tcl_MainLoopProc *TclGetMainLoop(void); static void Prompt(Tcl_Interp *interp, InteractiveState *isPtr); -static void StdinProc(ClientData clientData, int mask); -static void FreeMainInterp(ClientData clientData); +static void StdinProc(void *clientData, int mask); +static void FreeMainInterp(void *clientData); #if !defined(_WIN32) || defined(UNICODE) && !defined(TCL_ASCII_MAIN) static Tcl_ThreadDataKey dataKey; /* @@ -252,11 +248,13 @@ if (c != NULL) { Tcl_CloseEx(NULL, c, 0); if (Tcl_EvalFile(interp, fullName) != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan) { - Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); + if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) { + Tcl_WriteChars(chan, ENCODING_ERROR, -1); + } Tcl_WriteChars(chan, "\n", 1); } } } } @@ -283,27 +281,34 @@ *---------------------------------------------------------------------- */ TCL_NORETURN void Tcl_MainEx( - int argc, /* Number of arguments. */ + Tcl_Size argc, /* Number of arguments. */ TCHAR **argv, /* Array of argument strings. */ Tcl_AppInitProc *appInitProc, /* Application-specific initialization * function to call after most initialization * but before starting to execute commands. */ Tcl_Interp *interp) { + Tcl_Size i=0; /* argv[i] index */ Tcl_Obj *path, *resultPtr, *argvPtr, *appName; const char *encodingName = NULL; int code, exitCode = 0; Tcl_MainLoopProc *mainLoopProc; Tcl_Channel chan; InteractiveState is; TclpSetInitialEncodings(); - TclpFindExecutable((const char *)argv[0]); + 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; @@ -321,40 +326,41 @@ * -encoding ENCODING FILENAME * or like * FILENAME */ - if ((argc > 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1])) + /* 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]), TclGetString(value)); Tcl_DecrRefCount(value); argc -= 3; - argv += 3; - } else if ((argc > 1) && ('-' != argv[1][0])) { + i += 3; + } else if ((argc >= 1) && ('-' != argv[1][0])) { Tcl_SetStartupScript(NewNativeObj(argv[1]), NULL); argc--; - argv++; + i++; } } path = Tcl_GetStartupScript(&encodingName); - if (path == NULL) { + if (path != NULL) { + appName = path; + } else if (argv[0]) { appName = NewNativeObj(argv[0]); } else { - appName = path; + appName = Tcl_NewStringObj("tclsh", -1); } Tcl_SetVar2Ex(interp, "argv0", NULL, appName, TCL_GLOBAL_ONLY); - argc--; - argv++; Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewWideIntObj(argc), TCL_GLOBAL_ONLY); argvPtr = Tcl_NewListObj(0, NULL); while (argc--) { - Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++)); + Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(argv[i++])); } Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY); /* * Set the "tcl_interactive" variable. @@ -372,11 +378,13 @@ if (appInitProc(interp) != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan) { Tcl_WriteChars(chan, "application-specific initialization failed: ", -1); - Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); + if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) { + Tcl_WriteChars(chan, ENCODING_ERROR, -1); + } Tcl_WriteChars(chan, "\n", 1); } } if (Tcl_InterpDeleted(interp)) { goto done; @@ -412,11 +420,13 @@ Tcl_IncrRefCount(keyPtr); Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr); Tcl_DecrRefCount(keyPtr); if (valuePtr) { - Tcl_WriteObj(chan, valuePtr); + if (Tcl_WriteObj(chan, valuePtr) < 0) { + Tcl_WriteChars(chan, ENCODING_ERROR, -1); + } } Tcl_WriteChars(chan, "\n", 1); Tcl_DecrRefCount(options); } exitCode = 1; @@ -449,11 +459,11 @@ Tcl_LinkVar(interp, "tcl_interactive", &is.tty, TCL_LINK_BOOLEAN); is.input = Tcl_GetStdChannel(TCL_STDIN); while ((is.input != NULL) && !Tcl_InterpDeleted(interp)) { mainLoopProc = TclGetMainLoop(); if (mainLoopProc == NULL) { - size_t length; + Tcl_Size length; if (is.tty) { Prompt(interp, &is); if (Tcl_InterpDeleted(interp)) { break; @@ -470,11 +480,11 @@ Tcl_DecrRefCount(is.commandPtr); is.commandPtr = Tcl_DuplicateObj(is.commandPtr); Tcl_IncrRefCount(is.commandPtr); } length = Tcl_GetsObj(is.input, is.commandPtr); - if (length == TCL_INDEX_NONE) { + if (length < 0) { if (Tcl_InputBlocked(is.input)) { /* * This can only happen if stdin has been set to * non-blocking. In that case cycle back and try again. * This sets up a tight polling loop (since we have no @@ -514,11 +524,11 @@ /* * The final newline is syntactically redundant, and causes some * error messages troubles deeper in, so lop it back off. */ - (void)TclGetStringFromObj(is.commandPtr, &length); + (void)Tcl_GetStringFromObj(is.commandPtr, &length); Tcl_SetObjLength(is.commandPtr, --length); code = Tcl_RecordAndEvalObj(interp, is.commandPtr, TCL_EVAL_GLOBAL); is.input = Tcl_GetStdChannel(TCL_STDIN); Tcl_DecrRefCount(is.commandPtr); @@ -525,20 +535,24 @@ TclNewObj(is.commandPtr); Tcl_IncrRefCount(is.commandPtr); if (code != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan) { - Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); + if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) { + Tcl_WriteChars(chan, ENCODING_ERROR, -1); + } Tcl_WriteChars(chan, "\n", 1); } } else if (is.tty) { resultPtr = Tcl_GetObjResult(interp); Tcl_IncrRefCount(resultPtr); - (void)TclGetStringFromObj(resultPtr, &length); + (void)Tcl_GetStringFromObj(resultPtr, &length); chan = Tcl_GetStdChannel(TCL_STDOUT); if ((length > 0) && chan) { - Tcl_WriteObj(chan, resultPtr); + if (Tcl_WriteObj(chan, resultPtr) < 0) { + Tcl_WriteChars(chan, ENCODING_ERROR, -1); + } Tcl_WriteChars(chan, "\n", 1); } Tcl_DecrRefCount(resultPtr); } } else { /* (mainLoopProc != NULL) */ @@ -731,15 +745,15 @@ *---------------------------------------------------------------------- */ static void StdinProc( - ClientData clientData, /* The state of interactive cmd line */ + void *clientData, /* The state of interactive cmd line */ TCL_UNUSED(int) /*mask*/) { int code; - size_t length; + Tcl_Size length; InteractiveState *isPtr = (InteractiveState *)clientData; Tcl_Channel chan = isPtr->input; Tcl_Obj *commandPtr = isPtr->commandPtr; Tcl_Interp *interp = isPtr->interp; @@ -747,11 +761,11 @@ Tcl_DecrRefCount(commandPtr); commandPtr = Tcl_DuplicateObj(commandPtr); Tcl_IncrRefCount(commandPtr); } length = Tcl_GetsObj(chan, commandPtr); - if (length == TCL_INDEX_NONE) { + if (length < 0) { if (Tcl_InputBlocked(chan)) { return; } if (isPtr->tty) { /* @@ -775,11 +789,11 @@ if (!TclObjCommandComplete(commandPtr)) { isPtr->prompt = PROMPT_CONTINUE; goto prompt; } isPtr->prompt = PROMPT_START; - (void)TclGetStringFromObj(commandPtr, &length); + (void)Tcl_GetStringFromObj(commandPtr, &length); Tcl_SetObjLength(commandPtr, --length); /* * Disable the stdin channel handler while evaluating the command; * otherwise if the command re-enters the event loop we might process @@ -799,21 +813,25 @@ } if (code != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan != NULL) { - Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); + if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) { + Tcl_WriteChars(chan, ENCODING_ERROR, -1); + } Tcl_WriteChars(chan, "\n", 1); } } else if (isPtr->tty) { Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); chan = Tcl_GetStdChannel(TCL_STDOUT); Tcl_IncrRefCount(resultPtr); - (void)TclGetStringFromObj(resultPtr, &length); + (void)Tcl_GetStringFromObj(resultPtr, &length); if ((length > 0) && (chan != NULL)) { - Tcl_WriteObj(chan, resultPtr); + if (Tcl_WriteObj(chan, resultPtr) < 0) { + Tcl_WriteChars(chan, ENCODING_ERROR, -1); + } Tcl_WriteChars(chan, "\n", 1); } Tcl_DecrRefCount(resultPtr); } @@ -870,21 +888,23 @@ defaultPrompt: if (isPtr->prompt == PROMPT_START) { chan = Tcl_GetStdChannel(TCL_STDOUT); if (chan != NULL) { Tcl_WriteChars(chan, DEFAULT_PRIMARY_PROMPT, - strlen(DEFAULT_PRIMARY_PROMPT)); + sizeof(DEFAULT_PRIMARY_PROMPT) - 1); } } } else { code = Tcl_EvalObjEx(interp, promptCmdPtr, TCL_EVAL_GLOBAL); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (script that generates prompt)"); chan = Tcl_GetStdChannel(TCL_STDERR); if (chan != NULL) { - Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); + if (Tcl_WriteObj(chan, Tcl_GetObjResult(interp)) < 0) { + Tcl_WriteChars(chan, ENCODING_ERROR, -1); + } Tcl_WriteChars(chan, "\n", 1); } goto defaultPrompt; } } @@ -907,11 +927,11 @@ *---------------------------------------------------------------------- */ static void FreeMainInterp( - ClientData clientData) + void *clientData) { Tcl_Interp *interp = (Tcl_Interp *)clientData; /*if (TclInExit()) return;*/ Index: generic/tclNamesp.c ================================================================== --- generic/tclNamesp.c +++ generic/tclNamesp.c @@ -5,15 +5,15 @@ * commands and global variables. The global :: namespace is the * traditional Tcl "global" scope. Other namespaces are created as * children of the global namespace. These other namespaces contain * special-purpose commands and variables for packages. * - * Copyright (c) 1993-1997 Lucent Technologies. - * Copyright (c) 1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. - * Copyright (c) 2002-2005 Donal K. Fellows. - * Copyright (c) 2006 Neil Madden. + * Copyright © 1993-1997 Lucent Technologies. + * Copyright © 1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. + * Copyright © 2002-2005 Donal K. Fellows. + * Copyright © 2006 Neil Madden. * Contributions from Don Porter, NIST, 2007. (not subject to US copyright) * * Originally implemented by * Michael J. McLennan * Bell Labs Innovations for Lucent Technologies @@ -69,30 +69,30 @@ /* * Declarations for functions local to this file: */ -static void DeleteImportedCmd(ClientData clientData); +static void DeleteImportedCmd(void *clientData); static int DoImport(Tcl_Interp *interp, Namespace *nsPtr, Tcl_HashEntry *hPtr, const char *cmdName, const char *pattern, Namespace *importNsPtr, int allowOverwrite); static void DupNsNameInternalRep(Tcl_Obj *objPtr,Tcl_Obj *copyPtr); -static char * ErrorCodeRead(ClientData clientData,Tcl_Interp *interp, +static char * ErrorCodeRead(void *clientData,Tcl_Interp *interp, const char *name1, const char *name2, int flags); -static char * ErrorInfoRead(ClientData clientData,Tcl_Interp *interp, +static char * ErrorInfoRead(void *clientData,Tcl_Interp *interp, const char *name1, const char *name2, int flags); -static char * EstablishErrorCodeTraces(ClientData clientData, +static char * EstablishErrorCodeTraces(void *clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); -static char * EstablishErrorInfoTraces(ClientData clientData, +static char * EstablishErrorInfoTraces(void *clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); static void FreeNsNameInternalRep(Tcl_Obj *objPtr); static int GetNamespaceFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr); -static int InvokeImportedNRCmd(ClientData clientData, +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; @@ -128,26 +128,27 @@ static const Tcl_ObjType nsNameType = { "nsName", /* the type's name */ FreeNsNameInternalRep, /* freeIntRepProc */ DupNsNameInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetNsNameFromAny /* setFromAnyProc */ + SetNsNameFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; -#define NsNameSetIntRep(objPtr, nnPtr) \ +#define NsNameSetInternalRep(objPtr, nnPtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ (nnPtr)->refCount++; \ ir.twoPtrValue.ptr1 = (nnPtr); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreIntRep((objPtr), &nsNameType, &ir); \ + Tcl_StoreInternalRep((objPtr), &nsNameType, &ir); \ } while (0) -#define NsNameGetIntRep(objPtr, nnPtr) \ +#define NsNameGetInternalRep(objPtr, nnPtr) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), &nsNameType); \ + 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 @@ -304,11 +305,11 @@ } else { nsPtr = (Namespace *) namespacePtr; /* * TODO: Examine whether it would be better to guard based on NS_DYING - * or NS_KILLED. It appears that these are not tested because they can + * or NS_TEARDOWN. It appears that these are not tested because they can * be set in a global interp that has been [namespace delete]d, but * which never really completely goes away because of lingering global * things like ::errorInfo and [::unknown] and hidden commands. * Review of those designs might permit stricter checking here. */ @@ -324,11 +325,11 @@ framePtr->objc = 0; framePtr->objv = NULL; framePtr->callerPtr = iPtr->framePtr; framePtr->callerVarPtr = iPtr->varFramePtr; if (iPtr->varFramePtr != NULL) { - framePtr->level = (iPtr->varFramePtr->level + 1); + framePtr->level = iPtr->varFramePtr->level + 1U; } else { framePtr->level = 0; } framePtr->procPtr = NULL; /* no called procedure */ framePtr->varTablePtr = NULL; /* and no local variables */ @@ -407,17 +408,19 @@ * is "dying" and there are no more active call frames, call * Tcl_DeleteNamespace to destroy it. */ nsPtr = framePtr->nsPtr; - if ((--nsPtr->activationCount <= (unsigned)(nsPtr == iPtr->globalNsPtr)) + if ((--nsPtr->activationCount <= (nsPtr == iPtr->globalNsPtr)) && (nsPtr->flags & NS_DYING)) { Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr); } framePtr->nsPtr = NULL; if (framePtr->tailcallPtr) { + /* Reusing the existing reference count from framePtr->tailcallPtr, so + * no need to Tcl_IncrRefCount(framePtr->tailcallPtr)*/ TclSetTailcall(interp, framePtr->tailcallPtr); } } /* @@ -490,11 +493,11 @@ *---------------------------------------------------------------------- */ static char * EstablishErrorCodeTraces( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, TCL_UNUSED(const char *) /*name1*/, TCL_UNUSED(const char *) /*name2*/, TCL_UNUSED(int) /*flags*/) { @@ -522,11 +525,11 @@ *---------------------------------------------------------------------- */ static char * ErrorCodeRead( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, TCL_UNUSED(const char *) /*name1*/, TCL_UNUSED(const char *) /*name2*/, TCL_UNUSED(int) /*flags*/) { @@ -564,11 +567,11 @@ *---------------------------------------------------------------------- */ static char * EstablishErrorInfoTraces( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, TCL_UNUSED(const char *) /*name1*/, TCL_UNUSED(const char *) /*name2*/, TCL_UNUSED(int) /*flags*/) { @@ -596,11 +599,11 @@ *---------------------------------------------------------------------- */ static char * ErrorInfoRead( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, TCL_UNUSED(const char *) /*name1*/, TCL_UNUSED(const char *) /*name2*/, TCL_UNUSED(int) /*flags*/) { @@ -648,11 +651,11 @@ * being created. Also used for error * reporting. */ const char *name, /* Name for the new namespace. May be a * qualified name with names of ancestor * namespaces separated by "::"s. */ - ClientData clientData, /* One-word value to store with namespace. */ + void *clientData, /* One-word value to store with namespace. */ Tcl_NamespaceDeleteProc *deleteProc) /* Function called to delete client data when * the namespace is deleted. NULL if no * function should be called. */ { @@ -663,11 +666,11 @@ const char *simpleName; Tcl_HashEntry *entryPtr; Tcl_DString buffer1, buffer2; Tcl_DString *namePtr, *buffPtr; int newEntry; - size_t nameLen; + Tcl_Size nameLen; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); const char *nameStr; Tcl_DString tmpBuffer; Tcl_DStringInit(&tmpBuffer); @@ -712,11 +715,11 @@ 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); + "CREATEGLOBAL", (void *)NULL); Tcl_DStringFree(&tmpBuffer); return NULL; } /* @@ -751,11 +754,11 @@ #endif ) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create namespace \"%s\": already exists", name)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NAMESPACE", - "CREATEEXISTING", NULL); + "CREATEEXISTING", (void *)NULL); Tcl_DStringFree(&tmpBuffer); return NULL; } /* @@ -782,13 +785,11 @@ nsPtr->flags = 0; nsPtr->activationCount = 0; nsPtr->refCount = 0; Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS); TclInitVarHashTable(&nsPtr->varTable, nsPtr); - nsPtr->exportArrayPtr = NULL; - nsPtr->numExportPatterns = 0; - nsPtr->maxExportPatterns = 0; + nsPtr->exportPatternList = NULL; nsPtr->cmdRefEpoch = 0; nsPtr->resolverEpoch = 0; nsPtr->cmdResProc = NULL; nsPtr->varResProc = NULL; nsPtr->compiledVarResProc = NULL; @@ -984,27 +985,28 @@ 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 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 > (unsigned)(nsPtr == globalNsPtr)) { + if (nsPtr->activationCount > (nsPtr == globalNsPtr)) { nsPtr->flags |= NS_DYING; if (nsPtr->parentPtr != NULL) { entryPtr = Tcl_FindHashEntry( TclGetNamespaceChildTable((Tcl_Namespace *) nsPtr->parentPtr), nsPtr->name); @@ -1011,20 +1013,20 @@ if (entryPtr != NULL) { Tcl_DeleteHashEntry(entryPtr); } } nsPtr->parentPtr = NULL; - } else if (!(nsPtr->flags & NS_KILLED)) { + } else if (!(nsPtr->flags & NS_TEARDOWN)) { /* * Delete the namespace and everything in it. If this is the global * namespace, then clear it but don't free its storage unless the - * interpreter is being torn down. Set the NS_KILLED flag to avoid + * interpreter is being torn down. Set the NS_TEARDOWN flag to avoid * recursive calls here - if the namespace is really in the process of * being deleted, ignore any second call. */ - nsPtr->flags |= (NS_DYING|NS_KILLED); + nsPtr->flags |= (NS_DYING|NS_TEARDOWN); TclTeardownNamespace(nsPtr); if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) { /* @@ -1058,11 +1060,11 @@ /* * We didn't really kill it, so remove the KILLED marks, so it can * get killed later, avoiding mem leaks. */ - nsPtr->flags &= ~(NS_DYING|NS_KILLED); + nsPtr->flags &= ~(NS_DYING|NS_TEARDOWN); } } TclNsDecrRefCount(nsPtr); } @@ -1070,10 +1072,88 @@ 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; + Tcl_Size 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) { + Tcl_Size 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) { + Tcl_Size 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 -- @@ -1101,11 +1181,11 @@ * and unlinked from its parent. */ { Interp *iPtr = (Interp *) nsPtr->interp; Tcl_HashEntry *entryPtr; Tcl_HashSearch search; - size_t i; + Tcl_Size i; /* * Start by destroying the namespace's variable table, since variables * might trigger traces. Variable table should be cleared but not freed! * TclDeleteNamespaceVars frees it, so we reinitialize it afterwards. @@ -1122,11 +1202,11 @@ * f97d4ee020]) we copy to a temporary array and then delete all those * commands. */ while (nsPtr->cmdTable.numEntries > 0) { - size_t length = nsPtr->cmdTable.numEntries; + 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); @@ -1179,79 +1259,19 @@ 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 + TclDeleteNamespaceChildren(nsPtr); /* * Free the namespace's export pattern array. */ - if (nsPtr->exportArrayPtr != NULL) { - for (i = 0; i < nsPtr->numExportPatterns; i++) { - Tcl_Free(nsPtr->exportArrayPtr[i]); - } - Tcl_Free(nsPtr->exportArrayPtr); - nsPtr->exportArrayPtr = NULL; - nsPtr->numExportPatterns = 0; - nsPtr->maxExportPatterns = 0; + if (nsPtr->exportPatternList != NULL) { + Tcl_DecrRefCount(nsPtr->exportPatternList); + nsPtr->exportPatternList = NULL; } /* * Free any client data associated with the namespace. */ @@ -1362,16 +1382,13 @@ * namespace qualifiers; only commands in the * specified namespace may be exported. */ int resetListFirst) /* If nonzero, resets the namespace's export * 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. */ @@ -1384,21 +1401,14 @@ /* * If resetListFirst is true (nonzero), clear the namespace's export * pattern list. */ - if (resetListFirst) { - if (nsPtr->exportArrayPtr != NULL) { - for (i = 0; i < nsPtr->numExportPatterns; i++) { - Tcl_Free(nsPtr->exportArrayPtr[i]); - } - Tcl_Free(nsPtr->exportArrayPtr); - nsPtr->exportArrayPtr = NULL; - TclInvalidateNsCmdLookup(nsPtr); - nsPtr->numExportPatterns = 0; - nsPtr->maxExportPatterns = 0; - } + if (resetListFirst && nsPtr->exportPatternList) { + TclInvalidateNsCmdLookup(nsPtr); + Tcl_DecrRefCount(nsPtr->exportPatternList); + nsPtr->exportPatternList = NULL; } /* * Check that the pattern doesn't have namespace qualifiers. */ @@ -1407,53 +1417,42 @@ &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); + Tcl_SetErrorCode(interp, "TCL", "EXPORT", "INVALID", (void *)NULL); return TCL_ERROR; } /* * Make sure that we don't already have the pattern in the array */ - if (nsPtr->exportArrayPtr != NULL) { - for (i = 0; i < nsPtr->numExportPatterns; i++) { - if (strcmp(pattern, nsPtr->exportArrayPtr[i]) == 0) { + if (nsPtr->exportPatternList != NULL) { + Tcl_Size objc; + Tcl_Obj **objv; + + TclListObjGetElementsM(NULL, nsPtr->exportPatternList, &objc, &objv); + while (objc--) { + if (strcmp(pattern, Tcl_GetString(*objv++)) == 0) { /* * The pattern already exists in the list. */ return TCL_OK; } } - } - - /* - * Make sure there is room in the namespace's pattern array for the new - * pattern. - */ - - neededElems = nsPtr->numExportPatterns + 1; - if (neededElems > nsPtr->maxExportPatterns) { - nsPtr->maxExportPatterns = nsPtr->maxExportPatterns ? - 2 * nsPtr->maxExportPatterns : INIT_EXPORT_PATTERNS; - nsPtr->exportArrayPtr = (char **)Tcl_Realloc(nsPtr->exportArrayPtr, - sizeof(char *) * nsPtr->maxExportPatterns); - } - - /* - * Add the pattern to the namespace's array of export patterns. - */ - - len = strlen(pattern); - patternCpy = (char *)Tcl_Alloc(len + 1); - memcpy(patternCpy, pattern, len + 1); - - nsPtr->exportArrayPtr[nsPtr->numExportPatterns] = patternCpy; - nsPtr->numExportPatterns++; + } else { + nsPtr->exportPatternList = Tcl_NewObj(); + } + + /* + * Add the pattern to the namespace's list of export patterns. + */ + + Tcl_ListObjAppendElement(NULL, nsPtr->exportPatternList, + Tcl_NewStringObj(pattern, -1)); /* * The list of commands actually exported from the namespace might have * changed (probably will have!) However, we do not need to recompute this * just yet; next time we need the info will be soon enough. @@ -1460,11 +1459,10 @@ */ TclInvalidateNsCmdLookup(nsPtr); return TCL_OK; -#undef INIT_EXPORT_PATTERNS } /* *---------------------------------------------------------------------- * @@ -1494,12 +1492,10 @@ * 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. */ @@ -1511,18 +1507,87 @@ /* * Append the export pattern list onto objPtr. */ - for (i = 0; i < nsPtr->numExportPatterns; i++) { - result = Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewStringObj(nsPtr->exportArrayPtr[i], -1)); - if (result != TCL_OK) { - return result; + if (nsPtr->exportPatternList == NULL) { + return TCL_OK; + } + return Tcl_ListObjAppendList(interp, objPtr, nsPtr->exportPatternList); +} + +/* + *---------------------------------------------------------------------- + * + * TclFillTableWithExports -- + * + * 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 namsapce 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. + * + * Results: + * + * Side effects: + * + *---------------------------------------------------------------------- + */ + +void +TclFillTableWithExports( + Namespace *nsPtr, + Tcl_HashTable *hash) +{ + Tcl_HashSearch search; + Tcl_HashEntry *hPtr; + + if (nsPtr->exportPatternList == NULL) { + return; + } + + hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); + for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + Tcl_Size objc; + Tcl_Obj **objv; + char *nsCmdName = (char *)Tcl_GetHashKey(&nsPtr->cmdTable, hPtr); + + TclListObjGetElementsM(NULL, nsPtr->exportPatternList, &objc, &objv); + while (objc--) { + if (Tcl_StringMatch(nsCmdName, Tcl_GetString(*objv++))) { + int isNew; + Tcl_HashEntry *exportPtr = Tcl_CreateHashEntry(hash, + nsCmdName, &isNew); + + /* + * Remember, hash entries have a full reference to the + * substituted part of the command (as a list) as their + * content! + */ + + if (isNew) { + Tcl_Obj *cmdObj, *cmdPrefixObj; + +#if 1 + TclNewObj(cmdObj); + Tcl_AppendStringsToObj(cmdObj, nsPtr->fullName, + (nsPtr->parentPtr ? "::" : ""), nsCmdName, NULL); +#else + cmdObj = Tcl_NewStringObj(nsCmdName, -1); +#endif + cmdPrefixObj = Tcl_NewListObj(1, &cmdObj); + Tcl_SetHashValue(exportPtr, cmdPrefixObj); + Tcl_IncrRefCount(cmdPrefixObj); + } + break; + } } } - return TCL_OK; } /* *---------------------------------------------------------------------- * @@ -1613,33 +1678,33 @@ * get the simple pattern (no namespace qualifiers or ::'s) at the end. */ if (strlen(pattern) == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj("empty import pattern",-1)); - Tcl_SetErrorCode(interp, "TCL", "IMPORT", "EMPTY", NULL); + Tcl_SetErrorCode(interp, "TCL", "IMPORT", "EMPTY", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, (void *)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); + Tcl_SetErrorCode(interp, "TCL", "IMPORT", "ORIGIN", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "IMPORT", "SELF", (void *)NULL); } return TCL_ERROR; } /* @@ -1697,21 +1762,26 @@ const char *cmdName, const char *pattern, Namespace *importNsPtr, int allowOverwrite) { - size_t i = 0, exported = 0; + Tcl_Size objc, exported = 0; + Tcl_Obj **objv; Tcl_HashEntry *found; /* * The command cmdName in the source namespace matches the pattern. Check * whether it was exported. If it wasn't, we ignore it. */ - while (!exported && (i < importNsPtr->numExportPatterns)) { - exported |= Tcl_StringMatch(cmdName, - importNsPtr->exportArrayPtr[i++]); + if (importNsPtr->exportPatternList == NULL) { + return TCL_OK; + } + + TclListObjGetElementsM(NULL, importNsPtr->exportPatternList, &objc, &objv); + while (!exported && objc--) { + exported |= Tcl_StringMatch(cmdName, Tcl_GetString(*objv++)); } if (!exported) { return TCL_OK; } @@ -1758,11 +1828,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "IMPORT", "LOOP", (void *)NULL); return TCL_ERROR; } } } @@ -1800,11 +1870,11 @@ return TCL_OK; } } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't import command \"%s\": already exists", cmdName)); - Tcl_SetErrorCode(interp, "TCL", "IMPORT", "OVERWRITE", NULL); + Tcl_SetErrorCode(interp, "TCL", "IMPORT", "OVERWRITE", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -1870,11 +1940,11 @@ if (sourceNsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown namespace in namespace forget pattern \"%s\"", pattern)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, (void *)NULL); return TCL_ERROR; } if (strcmp(pattern, simplePattern) == 0) { /* @@ -2007,11 +2077,11 @@ *---------------------------------------------------------------------- */ static int InvokeImportedNRCmd( - ClientData clientData, /* Points to the imported command's + void *clientData, /* Points to the imported command's * ImportedCmdData structure. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { @@ -2022,11 +2092,11 @@ return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NOERR, realCmdPtr); } int TclInvokeImportedCmd( - ClientData clientData, /* Points to the imported command's + void *clientData, /* Points to the imported command's * ImportedCmdData structure. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { @@ -2055,11 +2125,11 @@ *---------------------------------------------------------------------- */ static void DeleteImportedCmd( - ClientData clientData) /* Points to the imported command's + void *clientData) /* Points to the imported command's * ImportedCmdData structure. */ { ImportedCmdData *dataPtr = (ImportedCmdData *)clientData; Command *realCmdPtr = dataPtr->realCmdPtr; Command *selfPtr = dataPtr->selfPtr; @@ -2505,11 +2575,11 @@ } if (flags & TCL_LEAVE_ERR_MSG) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown namespace \"%s\"", name)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, (void *)NULL); } return NULL; } /* @@ -2609,19 +2679,19 @@ */ cmdPtr = NULL; if (cxtNsPtr->commandPathLength!=0 && strncmp(name, "::", 2) && !(flags & TCL_NAMESPACE_ONLY)) { - size_t i; + Tcl_Size i; Namespace *pathNsPtr, *realNsPtr, *dummyNsPtr; (void) TclGetNamespaceForQualName(interp, name, cxtNsPtr, TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr, &simpleName); if ((realNsPtr != NULL) && (simpleName != NULL)) { if ((cxtNsPtr == realNsPtr) - || !(realNsPtr->flags & NS_DYING)) { + || !(realNsPtr->flags & NS_DEAD)) { entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName); if (entryPtr != NULL) { cmdPtr = (Command *)Tcl_GetHashValue(entryPtr); } } @@ -2629,20 +2699,20 @@ /* * Next, check along the path. */ - for (i=0 ; icommandPathLength && cmdPtr==NULL ; i++) { + for (i=0 ; (cmdPtr == NULL) && icommandPathLength ; i++) { pathNsPtr = cxtNsPtr->commandPathArray[i].nsPtr; if (pathNsPtr == NULL) { continue; } (void) TclGetNamespaceForQualName(interp, name, pathNsPtr, TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr, &simpleName); if ((realNsPtr != NULL) && (simpleName != NULL) - && !(realNsPtr->flags & NS_DYING)) { + && !(realNsPtr->flags & NS_DEAD)) { entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName); if (entryPtr != NULL) { cmdPtr = (Command *)Tcl_GetHashValue(entryPtr); } } @@ -2656,11 +2726,11 @@ if (cmdPtr == NULL) { (void) TclGetNamespaceForQualName(interp, name, NULL, TCL_GLOBAL_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr, &simpleName); if ((realNsPtr != NULL) && (simpleName != NULL) - && !(realNsPtr->flags & NS_DYING)) { + && !(realNsPtr->flags & NS_DEAD)) { entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName); if (entryPtr != NULL) { cmdPtr = (Command *)Tcl_GetHashValue(entryPtr); } } @@ -2695,11 +2765,11 @@ } if (flags & TCL_LEAVE_ERR_MSG) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown command \"%s\"", name)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", name, (void *)NULL); } return NULL; } /* @@ -2889,11 +2959,11 @@ NamespaceCurrentCmd(NULL, interp, 1, NULL); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "namespace \"%s\" not found in \"%s\"", name, Tcl_GetStringResult(interp))); } - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -2904,11 +2974,11 @@ * namespace. */ Tcl_Namespace **nsPtrPtr) /* Result namespace pointer goes here. */ { ResolvedNsName *resNamePtr; - NsNameGetIntRep(objPtr, resNamePtr); + NsNameGetInternalRep(objPtr, resNamePtr); if (resNamePtr) { Namespace *nsPtr, *refNsPtr; /* * Check that the ResolvedNsName is still valid; avoid letting the ref @@ -2921,14 +2991,14 @@ && (!refNsPtr || (refNsPtr == (Namespace *) TclGetCurrentNamespace(interp)))) { *nsPtrPtr = (Tcl_Namespace *) nsPtr; return TCL_OK; } - Tcl_StoreIntRep(objPtr, &nsNameType, NULL); + Tcl_StoreInternalRep(objPtr, &nsNameType, NULL); } if (SetNsNameFromAny(interp, objPtr) == TCL_OK) { - NsNameGetIntRep(objPtr, resNamePtr); + NsNameGetInternalRep(objPtr, resNamePtr); assert(resNamePtr != NULL); *nsPtrPtr = (Tcl_Namespace *) resNamePtr->nsPtr; return TCL_OK; } return TCL_ERROR; @@ -2979,11 +3049,11 @@ *---------------------------------------------------------------------- */ static int NamespaceChildrenCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *namespacePtr; @@ -3108,19 +3178,19 @@ *---------------------------------------------------------------------- */ static int NamespaceCodeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Namespace *currNsPtr; Tcl_Obj *listPtr, *objPtr; const char *arg; - size_t length; + Tcl_Size length; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arg"); return TCL_ERROR; } @@ -3131,11 +3201,11 @@ * [::namespace code] generates it. Anything more forgiving can have * the effect of failing in namespaces that contain their own custom " "namespace" command. [Bug 3202171]. */ - arg = TclGetStringFromObj(objv[1], &length); + arg = Tcl_GetStringFromObj(objv[1], &length); if (*arg==':' && length > 20 && strncmp(arg, "::namespace inscope ", 20) == 0) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } @@ -3189,11 +3259,11 @@ *---------------------------------------------------------------------- */ static int NamespaceCurrentCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Namespace *currNsPtr; @@ -3252,11 +3322,11 @@ *---------------------------------------------------------------------- */ static int NamespaceDeleteCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *namespacePtr; @@ -3276,16 +3346,16 @@ for (i = 1; i < objc; i++) { name = TclGetString(objv[i]); namespacePtr = Tcl_FindNamespace(interp, name, NULL, /*flags*/ 0); if ((namespacePtr == NULL) - || (((Namespace *) namespacePtr)->flags & NS_KILLED)) { + || (((Namespace *) namespacePtr)->flags & NS_TEARDOWN)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown namespace \"%s\" in namespace delete command", TclGetString(objv[i]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", - TclGetString(objv[i]), NULL); + TclGetString(objv[i]), (void *)NULL); return TCL_ERROR; } } /* @@ -3329,11 +3399,11 @@ *---------------------------------------------------------------------- */ static int NamespaceEvalCmd( - ClientData clientData, /* Arbitrary value passed to cmd. */ + void *clientData, /* Arbitrary value passed to cmd. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, NRNamespaceEvalCmd, clientData, objc, @@ -3340,11 +3410,11 @@ objv); } static int NRNamespaceEvalCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -3422,11 +3492,11 @@ return TclNREvalObjEx(interp, objPtr, 0, invoker, word); } static int NsEval_Callback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Namespace *namespacePtr = (Tcl_Namespace *)data[0]; @@ -3472,11 +3542,11 @@ *---------------------------------------------------------------------- */ static int NamespaceExistsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *namespacePtr; @@ -3527,16 +3597,20 @@ *---------------------------------------------------------------------- */ static int NamespaceExportCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int firstArg, i; + Namespace *nsPtr; + Tcl_Obj *dict, *value; + Tcl_Size startSize, endSize, firstArg, i; + int changed = 0; + int code = TCL_OK; if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?-clear? ?pattern pattern...?"); return TCL_ERROR; } @@ -3544,41 +3618,99 @@ /* * If no pattern arguments are given, and "-clear" isn't specified, return * the namespace's current export pattern list. */ + nsPtr = (Namespace *) TclGetCurrentNamespace(interp); if (objc == 1) { - Tcl_Obj *listPtr; - - TclNewObj(listPtr); - (void)Tcl_AppendExportList(interp, NULL, listPtr); - Tcl_SetObjResult(interp, listPtr); + if (nsPtr->exportPatternList) { + Tcl_SetObjResult(interp, nsPtr->exportPatternList); + } return TCL_OK; } /* * Process the optional "-clear" argument. */ firstArg = 1; if (strcmp("-clear", TclGetString(objv[firstArg])) == 0) { - Tcl_Export(interp, NULL, "::", 1); - Tcl_ResetResult(interp); + if (nsPtr->exportPatternList) { + Tcl_DecrRefCount(nsPtr->exportPatternList); + nsPtr->exportPatternList = NULL; + changed = 1; + } firstArg++; } /* * Add each pattern to the namespace's export pattern list. + * Use a dict as a simple way to screen out duplicates. */ + dict = Tcl_NewDictObj(); + value = Tcl_NewObj(); + Tcl_IncrRefCount(value); + if (nsPtr->exportPatternList) { + Tcl_Size epc; + Tcl_Obj **epv; + + TclListObjGetElementsM(NULL, nsPtr->exportPatternList, &epc, &epv); + while (epc--) { + Tcl_DictObjPut(NULL, dict, *epv++, value); + } + } + Tcl_DictObjSize(NULL, dict, &startSize); + for (i = firstArg; i < objc; i++) { - int result = Tcl_Export(interp, NULL, TclGetString(objv[i]), 0); - if (result != TCL_OK) { - return result; + Namespace *exportNsPtr, *dummyPtr; + const char *simplePattern, *pattern = Tcl_GetString(objv[i]); + + 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); + code = TCL_ERROR; + break; + } + + Tcl_DictObjPut(NULL, dict, objv[i], value); + } + Tcl_DictObjSize(NULL, dict, &endSize); + changed |= (endSize > startSize); + + if (endSize > startSize) { + int done; + Tcl_Obj *ep; + Tcl_DictSearch search; + + if (nsPtr->exportPatternList == NULL) { + nsPtr->exportPatternList = Tcl_NewObj(); + Tcl_IncrRefCount(nsPtr->exportPatternList); + } + + i = 0; + Tcl_DictObjFirst(NULL, dict, &search, &ep, NULL, &done); + for (; !done; i++, Tcl_DictObjNext(&search, &ep, NULL, &done)) { + if (i < startSize) { + continue; + } + Tcl_ListObjAppendElement(NULL, nsPtr->exportPatternList, ep); } + Tcl_DictObjDone(&search); + } + Tcl_DecrRefCount(value); + Tcl_DecrRefCount(dict); + + if (changed) { + TclInvalidateNsCmdLookup(nsPtr); } - return TCL_OK; + return code; } /* *---------------------------------------------------------------------- * @@ -3609,11 +3741,11 @@ *---------------------------------------------------------------------- */ static int NamespaceForgetCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *pattern; @@ -3674,11 +3806,11 @@ *---------------------------------------------------------------------- */ static int NamespaceImportCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int allowOverwrite = 0; @@ -3778,11 +3910,11 @@ *---------------------------------------------------------------------- */ static int NamespaceInscopeCmd( - ClientData clientData, /* Arbitrary value passed to cmd. */ + void *clientData, /* Arbitrary value passed to cmd. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, NRNamespaceInscopeCmd, clientData, objc, @@ -3789,11 +3921,11 @@ objv); } static int NRNamespaceInscopeCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *namespacePtr; @@ -3886,11 +4018,11 @@ *---------------------------------------------------------------------- */ static int NamespaceOriginCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Command cmd, origCmd; @@ -3915,11 +4047,11 @@ 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); + TclGetString(objv[1]), (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } @@ -3946,11 +4078,11 @@ *---------------------------------------------------------------------- */ static int NamespaceParentCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *nsPtr; @@ -4004,18 +4136,18 @@ *---------------------------------------------------------------------- */ static int NamespacePathCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp); - size_t i; - int nsObjc, result = TCL_ERROR; + Tcl_Size nsObjc, i; + int result = TCL_ERROR; Tcl_Obj **nsObjv; Tcl_Namespace **namespaceList = NULL; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?pathList?"); @@ -4042,18 +4174,18 @@ /* * There is a path given, so parse it into an array of namespace pointers. */ - if (TclListObjGetElements(interp, objv[1], &nsObjc, &nsObjv) != TCL_OK) { + if (TclListObjGetElementsM(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++) { + for (i = 0; i < nsObjc; i++) { if (TclGetNamespaceFromObj(interp, nsObjv[i], &namespaceList[i]) != TCL_OK) { goto badNamespace; } } @@ -4094,17 +4226,17 @@ */ void TclSetNsPath( Namespace *nsPtr, /* Namespace whose path is to be set. */ - size_t pathLength, /* Length of pathAry. */ + Tcl_Size pathLength, /* Length of pathAry. */ Tcl_Namespace *pathAry[]) /* Array of namespaces that are the path. */ { if (pathLength != 0) { NamespacePathEntry *tmpPathArray = (NamespacePathEntry *)Tcl_Alloc(sizeof(NamespacePathEntry) * pathLength); - size_t i; + Tcl_Size i; for (i=0 ; icommandPathLength ; i++) { NamespacePathEntry *nsPathPtr = &nsPtr->commandPathArray[i]; if (nsPathPtr->prevPtr != NULL) { nsPathPtr->prevPtr->nextPtr = nsPathPtr->nextPtr; @@ -4184,11 +4316,11 @@ * nothing * * Side effects: * Increments the command reference epoch in each namespace whose path * includes the given namespace. This causes any cached resolved names - * whose root cacheing context starts at that namespace to be recomputed + * whose root caching context starts at that namespace to be recomputed * the next time they are used. * *---------------------------------------------------------------------- */ @@ -4231,17 +4363,17 @@ *---------------------------------------------------------------------- */ static int NamespaceQualifiersCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *name, *p; - size_t length; + Tcl_Size length; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "string"); return TCL_ERROR; } @@ -4257,11 +4389,11 @@ } 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 : */ + p--; /* Back up over the preceding : */ } break; } } @@ -4299,11 +4431,11 @@ *---------------------------------------------------------------------- */ static int NamespaceUnknownCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *currNsPtr; @@ -4402,19 +4534,19 @@ Tcl_Interp *interp, /* Interpreter in which the namespace * exists. */ Tcl_Namespace *nsPtr, /* Namespace which is being updated. */ Tcl_Obj *handlerPtr) /* The new handler, or NULL to reset. */ { - int lstlen = 0; + Tcl_Size lstlen = 0; Namespace *currNsPtr = (Namespace *) nsPtr; /* * Ensure that we check for errors *first* before we change anything. */ if (handlerPtr != NULL) { - if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) { + if (TclListObjLengthM(interp, handlerPtr, &lstlen) != TCL_OK) { /* * Not a list. */ return TCL_ERROR; @@ -4486,11 +4618,11 @@ *---------------------------------------------------------------------- */ static int NamespaceTailCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *name, *p; @@ -4536,19 +4668,19 @@ * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Creates new variables in the current scope, linked to the - * corresponding variables in the stipulated nmamespace. If anything goes + * corresponding variables in the stipulated namespace. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceUpvarCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -4618,11 +4750,11 @@ *---------------------------------------------------------------------- */ static int NamespaceWhichCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const opts[] = { @@ -4699,11 +4831,11 @@ Tcl_Obj *objPtr) /* nsName object with internal representation * to free. */ { ResolvedNsName *resNamePtr; - NsNameGetIntRep(objPtr, resNamePtr); + NsNameGetInternalRep(objPtr, resNamePtr); assert(resNamePtr != NULL); /* * Decrement the reference count of the namespace. If there are no more * references, free it up. @@ -4745,13 +4877,13 @@ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { ResolvedNsName *resNamePtr; - NsNameGetIntRep(srcPtr, resNamePtr); + NsNameGetInternalRep(srcPtr, resNamePtr); assert(resNamePtr != NULL); - NsNameSetIntRep(copyPtr, resNamePtr); + NsNameSetInternalRep(copyPtr, resNamePtr); } /* *---------------------------------------------------------------------- * @@ -4810,11 +4942,11 @@ resNamePtr->refNsPtr = NULL; } else { resNamePtr->refNsPtr = (Namespace *) TclGetCurrentNamespace(interp); } resNamePtr->refCount = 0; - NsNameSetIntRep(objPtr, resNamePtr); + NsNameSetInternalRep(objPtr, resNamePtr); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -4874,15 +5006,15 @@ /* *---------------------------------------------------------------------- * * TclLogCommandInfo -- * - * This function is invoked after an error occurs in an interpreter. It - * adds information to iPtr->errorInfo/errorStack fields to describe the + * Invoked after an error occurs in an interpreter. + * Adds information to iPtr->errorInfo/errorStack fields to describe the * command that was being executed when the error occurred. When pc and * tosPtr are non-NULL, conveying a bytecode execution "inner context", - * and the offending instruction is suitable, that inner context is + * and the offending instruction is suitable, and that inner context is * recorded in errorStack. * * Results: * None. * @@ -4898,12 +5030,13 @@ Tcl_Interp *interp, /* Interpreter in which to log information. */ const char *script, /* First character in script containing * command (must be <= command). */ const char *command, /* First character in command that generated * the error. */ - size_t length, /* Number of bytes in command (-1 means - * use all bytes up to first null byte). */ + Tcl_Size length, /* Number of bytes in command (< 0 means use + * all bytes up to first null byte). + */ const unsigned char *pc, /* Current pc of bytecode execution context */ Tcl_Obj **tosPtr) /* Current stack of bytecode execution * context */ { const char *p; @@ -4911,12 +5044,12 @@ int overflow, limit = 150; Var *varPtr, *arrayPtr; if (iPtr->flags & ERR_ALREADY_LOGGED) { /* - * Someone else has already logged error information for this command; - * we shouldn't add anything more. + * Someone else has already logged error information for this command. + * Don't add anything more. */ return; } @@ -4930,14 +5063,14 @@ if (*p == '\n') { iPtr->errorLine++; } } - if (length == TCL_INDEX_NONE) { + if (length < 0) { length = strlen(command); } - overflow = (length > (size_t)limit); + overflow = (length > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n %s\n\"%.*s%s\"", ((iPtr->errorInfo == NULL) ? "while executing" : "invoked from within"), (overflow ? limit : (int)length), command, (overflow ? "..." : ""))); @@ -4950,11 +5083,11 @@ */ return; } else { Tcl_HashEntry *hPtr - = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr); + = 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 @@ -4983,17 +5116,17 @@ Tcl_DecrRefCount(iPtr->errorStack); Tcl_IncrRefCount(newObj); iPtr->errorStack = newObj; } if (iPtr->resetErrorStack) { - int len; + Tcl_Size len; iPtr->resetErrorStack = 0; - Tcl_ListObjLength(interp, iPtr->errorStack, &len); + TclListObjLengthM(interp, iPtr->errorStack, &len); /* - * Reset while keeping the list intrep as much as possible. + * Reset while keeping the list internalrep as much as possible. */ Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, 0, NULL); if (pc != NULL) { Tcl_Obj *innerContext; @@ -5021,11 +5154,11 @@ * uplevel case, [lappend errorstack UP $relativelevel] */ Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->upLiteral); Tcl_ListObjAppendElement(NULL, iPtr->errorStack, Tcl_NewWideIntObj( - iPtr->framePtr->level - iPtr->varFramePtr->level)); + (int)(iPtr->framePtr->level - iPtr->varFramePtr->level))); } else if (iPtr->framePtr != iPtr->rootFramePtr) { /* * normal case, [lappend errorstack CALL [info level 0]] */ @@ -5055,11 +5188,11 @@ void TclErrorStackResetIf( Tcl_Interp *interp, const char *msg, - size_t length) + Tcl_Size length) { Interp *iPtr = (Interp *) interp; if (Tcl_IsShared(iPtr->errorStack)) { Tcl_Obj *newObj; @@ -5068,17 +5201,17 @@ Tcl_DecrRefCount(iPtr->errorStack); Tcl_IncrRefCount(newObj); iPtr->errorStack = newObj; } if (iPtr->resetErrorStack) { - int len; + Tcl_Size len; iPtr->resetErrorStack = 0; - Tcl_ListObjLength(interp, iPtr->errorStack, &len); + TclListObjLengthM(interp, iPtr->errorStack, &len); /* - * Reset while keeping the list intrep as much as possible. + * Reset while keeping the list internalrep as much as possible. */ Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, 0, NULL); Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->innerLiteral); Tcl_ListObjAppendElement(NULL, iPtr->errorStack, @@ -5110,11 +5243,11 @@ Tcl_Interp *interp, /* Interpreter in which to log information. */ const char *script, /* First character in script containing * command (must be <= command). */ const char *command, /* First character in command that generated * the error. */ - size_t length) /* Number of bytes in command (-1 means use + Tcl_Size length) /* Number of bytes in command (-1 means use * all bytes up to first null byte). */ { TclLogCommandInfo(interp, script, command, length, NULL, NULL); } Index: generic/tclNotify.c ================================================================== --- generic/tclNotify.c +++ generic/tclNotify.c @@ -5,26 +5,27 @@ * notifier is lowest-level part of the event system. It manages an event * queue that holds Tcl_Event structures. The platform specific portion * of the notifier is defined in the tcl*Notify.c files in each platform * directory. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright (c) 1998 by Scriptics Corporation. - * Copyright (c) 2003 by Kevin B. Kenny. All rights reserved. + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 1998 Scriptics Corporation. + * Copyright © 2003 Kevin B. Kenny. All rights reserved. + * Copyright © 2021 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* - * Module-scope struct of notifier hooks that are checked in the default + * Notifier hooks that are checked in the public wrappers for the default * notifier functions (for overriding via Tcl_SetNotifier). */ -Tcl_NotifierProcs tclNotifierHooks = { +static Tcl_NotifierProcs tclNotifierHooks = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* * For each event source (created with Tcl_CreateEventSource) there is a @@ -32,11 +33,11 @@ */ typedef struct EventSource { Tcl_EventSetupProc *setupProc; Tcl_EventCheckProc *checkProc; - ClientData clientData; + void *clientData; struct EventSource *nextPtr; } EventSource; /* * The following structure keeps track of the state of the notifier on a @@ -68,11 +69,11 @@ * during an event source traversal. */ EventSource *firstEventSourcePtr; /* Pointer to first event source in list of * event sources for this thread. */ Tcl_ThreadId threadId; /* Thread that owns this notifier instance. */ - ClientData clientData; /* Opaque handle for platform specific + void *clientData; /* Opaque handle for platform specific * notifier. */ int initialized; /* 1 if notifier has been initialized. */ struct ThreadSpecificData *nextPtr; /* Next notifier in global list of notifiers. * Access is controlled by the listLock global @@ -92,12 +93,12 @@ /* * Declarations for routines used only in this file. */ -static void QueueEvent(ThreadSpecificData *tsdPtr, - Tcl_Event *evPtr, Tcl_QueuePosition position); +static int QueueEvent(ThreadSpecificData *tsdPtr, + Tcl_Event *evPtr, int position); /* *---------------------------------------------------------------------- * * TclInitNotifier -- @@ -172,11 +173,11 @@ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ThreadSpecificData **prevPtrPtr; Tcl_Event *evPtr, *hold; if (!tsdPtr->initialized) { - return; /* Notifier not initialized for the current thread */ + return; /* Notifier not initialized for the current thread */ } Tcl_MutexLock(&(tsdPtr->queueMutex)); for (evPtr = tsdPtr->firstEventPtr; evPtr != NULL; ) { hold = evPtr; @@ -222,13 +223,45 @@ *---------------------------------------------------------------------- */ void Tcl_SetNotifier( - Tcl_NotifierProcs *notifierProcPtr) + const Tcl_NotifierProcs *notifierProcPtr) { tclNotifierHooks = *notifierProcPtr; + + /* + * Don't allow hooks to refer to the hook point functions; avoids infinite + * loop. + */ + + if (tclNotifierHooks.setTimerProc == Tcl_SetTimer) { + tclNotifierHooks.setTimerProc = NULL; + } + if (tclNotifierHooks.waitForEventProc == Tcl_WaitForEvent) { + tclNotifierHooks.waitForEventProc = NULL; + } + if (tclNotifierHooks.initNotifierProc == Tcl_InitNotifier) { + tclNotifierHooks.initNotifierProc = NULL; + } + if (tclNotifierHooks.finalizeNotifierProc == Tcl_FinalizeNotifier) { + tclNotifierHooks.finalizeNotifierProc = NULL; + } + if (tclNotifierHooks.alertNotifierProc == Tcl_AlertNotifier) { + tclNotifierHooks.alertNotifierProc = NULL; + } + if (tclNotifierHooks.serviceModeHookProc == Tcl_ServiceModeHook) { + tclNotifierHooks.serviceModeHookProc = NULL; + } +#ifndef _WIN32 + if (tclNotifierHooks.createFileHandlerProc == Tcl_CreateFileHandler) { + tclNotifierHooks.createFileHandlerProc = NULL; + } + if (tclNotifierHooks.deleteFileHandlerProc == Tcl_DeleteFileHandler) { + tclNotifierHooks.deleteFileHandlerProc = NULL; + } +#endif /* !_WIN32 */ } /* *---------------------------------------------------------------------- * @@ -253,11 +286,11 @@ * used to wait. It figures out whether anything interesting actually * happened (e.g. by calling Tcl_AsyncReady), and then calls * Tcl_QueueEvent to queue any events that are ready. * * Each of these functions is passed two arguments, e.g. - * (*checkProc)(ClientData clientData, int flags)); + * (*checkProc)(void *clientData, int flags)); * ClientData is the same as the clientData argument here, and flags is a * combination of things like TCL_FILE_EVENTS that indicates what events * are of interest: setupProc and checkProc use flags to figure out * whether their events are relevant or not. * @@ -270,11 +303,11 @@ /* Function to invoke to figure out what to * wait for. */ Tcl_EventCheckProc *checkProc, /* Function to call after waiting to see what * happened. */ - ClientData clientData) /* One-word argument to pass to setupProc and + void *clientData) /* One-word argument to pass to setupProc and * checkProc. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); EventSource *sourcePtr = (EventSource *)Tcl_Alloc(sizeof(EventSource)); @@ -309,11 +342,11 @@ /* Function to invoke to figure out what to * wait for. */ Tcl_EventCheckProc *checkProc, /* Function to call after waiting to see what * happened. */ - ClientData clientData) /* One-word argument to pass to setupProc and + void *clientData) /* One-word argument to pass to setupProc and * checkProc. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); EventSource *sourcePtr, *prevPtr; @@ -356,12 +389,12 @@ Tcl_Event *evPtr, /* Event to add to queue. The storage space * must have been allocated the caller with * malloc (Tcl_Alloc), and it becomes the * property of the event queue. It will be * freed after the event has been handled. */ - Tcl_QueuePosition position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, - * TCL_QUEUE_MARK. */ + int position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK, + * possibly combined with TCL_QUEUE_ALERT_IF_EMPTY. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); QueueEvent(tsdPtr, evPtr, position); } @@ -388,12 +421,12 @@ Tcl_Event *evPtr, /* Event to add to queue. The storage space * must have been allocated the caller with * malloc (Tcl_Alloc), and it becomes the * property of the event queue. It will be * freed after the event has been handled. */ - Tcl_QueuePosition position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, - * TCL_QUEUE_MARK. */ + int position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK, + * possibly combined with TCL_QUEUE_ALERT_IF_EMPTY. */ { ThreadSpecificData *tsdPtr; /* * Find the notifier associated with the specified thread. @@ -408,11 +441,13 @@ /* * Queue the event if there was a notifier associated with the thread. */ if (tsdPtr) { - QueueEvent(tsdPtr, evPtr, position); + if (QueueEvent(tsdPtr, evPtr, position)) { + Tcl_AlertNotifier(tsdPtr->clientData); + } } else { Tcl_Free(evPtr); } Tcl_MutexUnlock(&listLock); } @@ -428,32 +463,36 @@ * 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. + * For TCL_QUEUE_ALERT_IF_EMPTY the empty state before the + * operation is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ -static void +static int QueueEvent( ThreadSpecificData *tsdPtr, /* Handle to thread local data that indicates * which event queue to use. */ Tcl_Event *evPtr, /* Event to add to queue. The storage space * must have been allocated the caller with * malloc (Tcl_Alloc), and it becomes the * property of the event queue. It will be * freed after the event has been handled. */ - Tcl_QueuePosition position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, - * TCL_QUEUE_MARK. */ + int position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK, + * possibly combined with TCL_QUEUE_ALERT_IF_EMPTY */ { Tcl_MutexLock(&(tsdPtr->queueMutex)); - if (position == TCL_QUEUE_TAIL) { + 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; @@ -461,21 +500,21 @@ tsdPtr->firstEventPtr = evPtr; } else { tsdPtr->lastEventPtr->nextPtr = evPtr; } tsdPtr->lastEventPtr = evPtr; - } else if (position == TCL_QUEUE_HEAD) { + } else if ((position & 3) == TCL_QUEUE_HEAD) { /* * Push the event on the head of the queue. */ evPtr->nextPtr = tsdPtr->firstEventPtr; if (tsdPtr->firstEventPtr == NULL) { tsdPtr->lastEventPtr = evPtr; } tsdPtr->firstEventPtr = evPtr; - } else if (position == TCL_QUEUE_MARK) { + } else if ((position & 3) == TCL_QUEUE_MARK) { /* * Insert the event after the current marker event and advance the * marker to the new event. */ @@ -490,10 +529,11 @@ if (evPtr->nextPtr == NULL) { tsdPtr->lastEventPtr = evPtr; } } Tcl_MutexUnlock(&(tsdPtr->queueMutex)); + return position & TCL_QUEUE_ALERT_IF_EMPTY; } /* *---------------------------------------------------------------------- * @@ -514,11 +554,11 @@ */ void Tcl_DeleteEvents( Tcl_EventDeleteProc *proc, /* The function to call. */ - ClientData clientData) /* The type-specific data. */ + void *clientData) /* The type-specific data. */ { Tcl_Event *evPtr; /* Pointer to the event being examined */ Tcl_Event *prevPtr; /* Pointer to evPtr's predecessor, or NULL if * evPtr designates the first event in the * queue for the thread. */ @@ -792,11 +832,11 @@ *---------------------------------------------------------------------- */ void Tcl_SetMaxBlockTime( - const Tcl_Time *timePtr) /* Specifies a maximum elapsed time for the + const Tcl_Time *timePtr) /* Specifies a maximum elapsed time for the * next blocking operation in the event * tsdPtr-> */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -985,16 +1025,16 @@ if (flags & TCL_DONT_WAIT) { break; } /* - * If Tcl_WaitForEvent has returned 1, indicating that one system - * event has been dispatched (and thus that some Tcl code might have - * been indirectly executed), we break out of the loop. We do this to - * give VwaitCmd for instance a chance to check if that system event - * had the side effect of changing the variable (so the vwait can - * return and unwind properly). + * If Tcl_WaitForEvent has returned 1, indicating that one system event + * has been dispatched (and thus that some Tcl code might have been + * indirectly executed), we break out of the loop in order, e.g. to + * give vwait a chance to determine whether that system event had the + * side effect of changing the variable (so the vwait can return and + * unwind properly). * * NB: We will process idle events if any first, because otherwise we * might never do the idle events if the notifier always gets * system events. */ @@ -1130,12 +1170,266 @@ } } 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: */ Index: generic/tclOO.c ================================================================== --- generic/tclOO.c +++ generic/tclOO.c @@ -1,12 +1,12 @@ /* * tclOO.c -- * * This file contains the object-system core (NB: not Tcl_Obj, but ::oo) * - * Copyright (c) 2005-2012 by Donal K. Fellows - * Copyright (c) 2017 by Nathan Coulter + * Copyright © 2005-2019 Donal K. Fellows + * Copyright © 2017 Nathan Coulter * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -65,38 +65,38 @@ static int CloneClassMethod(Tcl_Interp *interp, Class *clsPtr, Method *mPtr, Tcl_Obj *namePtr, Method **newMPtrPtr); static int CloneObjectMethod(Tcl_Interp *interp, Object *oPtr, Method *mPtr, Tcl_Obj *namePtr); -static void DeletedDefineNamespace(ClientData clientData); -static void DeletedObjdefNamespace(ClientData clientData); -static void DeletedHelpersNamespace(ClientData clientData); +static void 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(ClientData clientData); -static void ObjectNamespaceDeleted(ClientData clientData); +static void MyDeleted(void *clientData); +static void ObjectNamespaceDeleted(void *clientData); static Tcl_CommandTraceProc ObjectRenamedTrace; -static inline void RemoveClass(Class **list, int num, int idx); -static inline void RemoveObject(Object **list, int num, int idx); +static inline void RemoveClass(Class **list, size_t num, size_t idx); +static inline void RemoveObject(Object **list, size_t num, size_t idx); static inline void SquelchCachedName(Object *oPtr); -static int PublicNRObjectCmd(ClientData clientData, +static int PublicNRObjectCmd(void *clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const *objv); +static int PrivateNRObjectCmd(void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); -static int PrivateNRObjectCmd(ClientData clientData, +static int MyClassNRObjCmd(void *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); +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! @@ -135,12 +135,15 @@ /* * Scripted parts of TclOO. First, the main script (cannot be outside this * file). */ -static const char *initScript = +static const char initScript[] = +#ifndef TCL_NO_DEPRECATED "package ifneeded TclOO " TCLOO_PATCHLEVEL " {# Already present, OK?};" +#endif +"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};" "namespace eval ::oo { variable version " TCLOO_VERSION " };" "namespace eval ::oo { variable patchlevel " TCLOO_PATCHLEVEL " };"; /* "tcl_findLibrary tcloo $oo::version $oo::version" */ /* " tcloo.tcl OO_LIBRARY oo::library;"; */ @@ -196,26 +199,26 @@ */ static inline void RemoveClass( Class **list, - int num, - int idx) + size_t num, + size_t idx) { - for (; idx < num - 1; idx++) { + for (; idx + 1 < num; idx++) { list[idx] = list[idx + 1]; } list[idx] = NULL; } static inline void RemoveObject( Object **list, - int num, - int idx) + size_t num, + size_t idx) { - for (; idx < num - 1; idx++) { + for (; idx + 1 < num; idx++) { list[idx] = list[idx + 1]; } list[idx] = NULL; } @@ -251,16 +254,20 @@ /* * Run our initialization script and, if that works, declare the package * to be fully provided. */ - if (Tcl_EvalEx(interp, initScript, -1, 0) != TCL_OK) { + if (Tcl_EvalEx(interp, initScript, TCL_INDEX_NONE, 0) != TCL_OK) { return TCL_ERROR; } - return Tcl_PkgProvideEx(interp, "TclOO", TCLOO_PATCHLEVEL, - (void *) &tclOOStubs); +#ifndef TCL_NO_DEPRECATED + Tcl_PkgProvideEx(interp, "TclOO", TCLOO_PATCHLEVEL, + &tclOOStubs); +#endif + return Tcl_PkgProvideEx(interp, "tcl::oo", TCLOO_PATCHLEVEL, + &tclOOStubs); } /* * ---------------------------------------------------------------------- * @@ -299,11 +306,11 @@ (ThreadLocalData *)Tcl_GetThreadData(&tsdKey, sizeof(ThreadLocalData)); Foundation *fPtr = (Foundation *)Tcl_Alloc(sizeof(Foundation)); Tcl_Obj *namePtr; Tcl_DString buffer; Command *cmdPtr; - int i; + size_t i; /* * Initialize the structure that holds the OO system core. This is * attached to the interpreter via an assocData entry; not very efficient, * but the best we can do without hacking the core more. @@ -318,10 +325,11 @@ 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, ""); TclNewLiteralStringObj(fPtr->destructorName, ""); @@ -382,13 +390,13 @@ * private; classes, unlike general objects, must have explicit names. We * also need to create the constructor for classes. */ TclNewLiteralStringObj(namePtr, "new"); - Tcl_NewInstanceMethod(interp, (Tcl_Object) fPtr->classCls->thisPtr, + TclNewInstanceMethod(interp, (Tcl_Object) fPtr->classCls->thisPtr, namePtr /* keeps ref */, 0 /* private */, NULL, NULL); - fPtr->classCls->constructorPtr = (Method *) Tcl_NewMethod(interp, + 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. @@ -420,11 +428,11 @@ /* * Evaluate the remaining definitions, which are a compiled-in Tcl script. */ - return Tcl_EvalEx(interp, tclOOSetupScript, -1, 0); + return Tcl_EvalEx(interp, tclOOSetupScript, TCL_INDEX_NONE, 0); } /* * ---------------------------------------------------------------------- * @@ -447,10 +455,11 @@ /* 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); @@ -526,29 +535,29 @@ * ---------------------------------------------------------------------- */ static void DeletedDefineNamespace( - ClientData clientData) + void *clientData) { Foundation *fPtr = (Foundation *)clientData; fPtr->defineNs = NULL; } static void DeletedObjdefNamespace( - ClientData clientData) + void *clientData) { Foundation *fPtr = (Foundation *)clientData; fPtr->objdefNs = NULL; } static void DeletedHelpersNamespace( - ClientData clientData) + void *clientData) { Foundation *fPtr = (Foundation *)clientData; fPtr->helpersNs = NULL; } @@ -645,11 +654,11 @@ } while (1) { char objName[10 + TCL_INTEGER_SPACE]; - sprintf(objName, "::oo::Obj%" TCL_Z_MODIFIER "u", ++fPtr->tsdPtr->nsCount); + 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; } @@ -780,21 +789,21 @@ * ---------------------------------------------------------------------- */ static void MyDeleted( - ClientData clientData) /* Reference to the object whose [my] has been + void *clientData) /* Reference to the object whose [my] has been * squelched. */ { Object *oPtr = (Object *)clientData; oPtr->myCommand = NULL; } static void MyClassDeleted( - ClientData clientData) + void *clientData) { Object *oPtr = (Object *)clientData; oPtr->myclassCommand = NULL; } @@ -811,11 +820,11 @@ * ---------------------------------------------------------------------- */ static void ObjectRenamedTrace( - ClientData clientData, /* The object being deleted. */ + void *clientData, /* The object being deleted. */ TCL_UNUSED(Tcl_Interp *), TCL_UNUSED(const char *) /*oldName*/, TCL_UNUSED(const char *) /*newName*/, int flags) /* Why was the object deleted? */ { @@ -951,15 +960,15 @@ TclOOReleaseClassContents( Tcl_Interp *interp, /* The interpreter containing the class. */ Object *oPtr) /* The object representing the class. */ { FOREACH_HASH_DECLS; - int i; + Tcl_Size i; Class *clsPtr = oPtr->classPtr, *tmpClsPtr; Method *mPtr; Foundation *fPtr = oPtr->fPtr; - Tcl_Obj *variableObj; + Tcl_Obj *variableObj, *propertyObj; PrivateVariableMapping *privateVariable; /* * Sanity check! */ @@ -1007,10 +1016,33 @@ } 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. */ @@ -1029,11 +1061,11 @@ * Squelch our metadata. */ if (clsPtr->metadataPtr != NULL) { Tcl_ObjectMetadataType *metadataTypePtr; - ClientData value; + void *value; FOREACH_HASH(metadataTypePtr, value, clsPtr->metadataPtr) { metadataTypePtr->deleteProc(value); } Tcl_DeleteHashTable(clsPtr->metadataPtr); @@ -1101,22 +1133,22 @@ * ---------------------------------------------------------------------- */ static void ObjectNamespaceDeleted( - ClientData clientData) /* Pointer to the class whose namespace is + void *clientData) /* Pointer to the class whose namespace is * being deleted. */ { Object *oPtr = (Object *)clientData; Foundation *fPtr = oPtr->fPtr; FOREACH_HASH_DECLS; Class *mixinPtr; Method *mPtr; - Tcl_Obj *filterObj, *variableObj; + Tcl_Obj *filterObj, *variableObj, *propertyObj; PrivateVariableMapping *privateVariable; Tcl_Interp *interp = oPtr->fPtr->interp; - int i; + Tcl_Size i; if (Destructing(oPtr)) { /* * TODO: Can ObjectNamespaceDeleted ever be called twice? If not, * this guard could be removed. @@ -1125,11 +1157,11 @@ return; } /* * One rule for the teardown routines is that if an object is in the - * process of being deleted, nothing else may modify its bookeeping + * process of being deleted, nothing else may modify its bookkeeping * records. This is the flag that */ oPtr->flags |= OBJECT_DESTRUCTING; @@ -1178,11 +1210,11 @@ */ if (((Command *) oPtr->command)->flags && CMD_DYING) { /* * Something has already started the command deletion process. We can - * go ahead and clean up the the namespace, + * go ahead and clean up the namespace, */ } else { /* * The namespace must have been deleted directly. Delete the command * as well. @@ -1252,19 +1284,42 @@ SquelchCachedName(oPtr); if (oPtr->metadataPtr != NULL) { Tcl_ObjectMetadataType *metadataTypePtr; - ClientData value; + void *value; FOREACH_HASH(metadataTypePtr, value, oPtr->metadataPtr) { metadataTypePtr->deleteProc(value); } Tcl_DeleteHashTable(oPtr->metadataPtr); Tcl_Free(oPtr->metadataPtr); oPtr->metadataPtr = NULL; } + + /* + * Squelch the property lists. + */ + + 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. @@ -1353,11 +1408,12 @@ TclOORemoveFromInstances( Object *oPtr, /* The instance to remove. */ Class *clsPtr) /* The class (possibly) containing the * reference to the instance. */ { - int i, res = 0; + Tcl_Size i; + int res = 0; Object *instPtr; FOREACH(instPtr, clsPtr->instances) { if (oPtr == instPtr) { RemoveItem(Object, clsPtr->instances, i); @@ -1415,11 +1471,12 @@ TclOORemoveFromMixins( Class *mixinPtr, /* The mixin to remove. */ Object *oPtr) /* The object (possibly) containing the * reference to the mixin. */ { - int i, res = 0; + Tcl_Size i; + int res = 0; Class *mixPtr; FOREACH(mixPtr, oPtr->mixins) { if (mixinPtr == mixPtr) { RemoveItem(Class, oPtr->mixins, i); @@ -1450,11 +1507,12 @@ TclOORemoveFromSubclasses( Class *subPtr, /* The subclass to remove. */ Class *superPtr) /* The superclass to possibly remove the * subclass reference from. */ { - int i, res = 0; + Tcl_Size i; + int res = 0; Class *subclsPtr; FOREACH(subclsPtr, superPtr->subclasses) { if (subPtr == subclsPtr) { RemoveItem(Class, superPtr->subclasses, i); @@ -1514,11 +1572,12 @@ TclOORemoveFromMixinSubs( Class *subPtr, /* The subclass to remove. */ Class *superPtr) /* The superclass to possibly remove the * subclass reference from. */ { - int i, res = 0; + Tcl_Size i; + int res = 0; Class *subclsPtr; FOREACH(subclsPtr, superPtr->mixinSubs) { if (subPtr == subclsPtr) { RemoveItem(Class, superPtr->mixinSubs, i); @@ -1654,19 +1713,19 @@ const char *nameStr, /* Name of object to create, or NULL to ask * the code to pick its own unique name. */ const char *nsNameStr, /* Name of namespace to create inside object, * or NULL to ask the code to pick its own * unique name. */ - int objc, /* Number of arguments. Negative value means + Tcl_Size objc, /* Number of arguments. Negative value means * do not call constructor. */ Tcl_Obj *const *objv, /* Argument list. */ - int skip) /* Number of arguments to _not_ pass to the + Tcl_Size skip) /* Number of arguments to _not_ pass to the * constructor. */ { Class *classPtr = (Class *) cls; Object *oPtr; - ClientData clientData[4]; + void *clientData[4]; oPtr = TclNewObjectInstanceCommon(interp, classPtr, nameStr, nsNameStr); if (oPtr == NULL) { return NULL; } @@ -1674,11 +1733,11 @@ /* * Run constructors, except when objc < 0, which is a special flag case * used for object cloning only. */ - if (objc >= 0) { + if (objc != TCL_INDEX_NONE) { CallContext *contextPtr = TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL, NULL, NULL); if (contextPtr != NULL) { int isRoot, result; @@ -1722,14 +1781,14 @@ const char *nameStr, /* Name of object to create, or NULL to ask * the code to pick its own unique name. */ const char *nsNameStr, /* Name of namespace to create inside object, * or NULL to ask the code to pick its own * unique name. */ - int objc, /* Number of arguments. Negative value means + Tcl_Size objc, /* Number of arguments. Negative value means * do not call constructor. */ Tcl_Obj *const *objv, /* Argument list. */ - int skip, /* Number of arguments to _not_ pass to the + Tcl_Size skip, /* Number of arguments to _not_ pass to the * constructor. */ Tcl_Object *objectPtr) /* Place to write the object reference upon * successful allocation. */ { Class *classPtr = (Class *) cls; @@ -1741,11 +1800,11 @@ if (oPtr == NULL) { return TCL_ERROR; } /* - * Run constructors, except when objc < 0 (a special flag case used for + * Run constructors, except when objc == TCL_INDEX_NONE (a special flag case used for * object cloning only). If there aren't any constructors, we do nothing. */ if (objc < 0) { *objectPtr = (Tcl_Object) oPtr; @@ -1804,11 +1863,11 @@ hPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simpleName); if (hPtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create object \"%s\": command already exists with" " that name", nameStr)); - Tcl_SetErrorCode(interp, "TCL", "OO", "OVERWRITE_OBJECT", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "OVERWRITE_OBJECT", (void *)NULL); return NULL; } } /* @@ -1841,11 +1900,11 @@ return oPtr; } static int FinalizeAlloc( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { CallContext *contextPtr = (CallContext *)data[0]; Object *oPtr = (Object *)data[1]; @@ -1858,11 +1917,11 @@ */ if (result != TCL_ERROR && Destructing(oPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "object deleted in constructor", -1)); - Tcl_SetErrorCode(interp, "TCL", "OO", "STILLBORN", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "STILLBORN", (void *)NULL); result = TCL_ERROR; } if (result != TCL_OK) { Tcl_DiscardInterpState(state); @@ -1919,29 +1978,30 @@ Method *mPtr; Class *mixinPtr; CallContext *contextPtr; Tcl_Obj *keyPtr, *filterObj, *variableObj, *args[3]; PrivateVariableMapping *privateVariable; - int i, result; + 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", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CLONING_CLASS", (void *)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, + (Tcl_Class) oPtr->selfCls, targetName, targetNamespaceName, TCL_INDEX_NONE, NULL, -1); if (o2Ptr == NULL) { return NULL; } @@ -2023,11 +2083,11 @@ * Copy the object's metadata. */ if (oPtr->metadataPtr != NULL) { Tcl_ObjectMetadataType *metadataTypePtr; - ClientData value, duplicate; + void *value, *duplicate; FOREACH_HASH(metadataTypePtr, value, oPtr->metadataPtr) { if (metadataTypePtr->cloneProc == NULL) { duplicate = value; } else { @@ -2168,11 +2228,11 @@ * Duplicate the class's metadata. */ if (clsPtr->metadataPtr != NULL) { Tcl_ObjectMetadataType *metadataTypePtr; - ClientData value, duplicate; + void *value, *duplicate; FOREACH_HASH(metadataTypePtr, value, clsPtr->metadataPtr) { if (metadataTypePtr->cloneProc == NULL) { duplicate = value; } else { @@ -2237,23 +2297,23 @@ Object *oPtr, Method *mPtr, Tcl_Obj *namePtr) { if (mPtr->typePtr == NULL) { - Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr, + TclNewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr, mPtr->flags & PUBLIC_METHOD, NULL, NULL); } else if (mPtr->typePtr->cloneProc) { - ClientData newClientData; + void *newClientData; if (mPtr->typePtr->cloneProc(interp, mPtr->clientData, &newClientData) != TCL_OK) { return TCL_ERROR; } - Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr, + TclNewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, newClientData); } else { - Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr, + TclNewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, mPtr->clientData); } return TCL_OK; } @@ -2266,24 +2326,24 @@ Method **m2PtrPtr) { Method *m2Ptr; if (mPtr->typePtr == NULL) { - m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, + m2Ptr = (Method *) TclNewMethod(interp, (Tcl_Class) clsPtr, namePtr, mPtr->flags & PUBLIC_METHOD, NULL, NULL); } else if (mPtr->typePtr->cloneProc) { - ClientData newClientData; + void *newClientData; if (mPtr->typePtr->cloneProc(interp, mPtr->clientData, &newClientData) != TCL_OK) { return TCL_ERROR; } - m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, + m2Ptr = (Method *) TclNewMethod(interp, (Tcl_Class) clsPtr, namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, newClientData); } else { - m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, + m2Ptr = (Method *) TclNewMethod(interp, (Tcl_Class) clsPtr, namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, mPtr->clientData); } if (m2PtrPtr != NULL) { *m2PtrPtr = m2Ptr; @@ -2315,11 +2375,11 @@ * metadata type. * * ---------------------------------------------------------------------- */ -ClientData +void * Tcl_ClassGetMetadata( Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr) { Class *clsPtr = (Class *) clazz; @@ -2336,11 +2396,11 @@ /* * There is a metadata store, so look in it for the given type. */ - hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, (char *) typePtr); + hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, typePtr); /* * Return the metadata value if we found it, otherwise NULL. */ @@ -2352,11 +2412,11 @@ void Tcl_ClassSetMetadata( Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr, - ClientData metadata) + void *metadata) { Class *clsPtr = (Class *) clazz; Tcl_HashEntry *hPtr; int isNew; @@ -2375,11 +2435,11 @@ /* * If the metadata is NULL, we're deleting the metadata for the type. */ if (metadata == NULL) { - hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, (char *) typePtr); + hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, typePtr); if (hPtr != NULL) { typePtr->deleteProc(Tcl_GetHashValue(hPtr)); Tcl_DeleteHashEntry(hPtr); } return; @@ -2388,18 +2448,18 @@ /* * Otherwise we're attaching the metadata. Note that if there was already * some metadata attached of this type, we delete that first. */ - hPtr = Tcl_CreateHashEntry(clsPtr->metadataPtr, (char *) typePtr, &isNew); + hPtr = Tcl_CreateHashEntry(clsPtr->metadataPtr, typePtr, &isNew); if (!isNew) { typePtr->deleteProc(Tcl_GetHashValue(hPtr)); } Tcl_SetHashValue(hPtr, metadata); } -ClientData +void * Tcl_ObjectGetMetadata( Tcl_Object object, const Tcl_ObjectMetadataType *typePtr) { Object *oPtr = (Object *) object; @@ -2416,11 +2476,11 @@ /* * There is a metadata store, so look in it for the given type. */ - hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, (char *) typePtr); + hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, typePtr); /* * Return the metadata value if we found it, otherwise NULL. */ @@ -2432,11 +2492,11 @@ void Tcl_ObjectSetMetadata( Tcl_Object object, const Tcl_ObjectMetadataType *typePtr, - ClientData metadata) + void *metadata) { Object *oPtr = (Object *) object; Tcl_HashEntry *hPtr; int isNew; @@ -2455,11 +2515,11 @@ /* * If the metadata is NULL, we're deleting the metadata for the type. */ if (metadata == NULL) { - hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, (char *) typePtr); + hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, typePtr); if (hPtr != NULL) { typePtr->deleteProc(Tcl_GetHashValue(hPtr)); Tcl_DeleteHashEntry(hPtr); } return; @@ -2468,11 +2528,11 @@ /* * Otherwise we're attaching the metadata. Note that if there was already * some metadata attached of this type, we delete that first. */ - hPtr = Tcl_CreateHashEntry(oPtr->metadataPtr, (char *) typePtr, &isNew); + hPtr = Tcl_CreateHashEntry(oPtr->metadataPtr, typePtr, &isNew); if (!isNew) { typePtr->deleteProc(Tcl_GetHashValue(hPtr)); } Tcl_SetHashValue(hPtr, metadata); } @@ -2490,21 +2550,21 @@ * ---------------------------------------------------------------------- */ int TclOOPublicObjectCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return Tcl_NRCallObjProc(interp, PublicNRObjectCmd, clientData,objc,objv); } static int PublicNRObjectCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return TclOOObjectCmdCore((Object *)clientData, interp, objc, objv, PUBLIC_METHOD, @@ -2511,21 +2571,21 @@ NULL); } int TclOOPrivateObjectCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return Tcl_NRCallObjProc(interp, PrivateNRObjectCmd,clientData,objc,objv); } static int PrivateNRObjectCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return TclOOObjectCmdCore((Object *)clientData, interp, objc, objv, 0, NULL); @@ -2542,11 +2602,11 @@ int publicPrivate, /* Whether this is an invoke from a public * context (PUBLIC_METHOD), a private context * (PRIVATE_METHOD), or a *really* private * context (any other value; conventionally * 0). */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* Array of argument objects. It is assumed * that the name of the method to invoke will * be at index 1. */ { switch (publicPrivate) { @@ -2572,21 +2632,21 @@ * ---------------------------------------------------------------------- */ int TclOOMyClassObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return Tcl_NRCallObjProc(interp, MyClassNRObjCmd, clientData, objc, objv); } static int MyClassNRObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *)clientData; @@ -2613,11 +2673,11 @@ int TclOOObjectCmdCore( Object *oPtr, /* The object being invoked. */ Tcl_Interp *interp, /* The interpreter containing the object. */ - int objc, /* How many arguments are being passed in. */ + Tcl_Size objc, /* How many arguments are being passed in. */ Tcl_Obj *const *objv, /* The array of arguments. */ int flags, /* Whether this is an invocation through the * public or the private command interface. */ Class *startCls) /* Where to start in the call chain, or NULL * if we are to start at the front with @@ -2693,11 +2753,11 @@ if (contextPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "impossible to invoke method \"%s\": no defined method or" " unknown method", TclGetString(methodNamePtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD_MAPPED", - TclGetString(methodNamePtr), NULL); + TclGetString(methodNamePtr), (void *)NULL); return TCL_ERROR; } } else { /* * Get the call chain. @@ -2710,11 +2770,11 @@ if (contextPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "impossible to invoke method \"%s\": no defined method or" " unknown method", TclGetString(methodNamePtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", - TclGetString(methodNamePtr), NULL); + TclGetString(methodNamePtr), (void *)NULL); return TCL_ERROR; } } /* @@ -2737,11 +2797,11 @@ } 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); + TclGetString(methodNamePtr), (void *)NULL); TclOODeleteContext(contextPtr); return TCL_ERROR; } } @@ -2754,11 +2814,11 @@ return TclOOInvokeContext(contextPtr, interp, objc, objv); } static int FinalizeObjectCall( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { /* * Dispose of the call chain, which drops the lock on the object's @@ -2785,17 +2845,17 @@ int Tcl_ObjectContextInvokeNext( Tcl_Interp *interp, Tcl_ObjectContext context, - int objc, + Tcl_Size objc, Tcl_Obj *const *objv, - int skip) + Tcl_Size skip) { CallContext *contextPtr = (CallContext *) context; - int savedIndex = contextPtr->index; - int savedSkip = contextPtr->skip; + size_t savedIndex = contextPtr->index; + size_t savedSkip = contextPtr->skip; int result; if (contextPtr->index + 1 >= contextPtr->callPtr->numChain) { /* * We're at the end of the chain; generate an error message unless the @@ -2818,11 +2878,11 @@ methodType = "method"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "no next %s implementation", methodType)); - Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", (void *)NULL); return TCL_ERROR; } /* * Advance to the next method implementation in the chain in the method @@ -2857,13 +2917,13 @@ int TclNRObjectContextInvokeNext( Tcl_Interp *interp, Tcl_ObjectContext context, - int objc, + Tcl_Size objc, Tcl_Obj *const *objv, - int skip) + Tcl_Size skip) { CallContext *contextPtr = (CallContext *) context; if (contextPtr->index + 1 >= contextPtr->callPtr->numChain) { /* @@ -2887,11 +2947,11 @@ methodType = "method"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "no next %s implementation", methodType)); - Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", (void *)NULL); return TCL_ERROR; } /* * Advance to the next method implementation in the chain in the method @@ -2915,11 +2975,11 @@ return TclOOInvokeContext(contextPtr, interp, objc, objv); } static int FinalizeNext( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { CallContext *contextPtr = (CallContext *)data[0]; @@ -2966,11 +3026,11 @@ notAnObject: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s does not refer to an object", TclGetString(objPtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "OBJECT", TclGetString(objPtr), - NULL); + (void *)NULL); return NULL; } /* * ---------------------------------------------------------------------- @@ -2986,11 +3046,11 @@ int TclOOIsReachable( Class *targetPtr, Class *startPtr) { - int i; + Tcl_Size i; Class *superPtr; tailRecurse: if (startPtr == targetPtr) { return 1; @@ -3079,11 +3139,11 @@ Tcl_ObjectContext context) { return (Tcl_Object) ((CallContext *)context)->oPtr; } -int +Tcl_Size Tcl_ObjectContextSkippedArgs( Tcl_ObjectContext context) { return ((CallContext *)context)->skip; } @@ -3135,13 +3195,33 @@ 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: */ Index: generic/tclOO.decls ================================================================== --- generic/tclOO.decls +++ generic/tclOO.decls @@ -3,11 +3,11 @@ # This file contains the declarations for all supported public functions # that are exported by the TclOO package that is embedded within the Tcl # library via the stubs table. This file is used to generate the # tclOODecls.h, tclOOIntDecls.h and tclOOStubInit.c files. # -# Copyright (c) 2008-2013 by Donal K. Fellows. +# Copyright © 2008-2013 Donal K. Fellows. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. library tclOO @@ -66,12 +66,12 @@ Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr, void *clientData) } declare 13 { Tcl_Object Tcl_NewObjectInstance(Tcl_Interp *interp, Tcl_Class cls, - const char *nameStr, const char *nsNameStr, int objc, - Tcl_Obj *const *objv, int skip) + const char *nameStr, const char *nsNameStr, Tcl_Size objc, + Tcl_Obj *const *objv, Tcl_Size skip) } declare 14 { int Tcl_ObjectDeleted(Tcl_Object object) } declare 15 { @@ -82,11 +82,11 @@ } declare 17 { Tcl_Object Tcl_ObjectContextObject(Tcl_ObjectContext context) } declare 18 { - int Tcl_ObjectContextSkippedArgs(Tcl_ObjectContext context) + Tcl_Size Tcl_ObjectContextSkippedArgs(Tcl_ObjectContext context) } declare 19 { void *Tcl_ClassGetMetadata(Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr) } @@ -102,12 +102,12 @@ void Tcl_ObjectSetMetadata(Tcl_Object object, const Tcl_ObjectMetadataType *typePtr, void *metadata) } declare 23 { int Tcl_ObjectContextInvokeNext(Tcl_Interp *interp, - Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv, - int skip) + Tcl_ObjectContext context, Tcl_Size objc, Tcl_Obj *const *objv, + Tcl_Size skip) } declare 24 { Tcl_ObjectMapMethodNameProc *Tcl_ObjectGetMethodNameMapper( Tcl_Object object) } @@ -127,10 +127,30 @@ 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. @@ -162,11 +182,11 @@ Method *TclOONewProcMethod(Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr) } declare 5 { - int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp, int objc, + int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv, int publicOnly, Class *startCls) } declare 6 { int TclOOIsReachable(Class *targetPtr, Class *startPtr) } @@ -192,30 +212,30 @@ Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr) } declare 11 { int TclOOInvokeObject(Tcl_Interp *interp, Tcl_Object object, - Tcl_Class startCls, int publicPrivate, int objc, + Tcl_Class startCls, int publicPrivate, Tcl_Size objc, Tcl_Obj *const *objv) } declare 12 { - void TclOOObjectSetFilters(Object *oPtr, int numFilters, + void TclOOObjectSetFilters(Object *oPtr, Tcl_Size numFilters, Tcl_Obj *const *filters) } declare 13 { void TclOOClassSetFilters(Tcl_Interp *interp, Class *classPtr, - int numFilters, Tcl_Obj *const *filters) + Tcl_Size numFilters, Tcl_Obj *const *filters) } declare 14 { - void TclOOObjectSetMixins(Object *oPtr, int numMixins, + void TclOOObjectSetMixins(Object *oPtr, Tcl_Size numMixins, Class *const *mixins) } declare 15 { void TclOOClassSetMixins(Tcl_Interp *interp, Class *classPtr, - int numMixins, Class *const *mixins) + Tcl_Size numMixins, Class *const *mixins) } return # Local Variables: # mode: tcl # End: Index: generic/tclOO.h ================================================================== --- generic/tclOO.h +++ generic/tclOO.h @@ -22,12 +22,12 @@ * tests/ooNext2.test * unix/tclooConfig.sh * win/tclooConfig.sh */ -#define TCLOO_VERSION "1.2.0" -#define TCLOO_PATCHLEVEL TCLOO_VERSION +#define TCLOO_VERSION "1.3" +#define TCLOO_PATCHLEVEL TCLOO_VERSION ".0" #include "tcl.h" /* * For C++ compilers, use extern "C" @@ -38,11 +38,11 @@ #endif extern const char *TclOOInitializeStubs( Tcl_Interp *, const char *version); #define Tcl_OOInitStubs(interp) \ - TclOOInitializeStubs((interp), TCLOO_VERSION) + TclOOInitializeStubs((interp), TCLOO_PATCHLEVEL) #ifndef USE_TCL_STUBS # define TclOOInitializeStubs(interp, version) (TCLOO_PATCHLEVEL) #endif /* @@ -60,10 +60,16 @@ * 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, @@ -75,11 +81,11 @@ * 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 + * 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. */ @@ -90,16 +96,39 @@ 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. Index: generic/tclOOBasic.c ================================================================== --- generic/tclOOBasic.c +++ generic/tclOOBasic.c @@ -2,11 +2,11 @@ * tclOOBasic.c -- * * This file contains implementations of the "simple" commands and * methods from the object-system core. * - * Copyright (c) 2005-2013 by Donal K. Fellows + * Copyright © 2005-2013 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -13,10 +13,11 @@ #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; @@ -49,11 +50,11 @@ return (Tcl_Object *) &(TOP_CB(interp)->data[0]); } static int FinalizeConstruction( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Object *oPtr = (Object *)data[0]; @@ -74,24 +75,25 @@ * ---------------------------------------------------------------------- */ int TclOO_Class_Constructor( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) Tcl_ObjectContextObject(context); Tcl_Obj **invoke, *nameObj; - if (objc-1 > Tcl_ObjectContextSkippedArgs(context)) { - Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, + size_t skip = Tcl_ObjectContextSkippedArgs(context); + if ((size_t)objc > skip + 1) { + Tcl_WrongNumArgs(interp, skip, objv, "?definitionScript?"); return TCL_ERROR; - } else if (objc == Tcl_ObjectContextSkippedArgs(context)) { + } else if ((size_t)objc == skip) { return TCL_OK; } /* * Make the class definition delegate. This is special; it doesn't reenter @@ -132,11 +134,11 @@ return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL); } static int DecrRefsPostClassConstructor( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Tcl_Obj **invoke = (Tcl_Obj **)data[0]; Object *oPtr = (Object *)data[1]; @@ -172,20 +174,20 @@ * ---------------------------------------------------------------------- */ int TclOO_Class_Create( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Object *oPtr = (Object *) Tcl_ObjectContextObject(context); const char *objName; - size_t len; + Tcl_Size len; /* * Sanity check; should not be possible to invoke this method on a * non-class. */ @@ -193,29 +195,29 @@ if (oPtr->classPtr == NULL) { Tcl_Obj *cmdnameObj = TclOOObjectName(interp, oPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "object \"%s\" is not a class", TclGetString(cmdnameObj))); - Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", (void *)NULL); return TCL_ERROR; } /* * Check we have the right number of (sensible) arguments. */ - if (objc - Tcl_ObjectContextSkippedArgs(context) < 1) { + if (objc < 1 + Tcl_ObjectContextSkippedArgs(context)) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "objectName ?arg ...?"); return TCL_ERROR; } - objName = TclGetStringFromObj( + objName = Tcl_GetStringFromObj( objv[Tcl_ObjectContextSkippedArgs(context)], &len); if (len == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "object name must not be empty", -1)); - Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", (void *)NULL); return TCL_ERROR; } /* * Make the object and return its name. @@ -237,20 +239,20 @@ * ---------------------------------------------------------------------- */ int TclOO_Class_CreateNs( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Object *oPtr = (Object *) Tcl_ObjectContextObject(context); const char *objName, *nsName; - size_t len; + Tcl_Size len; /* * Sanity check; should not be possible to invoke this method on a * non-class. */ @@ -258,37 +260,37 @@ if (oPtr->classPtr == NULL) { Tcl_Obj *cmdnameObj = TclOOObjectName(interp, oPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "object \"%s\" is not a class", TclGetString(cmdnameObj))); - Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", (void *)NULL); return TCL_ERROR; } /* * Check we have the right number of (sensible) arguments. */ - if (objc - Tcl_ObjectContextSkippedArgs(context) < 2) { + if (objc + 1 < Tcl_ObjectContextSkippedArgs(context) + 3) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "objectName namespaceName ?arg ...?"); return TCL_ERROR; } - objName = TclGetStringFromObj( + objName = Tcl_GetStringFromObj( objv[Tcl_ObjectContextSkippedArgs(context)], &len); if (len == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "object name must not be empty", -1)); - Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", (void *)NULL); return TCL_ERROR; } - nsName = TclGetStringFromObj( + nsName = Tcl_GetStringFromObj( objv[Tcl_ObjectContextSkippedArgs(context)+1], &len); if (len == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "namespace name must not be empty", -1)); - Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", (void *)NULL); return TCL_ERROR; } /* * Make the object and return its name. @@ -310,11 +312,11 @@ * ---------------------------------------------------------------------- */ int TclOO_Class_New( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ @@ -329,11 +331,11 @@ if (oPtr->classPtr == NULL) { Tcl_Obj *cmdnameObj = TclOOObjectName(interp, oPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "object \"%s\" is not a class", TclGetString(cmdnameObj))); - Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", (void *)NULL); return TCL_ERROR; } /* * Make the object and return its name. @@ -354,21 +356,21 @@ * ---------------------------------------------------------------------- */ int TclOO_Object_Destroy( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Object *oPtr = (Object *) Tcl_ObjectContextObject(context); CallContext *contextPtr; - if (objc != Tcl_ObjectContextSkippedArgs(context)) { + if (objc != (int)Tcl_ObjectContextSkippedArgs(context)) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; } if (!(oPtr->flags & DESTRUCTOR_CALLED)) { @@ -390,11 +392,11 @@ return TCL_OK; } static int AfterNRDestructor( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { CallContext *contextPtr = (CallContext *)data[0]; @@ -415,25 +417,25 @@ * ---------------------------------------------------------------------- */ int TclOO_Object_Eval( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { CallContext *contextPtr = (CallContext *) context; Tcl_Object object = Tcl_ObjectContextObject(context); - const int skip = Tcl_ObjectContextSkippedArgs(context); + size_t skip = Tcl_ObjectContextSkippedArgs(context); CallFrame *framePtr, **framePtrPtr = &framePtr; Tcl_Obj *scriptPtr; CmdFrame *invoker; - if (objc-1 < skip) { + if ((size_t)objc < skip + 1) { Tcl_WrongNumArgs(interp, skip, objv, "arg ?arg ...?"); return TCL_ERROR; } /* @@ -457,11 +459,11 @@ * When there's more than one argument, we concatenate them together with * spaces between, then evaluate the result. Tcl_EvalObjEx will delete the * object when it decrements its refcount after eval'ing it. */ - if (objc != skip+1) { + if ((size_t)objc != skip+1) { scriptPtr = Tcl_ConcatObj(objc-skip, objv+skip); invoker = NULL; } else { scriptPtr = objv[skip]; invoker = ((Interp *) interp)->cmdFramePtr; @@ -476,11 +478,11 @@ return TclNREvalObjEx(interp, scriptPtr, 0, invoker, skip); } static int FinalizeEval( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { if (result == TCL_ERROR) { Object *oPtr = (Object *)data[0]; @@ -516,11 +518,11 @@ * ---------------------------------------------------------------------- */ int TclOO_Object_Unknown( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ @@ -528,21 +530,22 @@ CallContext *contextPtr = (CallContext *) context; Object *callerObj = NULL; Class *callerCls = NULL; Object *oPtr = contextPtr->oPtr; const char **methodNames; - int numMethodNames, i, skip = Tcl_ObjectContextSkippedArgs(context); + 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 (objc < skip+1) { + if ((size_t)objc < skip+1) { Tcl_WrongNumArgs(interp, skip, objv, "method ?arg ...?"); return TCL_ERROR; } /* @@ -587,11 +590,11 @@ piece = "methods"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "object \"%s\" has no %s", TclGetString(tmpBuf), piece)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", - TclGetString(objv[skip]), NULL); + TclGetString(objv[skip]), (void *)NULL); return TCL_ERROR; } errorMsg = Tcl_ObjPrintf("unknown method \"%s\": must be ", TclGetString(objv[skip])); @@ -606,11 +609,11 @@ } Tcl_AppendToObj(errorMsg, methodNames[i], -1); Tcl_Free((void *)methodNames); Tcl_SetObjResult(interp, errorMsg); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", - TclGetString(objv[skip]), NULL); + TclGetString(objv[skip]), (void *)NULL); return TCL_ERROR; } /* * ---------------------------------------------------------------------- @@ -622,23 +625,23 @@ * ---------------------------------------------------------------------- */ int TclOO_Object_LinkVar( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Interp *iPtr = (Interp *) interp; Tcl_Object object = Tcl_ObjectContextObject(context); Namespace *savedNsPtr; - int i; + Tcl_Size i; - if (objc-Tcl_ObjectContextSkippedArgs(context) < 0) { + if (objc < Tcl_ObjectContextSkippedArgs(context)) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "?varName ...?"); return TCL_ERROR; } @@ -650,11 +653,11 @@ if (iPtr->varFramePtr == NULL) { return TCL_OK; } - for (i=Tcl_ObjectContextSkippedArgs(context) ; ivarFramePtr; const char *arg; - if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) { + if ((int)Tcl_ObjectContextSkippedArgs(context)+1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "varName"); return TCL_ERROR; } argPtr = objv[objc-1]; @@ -775,11 +778,11 @@ Object *oPtr = (Object *) Tcl_ObjectContextObject(context); CallContext *callerContext = (CallContext *)framePtr->clientData; Method *mPtr = callerContext->callPtr->chain[ callerContext->index].mPtr; PrivateVariableMapping *pvPtr; - int i; + Tcl_Size i; if (mPtr->declaringObjectPtr == oPtr) { FOREACH_STRUCT(pvPtr, oPtr->privateVariables) { if (!strcmp(TclGetString(pvPtr->variableObj), TclGetString(argPtr))) { @@ -820,11 +823,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", arg, (void *)NULL); return TCL_ERROR; } /* * Now that we've pinned down what variable we're really talking about @@ -862,11 +865,11 @@ * ---------------------------------------------------------------------- */ int TclOONextObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; @@ -881,11 +884,11 @@ if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s may only be called from inside a method", TclGetString(objv[0]))); - Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (void *)NULL); return TCL_ERROR; } context = (Tcl_ObjectContext)framePtr->clientData; /* @@ -898,20 +901,20 @@ return TclNRObjectContextInvokeNext(interp, context, objc, objv, 1); } int TclOONextToObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; CallFrame *framePtr = iPtr->varFramePtr; Class *classPtr; CallContext *contextPtr; - int i; + Tcl_Size i; Tcl_Object object; const char *methodType; /* * Start with sanity checks on the calling context to make sure that we @@ -921,11 +924,11 @@ if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s may only be called from inside a method", TclGetString(objv[0]))); - Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (void *)NULL); return TCL_ERROR; } contextPtr = (CallContext *)framePtr->clientData; /* @@ -942,11 +945,11 @@ } classPtr = ((Object *)object)->classPtr; if (classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(objv[1]))); - Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", (void *)NULL); return TCL_ERROR; } /* * Search for an implementation of a method associated with the current @@ -983,41 +986,41 @@ methodType = "destructor"; } else { methodType = "method"; } - for (i=contextPtr->index ; i>=0 ; i--) { + 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", - NULL); + (void *)NULL); return TCL_ERROR; } } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s has no non-filter implementation by \"%s\"", methodType, TclGetString(objv[1]))); - Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", (void *)NULL); return TCL_ERROR; } static int NextRestoreFrame( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; CallContext *contextPtr = (CallContext *)data[1]; iPtr->varFramePtr = (CallFrame *)data[0]; if (contextPtr != NULL) { - contextPtr->index = PTR2INT(data[2]); + contextPtr->index = PTR2UINT(data[2]); } return result; } /* @@ -1031,11 +1034,11 @@ * ---------------------------------------------------------------------- */ int TclOOSelfObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { static const char *const subcmds[] = { @@ -1043,16 +1046,15 @@ "object", "target", NULL }; enum SelfCmds { SELF_CALL, SELF_CALLER, SELF_CLASS, SELF_FILTER, SELF_METHOD, SELF_NS, SELF_NEXT, SELF_OBJECT, SELF_TARGET - }; + } index; Interp *iPtr = (Interp *) interp; CallFrame *framePtr = iPtr->varFramePtr; CallContext *contextPtr; Tcl_Obj *result[3]; - int index; #define CurrentlyInvoked(contextPtr) \ ((contextPtr)->callPtr->chain[(contextPtr)->index]) /* @@ -1061,11 +1063,11 @@ if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s may only be called from inside a method", TclGetString(objv[0]))); - Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (void *)NULL); return TCL_ERROR; } contextPtr = (CallContext*)framePtr->clientData; @@ -1082,25 +1084,25 @@ } else if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "subcommand", 0, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum SelfCmds) index) { + switch (index) { case SELF_OBJECT: Tcl_SetObjResult(interp, TclOOObjectName(interp, contextPtr->oPtr)); return TCL_OK; case SELF_NS: Tcl_SetObjResult(interp, Tcl_NewStringObj( - contextPtr->oPtr->namespacePtr->fullName,-1)); + 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, TclOOObjectName(interp, clsPtr->thisPtr)); return TCL_OK; @@ -1117,11 +1119,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", (void *)NULL); return TCL_ERROR; } else { struct MInvoke *miPtr = &CurrentlyInvoked(contextPtr); Object *oPtr; const char *type; @@ -1143,11 +1145,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", (void *)NULL); return TCL_ERROR; } else { CallContext *callerPtr = (CallContext *)framePtr->callerVarPtr->clientData; Method *mPtr = callerPtr->callPtr->chain[callerPtr->index].mPtr; Object *declarerPtr; @@ -1211,16 +1213,16 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", (void *)NULL); return TCL_ERROR; } else { Method *mPtr; Object *declarerPtr; - int i; + Tcl_Size i; for (i=contextPtr->index ; icallPtr->numChain ; i++){ if (!contextPtr->callPtr->chain[i].isFilter) { break; } @@ -1247,11 +1249,11 @@ Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); return TCL_OK; } case SELF_CALL: result[0] = TclOORenderCallChain(interp, contextPtr->callPtr); - TclNewIntObj(result[1], contextPtr->index); + TclNewIndexObj(result[1], contextPtr->index); Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); return TCL_OK; } return TCL_ERROR; } @@ -1268,11 +1270,11 @@ * ---------------------------------------------------------------------- */ int TclOOCopyObjectCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Object oPtr, o2Ptr; Index: generic/tclOOCall.c ================================================================== --- generic/tclOOCall.c +++ generic/tclOOCall.c @@ -1,12 +1,13 @@ /* * tclOOCall.c -- * * This file contains the method call chain management code for the - * object-system core. + * object-system core. It also contains everything else that does + * inheritance hierarchy traversal. * - * Copyright (c) 2005-2012 by Donal K. Fellows + * Copyright © 2005-2019 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -22,11 +23,11 @@ * the construction of the CallContext. */ struct ChainBuilder { CallChain *callChainPtr; /* The call chain being built. */ - int filterLength; /* Number of entries in the call chain that + size_t filterLength; /* Number of entries in the call chain that * are due to processing filters and not the * main call chain. */ Object *oPtr; /* The object that we are building the chain * for. */ }; @@ -56,10 +57,11 @@ #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)) /* @@ -89,11 +91,11 @@ */ 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, +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); @@ -135,11 +137,11 @@ static void FreeMethodNameRep(Tcl_Obj *objPtr); static inline int IsStillValid(CallChain *callPtr, Object *oPtr, int flags, int reuseMask); static Tcl_NRPostProc ResetFilterFlags; static Tcl_NRPostProc SetFilterFlags; -static int SortMethodNames(Tcl_HashTable *namesPtr, int flags, +static size_t SortMethodNames(Tcl_HashTable *namesPtr, int flags, const char ***stringsPtr); static inline void StashCallChain(Tcl_Obj *objPtr, CallChain *callPtr); /* * Object type used to manage type caches attached to method names. @@ -148,11 +150,12 @@ static const Tcl_ObjType methodNameType = { "TclOO method name", FreeMethodNameRep, DupMethodNameRep, NULL, - NULL + NULL, + TCL_OBJTYPE_V0 }; /* * ---------------------------------------------------------------------- @@ -245,16 +248,16 @@ static inline void StashCallChain( Tcl_Obj *objPtr, CallChain *callPtr) { - Tcl_ObjIntRep ir; + Tcl_ObjInternalRep ir; callPtr->refCount++; TclGetString(objPtr); ir.twoPtrValue.ptr1 = callPtr; - Tcl_StoreIntRep(objPtr, &methodNameType, &ir); + Tcl_StoreInternalRep(objPtr, &methodNameType, &ir); } void TclOOStashContext( Tcl_Obj *objPtr, @@ -278,19 +281,19 @@ DupMethodNameRep( Tcl_Obj *srcPtr, Tcl_Obj *dstPtr) { StashCallChain(dstPtr, - (CallChain *)TclFetchIntRep(srcPtr, &methodNameType)->twoPtrValue.ptr1); + (CallChain *)TclFetchInternalRep(srcPtr, &methodNameType)->twoPtrValue.ptr1); } static void FreeMethodNameRep( Tcl_Obj *objPtr) { TclOODeleteChain( - (CallChain *)TclFetchIntRep(objPtr, &methodNameType)->twoPtrValue.ptr1); + (CallChain *)TclFetchInternalRep(objPtr, &methodNameType)->twoPtrValue.ptr1); } /* * ---------------------------------------------------------------------- * @@ -304,11 +307,11 @@ * ---------------------------------------------------------------------- */ int TclOOInvokeContext( - ClientData clientData, /* The method call context. */ + void *clientData, /* The method call context. */ Tcl_Interp *interp, /* Interpreter for error reporting, and many * other sorts of context handling (e.g., * commands, variables) depending on method * implementation. */ int objc, /* The number of arguments. */ @@ -324,11 +327,11 @@ * entries in the chain so that they do not get deleted out from under our * feet. */ if (contextPtr->index == 0) { - int i; + Tcl_Size i; for (i = 0 ; i < contextPtr->callPtr->numChain ; i++) { AddRef(contextPtr->callPtr->chain[i].mPtr); } @@ -367,17 +370,21 @@ /* * Run the method implementation. */ - return mPtr->typePtr->callProc(mPtr->clientData, interp, + 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( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { CallContext *contextPtr = (CallContext *)data[0]; @@ -385,11 +392,11 @@ return result; } static int ResetFilterFlags( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { CallContext *contextPtr = (CallContext *)data[0]; @@ -397,16 +404,16 @@ return result; } static int FinalizeMethodRefs( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { CallContext *contextPtr = (CallContext *)data[0]; - int i; + Tcl_Size i; for (i = 0 ; i < contextPtr->callPtr->numChain ; i++) { TclOODelMethodRef(contextPtr->callPtr->chain[i].mPtr); } return result; @@ -443,11 +450,11 @@ Tcl_HashTable examinedClasses; /* Used to track what classes have been looked * at. Is set-like in nature and keyed by * pointer to class. */ FOREACH_HASH_DECLS; - int i, numStrings; + Tcl_Size i, numStrings; Class *mixinPtr; Tcl_Obj *namePtr; Method *mPtr; Tcl_InitObjHashTable(&names); @@ -519,11 +526,11 @@ numStrings = SortMethodNames(&names, flags, stringsPtr); Tcl_DeleteHashTable(&names); return numStrings; } -int +size_t TclOOGetSortedClassMethodList( Class *clsPtr, /* The class to get the method names for. */ int flags, /* Whether we just want the public method * names. */ const char ***stringsPtr) /* Where to write a pointer to the array of @@ -533,11 +540,11 @@ * mapping. */ Tcl_HashTable examinedClasses; /* Used to track what classes have been looked * at. Is set-like in nature and keyed by * pointer to class. */ - int numStrings; + size_t numStrings; Tcl_InitObjHashTable(&names); Tcl_InitHashTable(&examinedClasses, TCL_ONE_WORD_KEYS); /* @@ -578,11 +585,11 @@ * The length of the sorted list. * * ---------------------------------------------------------------------- */ -static int +static size_t SortMethodNames( Tcl_HashTable *namesPtr, /* The table of names; unsorted, but contains * whether the names are wanted and under what * circumstances. */ int flags, /* Whether we are looking for unexported @@ -669,11 +676,11 @@ */ static void AddClassMethodNames( Class *clsPtr, /* Class to get method names from. */ - const int flags, /* Whether we are interested in just the + int flags, /* Whether we are interested in just the * public method names. */ Tcl_HashTable *const namesPtr, /* Reference to the hash table to put the * information in. The hash table maps the * Tcl_Obj * method name to an integral value @@ -684,18 +691,18 @@ /* Hash table that tracks what classes have * already been looked at. The keys are the * pointers to the classes, and the values are * immaterial. */ { - int i; + Tcl_Size i; /* * If we've already started looking at this class, stop working on it now * to prevent repeated work. */ - if (Tcl_FindHashEntry(examinedClassesPtr, (char *) clsPtr)) { + if (Tcl_FindHashEntry(examinedClassesPtr, clsPtr)) { return; } /* * Scope all declarations so that the compiler can stand a good chance of @@ -708,11 +715,11 @@ FOREACH_HASH_DECLS; Tcl_Obj *namePtr; Method *mPtr; int isNew; - (void) Tcl_CreateHashEntry(examinedClassesPtr, (char *) clsPtr, + (void) Tcl_CreateHashEntry(examinedClassesPtr, clsPtr, &isNew); if (!isNew) { break; } @@ -767,11 +774,11 @@ FOREACH_HASH(namePtr, mPtr, methodsTablePtr) { if (IS_PRIVATE(mPtr)) { int isNew; - hPtr = Tcl_CreateHashEntry(namesPtr, (char *) namePtr, &isNew); + hPtr = Tcl_CreateHashEntry(namesPtr, namePtr, &isNew); Tcl_SetHashValue(hPtr, INT2PTR(IN_LIST)); } } } @@ -783,11 +790,11 @@ Tcl_HashTable *namesPtr) { if (!IS_PRIVATE(mPtr)) { int isNew; Tcl_HashEntry *hPtr = - Tcl_CreateHashEntry(namesPtr, (char *) namePtr, &isNew); + Tcl_CreateHashEntry(namesPtr, namePtr, &isNew); if (isNew) { int isWanted = (!WANT_PUBLIC(flags) || IS_PUBLIC(mPtr)) ? IN_LIST : 0; @@ -831,11 +838,11 @@ Tcl_HashEntry *hPtr; Method *mPtr; int donePrivate = 0; if (oPtr->methodsPtr) { - hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) methodName); + hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, methodName); if (hPtr != NULL) { mPtr = (Method *)Tcl_GetHashValue(hPtr); if (IS_PRIVATE(mPtr)) { AddMethodToCallChain(mPtr, cbPtr, NULL, NULL, flags); donePrivate = 1; @@ -875,16 +882,17 @@ 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_Size i; + int foundPrivate = 0, blockedUnexported = 0; Tcl_HashEntry *hPtr; Method *mPtr; if (!(flags & (KNOWN_STATE | SPECIAL)) && oPtr->methodsPtr) { - hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) methodNameObj); + hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, methodNameObj); if (hPtr != NULL) { mPtr = (Method *)Tcl_GetHashValue(hPtr); if (!IS_PRIVATE(mPtr)) { if (WANT_PUBLIC(flags)) { @@ -911,11 +919,11 @@ foundPrivate |= AddSimpleClassChainToCallContext(mixinPtr, methodNameObj, cbPtr, doneFilters, flags | TRAVERSED_MIXIN, filterDecl); } if (oPtr->methodsPtr && !blockedUnexported) { - hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *)methodNameObj); + hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, methodNameObj); if (hPtr != NULL) { mPtr = (Method *)Tcl_GetHashValue(hPtr); if (!IS_PRIVATE(mPtr)) { AddMethodToCallChain(mPtr, cbPtr, doneFilters, filterDecl, flags); @@ -967,11 +975,11 @@ * and we have passed a mixin, or we're not * looking to add things from a mixin and have * not passed a mixin. */ { CallChain *callPtr = cbPtr->callChainPtr; - int i; + Tcl_Size i; /* * Return if this is just an entry used to record whether this is a public * method. If so, there's nothing real to call and so nothing to add to * the call chain. @@ -1088,11 +1096,11 @@ * Calculates whether the given call chain can be used for executing a * method for the given object. The condition on a chain from a cached * location being reusable is: * - Refers to the same object (same creation epoch), and * - Still across the same class structure (same global epoch), and - * - Still across the same object strucutre (same local epoch), and + * - Still across the same object structure (same local epoch), and * - No public/private/filter magic leakage (same flags, modulo the fact * that a public chain will satisfy a non-public call). * * ---------------------------------------------------------------------- */ @@ -1147,11 +1155,12 @@ * methodNameObj. */ { CallContext *contextPtr; CallChain *callPtr; struct ChainBuilder cb; - int i, count, doFilters, donePrivate = 0; + Tcl_Size i, count; + int doFilters, donePrivate = 0; Tcl_HashEntry *hPtr; Tcl_HashTable doneFilters; if (cacheInThisObj == NULL) { cacheInThisObj = methodNameObj; @@ -1187,33 +1196,33 @@ * of the cache. This is made a bit more complex by the fact that * there are multiple different layers of cache (in the Tcl_Obj, in * the object, and in the class). */ - const Tcl_ObjIntRep *irPtr; + const Tcl_ObjInternalRep *irPtr; const int reuseMask = (WANT_PUBLIC(flags) ? ~0 : ~PUBLIC_METHOD); - if ((irPtr = TclFetchIntRep(cacheInThisObj, &methodNameType))) { + if ((irPtr = TclFetchInternalRep(cacheInThisObj, &methodNameType))) { callPtr = (CallChain *)irPtr->twoPtrValue.ptr1; if (IsStillValid(callPtr, oPtr, flags, reuseMask)) { callPtr->refCount++; goto returnContext; } - Tcl_StoreIntRep(cacheInThisObj, &methodNameType, NULL); + Tcl_StoreInternalRep(cacheInThisObj, &methodNameType, NULL); } if (oPtr->flags & USE_CLASS_CACHE) { if (oPtr->selfCls->classChainCache != NULL) { hPtr = Tcl_FindHashEntry(oPtr->selfCls->classChainCache, - (char *) methodNameObj); + methodNameObj); } else { hPtr = NULL; } } else { if (oPtr->chainCache != NULL) { hPtr = Tcl_FindHashEntry(oPtr->chainCache, - (char *) methodNameObj); + methodNameObj); } else { hPtr = NULL; } } @@ -1330,27 +1339,28 @@ 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, - (char *) methodNameObj, &i); + 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, - (char *) methodNameObj, &i); + methodNameObj, &isNew); } } callPtr->refCount++; Tcl_SetHashValue(hPtr, callPtr); StashCallChain(cacheInThisObj, callPtr); @@ -1406,11 +1416,11 @@ * PRIVATE_METHOD, DESTRUCTOR and * FILTER_HANDLING are useful. */ { CallChain *callPtr; struct ChainBuilder cb; - int i, count; + Tcl_Size count; Foundation *fPtr = clsPtr->thisPtr->fPtr; Tcl_HashEntry *hPtr; Tcl_HashTable doneFilters; Object obj; @@ -1432,11 +1442,11 @@ * in the class). */ if (clsPtr->classChainCache != NULL) { hPtr = Tcl_FindHashEntry(clsPtr->classChainCache, - (char *) methodNameObj); + methodNameObj); if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) { const int reuseMask = (WANT_PUBLIC(flags) ? ~0 : ~PUBLIC_METHOD); callPtr = (CallChain *)Tcl_GetHashValue(hPtr); if (IsStillValid(callPtr, &obj, flags, reuseMask)) { @@ -1486,11 +1496,11 @@ NULL); /* * Check to see if the method has no implementation. If so, we probably * need to add in a call to the unknown method. Otherwise, set up the - * cacheing of the method implementation (if relevant). + * caching of the method implementation (if relevant). */ if (count == callPtr->numChain) { AddSimpleChainToCallContext(&obj, NULL, fPtr->unknownMethodNameObj, &cb, NULL, BUILDING_MIXINS, NULL); @@ -1502,16 +1512,17 @@ 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, - (char *) methodNameObj, &i); + methodNameObj, &isNew); } callPtr->refCount++; Tcl_SetHashValue(hPtr, callPtr); StashCallChain(methodNameObj, callPtr); } @@ -1540,11 +1551,12 @@ * processed. Keys are objects, values are * ignored. */ int flags) /* Whether we've gone along a mixin link * yet. */ { - int i, clearedFlags = + Tcl_Size i; + int clearedFlags = flags & ~(TRAVERSED_MIXIN|OBJECT_MIXIN|BUILDING_MIXINS); Class *superPtr, *mixinPtr; Tcl_Obj *filterObj; tailRecurse: @@ -1570,12 +1582,11 @@ if (MIXIN_CONSISTENT(flags)) { FOREACH(filterObj, clsPtr->filters) { int isNew; - (void) Tcl_CreateHashEntry(doneFilters, (char *) filterObj, - &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); @@ -1629,11 +1640,11 @@ int flags, /* What sort of call chain are we building. */ Class *const filterDecl) /* The class that declared the filter. If * NULL, either the filter was declared by the * object or this isn't a filter. */ { - int i; + Tcl_Size i; Class *superPtr; /* * We hard-code the tail-recursive form. It's by far the most common case * *and* it is much more gentle on the stack. @@ -1707,11 +1718,12 @@ 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; + 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. @@ -1733,11 +1745,11 @@ } else if (flags & DESTRUCTOR) { AddMethodToCallChain(classPtr->destructorPtr, cbPtr, doneFilters, filterDecl, flags); } else { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&classPtr->classMethods, - (char *) methodNameObj); + methodNameObj); if (classPtr->flags & HAS_PRIVATE_METHODS) { privateDanger |= 1; } if (hPtr != NULL) { @@ -1792,11 +1804,11 @@ CallChain *callPtr) { Tcl_Obj *filterLiteral, *methodLiteral, *objectLiteral, *privateLiteral; Tcl_Obj *resultObj, *descObjs[4], **objv; Foundation *fPtr = TclOOGetFoundation(interp); - int i; + Tcl_Size i; /* * Allocate the literals (potentially) used in our description. */ @@ -1895,11 +1907,11 @@ { DefineChain define; DefineEntry staticSpace[DEFINE_CHAIN_STATIC_SIZE]; DefineEntry *entryPtr; Tcl_Namespace *nsPtr = NULL; - int i; + int i, flags = (forClass ? DEFINE_FOR_CLASS : 0); define.list = staticSpace; define.num = 0; define.size = DEFINE_CHAIN_STATIC_SIZE; @@ -1906,12 +1918,12 @@ /* * Add the actual define locations. We have to do this twice to handle * class mixins right. */ - AddSimpleDefineNamespaces(oPtr, &define, forClass | BUILDING_MIXINS); - AddSimpleDefineNamespaces(oPtr, &define, forClass); + AddSimpleDefineNamespaces(oPtr, &define, flags | BUILDING_MIXINS); + AddSimpleDefineNamespaces(oPtr, &define, flags); /* * Go through the list until we find a namespace whose name we can * resolve. */ @@ -1948,11 +1960,11 @@ /* Where to add the define chain entries. */ int flags) /* What sort of define chain are we * building. */ { Class *mixinPtr; - int i; + Tcl_Size i; FOREACH(mixinPtr, oPtr->mixins) { AddSimpleClassDefineNamespaces(mixinPtr, definePtr, flags | TRAVERSED_MIXIN); } @@ -1977,11 +1989,11 @@ DefineChain *const definePtr, /* Where to add the define chain entries. */ int flags) /* What sort of define chain are we * building. */ { - int i; + Tcl_Size i; Class *superPtr; /* * We hard-code the tail-recursive form. It's by far the most common case * *and* it is much more gentle on the stack. @@ -1991,11 +2003,11 @@ FOREACH(superPtr, classPtr->mixins) { AddSimpleClassDefineNamespaces(superPtr, definePtr, flags | TRAVERSED_MIXIN); } - if (flags & ~(TRAVERSED_MIXIN | BUILDING_MIXINS)) { + if (flags & DEFINE_FOR_CLASS) { AddDefinitionNamespaceToChain(classPtr, classPtr->clsDefinitionNs, definePtr, flags); } else { AddDefinitionNamespaceToChain(classPtr, classPtr->objDefinitionNs, definePtr, flags); @@ -2099,13 +2111,266 @@ } 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: */ Index: generic/tclOODecls.h ================================================================== --- generic/tclOODecls.h +++ generic/tclOODecls.h @@ -67,12 +67,12 @@ const Tcl_MethodType *typePtr, void *clientData); /* 13 */ TCLAPI Tcl_Object Tcl_NewObjectInstance(Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, - const char *nsNameStr, int objc, - Tcl_Obj *const *objv, int skip); + const char *nsNameStr, Tcl_Size objc, + Tcl_Obj *const *objv, Tcl_Size skip); /* 14 */ TCLAPI int Tcl_ObjectDeleted(Tcl_Object object); /* 15 */ TCLAPI int Tcl_ObjectContextIsFiltering( Tcl_ObjectContext context); @@ -79,11 +79,11 @@ /* 16 */ TCLAPI Tcl_Method Tcl_ObjectContextMethod(Tcl_ObjectContext context); /* 17 */ TCLAPI Tcl_Object Tcl_ObjectContextObject(Tcl_ObjectContext context); /* 18 */ -TCLAPI int Tcl_ObjectContextSkippedArgs( +TCLAPI Tcl_Size Tcl_ObjectContextSkippedArgs( Tcl_ObjectContext context); /* 19 */ TCLAPI void * Tcl_ClassGetMetadata(Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr); /* 20 */ @@ -97,12 +97,12 @@ TCLAPI void Tcl_ObjectSetMetadata(Tcl_Object object, const Tcl_ObjectMetadataType *typePtr, void *metadata); /* 23 */ TCLAPI int Tcl_ObjectContextInvokeNext(Tcl_Interp *interp, - Tcl_ObjectContext context, int objc, - Tcl_Obj *const *objv, int skip); + Tcl_ObjectContext context, Tcl_Size objc, + Tcl_Obj *const *objv, Tcl_Size skip); /* 24 */ TCLAPI Tcl_ObjectMapMethodNameProc * Tcl_ObjectGetMethodNameMapper( Tcl_Object object); /* 25 */ TCLAPI void Tcl_ObjectSetMethodNameMapper(Tcl_Object object, @@ -116,10 +116,29 @@ /* 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; @@ -138,27 +157,32 @@ int (*tcl_MethodIsPublic) (Tcl_Method method); /* 8 */ int (*tcl_MethodIsType) (Tcl_Method method, const Tcl_MethodType *typePtr, void **clientDataPtr); /* 9 */ Tcl_Obj * (*tcl_MethodName) (Tcl_Method method); /* 10 */ Tcl_Method (*tcl_NewInstanceMethod) (Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr, void *clientData); /* 11 */ Tcl_Method (*tcl_NewMethod) (Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr, void *clientData); /* 12 */ - Tcl_Object (*tcl_NewObjectInstance) (Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, int objc, Tcl_Obj *const *objv, int skip); /* 13 */ + Tcl_Object (*tcl_NewObjectInstance) (Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, Tcl_Size objc, Tcl_Obj *const *objv, Tcl_Size skip); /* 13 */ int (*tcl_ObjectDeleted) (Tcl_Object object); /* 14 */ int (*tcl_ObjectContextIsFiltering) (Tcl_ObjectContext context); /* 15 */ Tcl_Method (*tcl_ObjectContextMethod) (Tcl_ObjectContext context); /* 16 */ Tcl_Object (*tcl_ObjectContextObject) (Tcl_ObjectContext context); /* 17 */ - int (*tcl_ObjectContextSkippedArgs) (Tcl_ObjectContext context); /* 18 */ + Tcl_Size (*tcl_ObjectContextSkippedArgs) (Tcl_ObjectContext context); /* 18 */ void * (*tcl_ClassGetMetadata) (Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr); /* 19 */ void (*tcl_ClassSetMetadata) (Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr, void *metadata); /* 20 */ void * (*tcl_ObjectGetMetadata) (Tcl_Object object, const Tcl_ObjectMetadataType *typePtr); /* 21 */ void (*tcl_ObjectSetMetadata) (Tcl_Object object, const Tcl_ObjectMetadataType *typePtr, void *metadata); /* 22 */ - int (*tcl_ObjectContextInvokeNext) (Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv, int skip); /* 23 */ + int (*tcl_ObjectContextInvokeNext) (Tcl_Interp *interp, Tcl_ObjectContext context, Tcl_Size objc, Tcl_Obj *const *objv, Tcl_Size skip); /* 23 */ Tcl_ObjectMapMethodNameProc * (*tcl_ObjectGetMethodNameMapper) (Tcl_Object object); /* 24 */ void (*tcl_ObjectSetMethodNameMapper) (Tcl_Object object, Tcl_ObjectMapMethodNameProc *mapMethodNameProc); /* 25 */ void (*tcl_ClassSetConstructor) (Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 26 */ void (*tcl_ClassSetDestructor) (Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 27 */ Tcl_Obj * (*tcl_GetObjectName) (Tcl_Interp *interp, Tcl_Object object); /* 28 */ int (*tcl_MethodIsPrivate) (Tcl_Method method); /* 29 */ + Tcl_Class (*tcl_GetClassOfObject) (Tcl_Object object); /* 30 */ + Tcl_Obj * (*tcl_GetObjectClassName) (Tcl_Interp *interp, Tcl_Object object); /* 31 */ + int (*tcl_MethodIsType2) (Tcl_Method method, const Tcl_MethodType2 *typePtr, void **clientDataPtr); /* 32 */ + Tcl_Method (*tcl_NewInstanceMethod2) (Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int flags, const Tcl_MethodType2 *typePtr, void *clientData); /* 33 */ + Tcl_Method (*tcl_NewMethod2) (Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int flags, const Tcl_MethodType2 *typePtr, void *clientData); /* 34 */ } TclOOStubs; extern const TclOOStubs *tclOOStubsPtr; #ifdef __cplusplus @@ -229,11 +253,31 @@ (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 */ Index: generic/tclOODefineCmds.c ================================================================== --- generic/tclOODefineCmds.c +++ generic/tclOODefineCmds.c @@ -2,11 +2,11 @@ * tclOODefineCmds.c -- * * This file contains the implementation of the ::oo::define command, * part of the object-system core (NB: not Tcl_Obj, but ::oo). * - * Copyright (c) 2006-2013 by Donal K. Fellows + * Copyright © 2006-2019 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -58,10 +58,11 @@ /* * 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, @@ -76,53 +77,57 @@ 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, +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. @@ -134,10 +139,18 @@ 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 @@ -199,21 +212,61 @@ * representative object is special. But it won't hurt. */ if (classPtr->thisPtr->mixins.num > 0) { classPtr->thisPtr->epoch++; + + /* + * Invalidate the property caches directly. + */ + + if (classPtr->properties.allReadableCache) { + Tcl_DecrRefCount(classPtr->properties.allReadableCache); + classPtr->properties.allReadableCache = NULL; + } + if (classPtr->properties.allWritableCache) { + Tcl_DecrRefCount(classPtr->properties.allWritableCache); + classPtr->properties.allWritableCache = NULL; + } } return; } /* * Either there's no class (?!) or we're reconfiguring something that is - * in use. Force regeneration of call chains. + * in use. Force regeneration of call chains and properties. */ TclOOGetFoundation(interp)->epoch++; } + +/* + * ---------------------------------------------------------------------- + * + * BumpInstanceEpoch -- + * + * Advances the epoch and clears the property cache of an object. The + * equivalent for classes is BumpGlobalEpoch(), as classes have a more + * complex set of relationships to other entities. + * + * ---------------------------------------------------------------------- + */ + +static inline void +BumpInstanceEpoch( + Object *oPtr) +{ + oPtr->epoch++; + if (oPtr->properties.allReadableCache) { + Tcl_DecrRefCount(oPtr->properties.allReadableCache); + oPtr->properties.allReadableCache = NULL; + } + if (oPtr->properties.allWritableCache) { + Tcl_DecrRefCount(oPtr->properties.allWritableCache); + oPtr->properties.allWritableCache = NULL; + } +} /* * ---------------------------------------------------------------------- * * RecomputeClassCacheFlag -- @@ -247,14 +300,14 @@ */ void TclOOObjectSetFilters( Object *oPtr, - int numFilters, + Tcl_Size numFilters, Tcl_Obj *const *filters) { - int i; + Tcl_Size i; if (oPtr->filters.num) { Tcl_Obj *filterObj; FOREACH(filterObj, oPtr->filters) { @@ -290,11 +343,11 @@ } oPtr->filters.list = filtersList; oPtr->filters.num = numFilters; oPtr->flags &= ~USE_CLASS_CACHE; } - oPtr->epoch++; /* Only this object can be affected. */ + BumpInstanceEpoch(oPtr); /* Only this object can be affected. */ } /* * ---------------------------------------------------------------------- * @@ -307,14 +360,14 @@ void TclOOClassSetFilters( Tcl_Interp *interp, Class *classPtr, - int numFilters, + Tcl_Size numFilters, Tcl_Obj *const *filters) { - int i; + Tcl_Size i; if (classPtr->filters.num) { Tcl_Obj *filterObj; FOREACH(filterObj, classPtr->filters) { @@ -369,15 +422,15 @@ */ void TclOOObjectSetMixins( Object *oPtr, - int numMixins, + Tcl_Size numMixins, Class *const *mixins) { Class *mixinPtr; - int i; + Tcl_Size i; if (numMixins == 0) { if (oPtr->mixins.num != 0) { FOREACH(mixinPtr, oPtr->mixins) { TclOORemoveFromInstances(oPtr, mixinPtr); @@ -413,11 +466,11 @@ AddRef(mixinPtr->thisPtr); } } } - oPtr->epoch++; + BumpInstanceEpoch(oPtr); } /* * ---------------------------------------------------------------------- * @@ -430,15 +483,15 @@ void TclOOClassSetMixins( Tcl_Interp *interp, Class *classPtr, - int numMixins, + Tcl_Size numMixins, Class *const *mixins) { Class *mixinPtr; - int i; + Tcl_Size i; if (numMixins == 0) { if (classPtr->mixins.num != 0) { FOREACH(mixinPtr, classPtr->mixins) { TclOORemoveFromMixinSubs(classPtr, mixinPtr); @@ -480,18 +533,20 @@ * * Helpers for installing standard and private variable maps. * * ---------------------------------------------------------------------- */ + static inline void InstallStandardVariableMapping( VariableNameList *vnlPtr, - int varc, + Tcl_Size varc, Tcl_Obj *const *varv) { Tcl_Obj *variableObj; - int i, n, created; + Tcl_Size i, n; + int created; Tcl_HashTable uniqueTable; for (i=0 ; imethodsPtr) { noSuchMethod: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "method %s does not exist", TclGetString(fromPtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", - TclGetString(fromPtr), NULL); + TclGetString(fromPtr), (void *)NULL); return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) fromPtr); + hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, fromPtr); if (hPtr == NULL) { goto noSuchMethod; } if (toPtr) { - newHPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) toPtr, + newHPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, toPtr, &isNew); if (hPtr == newHPtr) { renameToSelf: Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot rename method to itself", -1)); - Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_TO_SELF", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_TO_SELF", (void *)NULL); return TCL_ERROR; } else if (!isNew) { renameToExisting: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "method called %s already exists", TclGetString(toPtr))); - Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_OVER", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_OVER", (void *)NULL); return TCL_ERROR; } } } else { - hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods, - (char *) fromPtr); + hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods, fromPtr); if (hPtr == NULL) { goto noSuchMethod; } if (toPtr) { newHPtr = Tcl_CreateHashEntry(&oPtr->classPtr->classMethods, @@ -693,32 +748,32 @@ * ---------------------------------------------------------------------- */ int TclOOUnknownDefinition( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Namespace *nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); Tcl_HashSearch search; Tcl_HashEntry *hPtr; - size_t soughtLen; + 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", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_UNKNOWN", (void *)NULL); return TCL_ERROR; } if (TclOOGetDefineCmdContext(interp) == NULL) { return TCL_ERROR; } - soughtStr = TclGetStringFromObj(objv[1], &soughtLen); + soughtStr = Tcl_GetStringFromObj(objv[1], &soughtLen); if (soughtLen == 0) { goto noMatch; } hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); while (hPtr != NULL) { @@ -754,11 +809,11 @@ } noMatch: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid command name \"%s\"", soughtStr)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", soughtStr, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", soughtStr, (void *)NULL); return TCL_ERROR; } /* * ---------------------------------------------------------------------- @@ -775,12 +830,12 @@ FindCommand( Tcl_Interp *interp, Tcl_Obj *stringObj, Tcl_Namespace *const namespacePtr) { - size_t length; - const char *nameStr, *string = TclGetStringFromObj(stringObj, &length); + Tcl_Size length; + const char *nameStr, *string = Tcl_GetStringFromObj(stringObj, &length); Namespace *const nsPtr = (Namespace *) namespacePtr; FOREACH_HASH_DECLS; Tcl_Command cmd, cmd2; /* @@ -844,11 +899,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } /* * framePtrPtr is needed to satisfy GCC 3.3's strict aliasing rules. @@ -885,19 +940,19 @@ || (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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return NULL; } return object; } @@ -937,11 +992,11 @@ return NULL; } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", - TclGetString(className), NULL); + TclGetString(className), (void *)NULL); return NULL; } return oPtr->classPtr; } @@ -994,20 +1049,20 @@ * could have been renamed... */ const char *typeOfSubject) /* Part of the message, saying whether it was * an object, class or class-as-object that * was being configured. */ { - size_t length; + Tcl_Size length; Tcl_Obj *realNameObj = Tcl_ObjectDeleted((Tcl_Object) oPtr) ? savedNameObj : TclOOObjectName(interp, oPtr); - const char *objName = TclGetStringFromObj(realNameObj, &length); - unsigned limit = OBJNAME_LENGTH_IN_ERRORINFO_LIMIT; + const char *objName = Tcl_GetStringFromObj(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 : (unsigned)length), objName, + typeOfSubject, (overflow ? limit : (int)length), objName, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } /* * ---------------------------------------------------------------------- @@ -1030,11 +1085,12 @@ int objc, Tcl_Obj *const *objv) { Tcl_Obj *objPtr, *obj2Ptr, **objs; Tcl_Command cmd; - int isRoot, dummy, result, offset = cmdIndex + 1; + int isRoot, result, offset = cmdIndex + 1; + Tcl_Size dummy; /* * More than one argument: fire them through the ensemble processing * engine so that everything appears to be good and proper in error * messages. Note that we cannot just concatenate and send through @@ -1063,11 +1119,11 @@ 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); + TclListObjGetElementsM(NULL, objPtr, &dummy, &objs); result = Tcl_EvalObjv(interp, objc - cmdIndex, objs, TCL_EVAL_INVOKE); if (isRoot) { TclResetRewriteEnsemble(interp, 1); } @@ -1090,11 +1146,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Namespace *nsPtr; @@ -1112,11 +1168,11 @@ } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s does not refer to a class", TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", - TclGetString(objv[1]), NULL); + TclGetString(objv[1]), (void *)NULL); return TCL_ERROR; } /* * Make the oo::define namespace the current namespace and evaluate the @@ -1166,11 +1222,11 @@ * ---------------------------------------------------------------------- */ int TclOOObjDefObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Namespace *nsPtr; @@ -1235,11 +1291,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineSelfObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Namespace *nsPtr; @@ -1306,11 +1362,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineObjSelfObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Object *oPtr; @@ -1340,11 +1396,11 @@ * ---------------------------------------------------------------------- */ int TclOODefinePrivateObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstancePrivate = (clientData != NULL); @@ -1413,11 +1469,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineClassObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Object *oPtr; @@ -1434,17 +1490,17 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } /* * Parse the argument to get the class to set the object's class to. @@ -1460,11 +1516,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } /* * Set the object's class. @@ -1503,11 +1559,11 @@ } if (oPtr->classPtr != NULL) { BumpGlobalEpoch(interp, oPtr->classPtr); } else { - oPtr->epoch++; + BumpInstanceEpoch(oPtr); } } return TCL_OK; } @@ -1522,19 +1578,19 @@ * ---------------------------------------------------------------------- */ int TclOODefineConstructorObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Object *oPtr; Class *clsPtr; Tcl_Method method; - size_t bodyLength; + Tcl_Size bodyLength; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arguments body"); return TCL_ERROR; } @@ -1548,11 +1604,11 @@ if (oPtr == NULL) { return TCL_ERROR; } clsPtr = oPtr->classPtr; - (void)TclGetStringFromObj(objv[2], &bodyLength); + (void)Tcl_GetStringFromObj(objv[2], &bodyLength); if (bodyLength > 0) { /* * Create the method structure. */ @@ -1591,11 +1647,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineDefnNsObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { static const char *kindList[] = { @@ -1613,18 +1669,18 @@ return TCL_ERROR; } if (!oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); - Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } /* * Parse the arguments and work out what the user wants to do. @@ -1676,11 +1732,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineDeleteMethodObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceDeleteMethod = (clientData != NULL); @@ -1697,11 +1753,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } for (i = 1; i < objc; i++) { /* @@ -1713,11 +1769,11 @@ return TCL_ERROR; } } if (isInstanceDeleteMethod) { - oPtr->epoch++; + BumpInstanceEpoch(oPtr); } else { BumpGlobalEpoch(interp, oPtr->classPtr); } return TCL_OK; } @@ -1733,19 +1789,19 @@ * ---------------------------------------------------------------------- */ int TclOODefineDestructorObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Object *oPtr; Class *clsPtr; Tcl_Method method; - size_t bodyLength; + Tcl_Size bodyLength; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "body"); return TCL_ERROR; } @@ -1754,11 +1810,11 @@ if (oPtr == NULL) { return TCL_ERROR; } clsPtr = oPtr->classPtr; - (void)TclGetStringFromObj(objv[1], &bodyLength); + (void)Tcl_GetStringFromObj(objv[1], &bodyLength); if (bodyLength > 0) { /* * Create the method structure. */ @@ -1798,11 +1854,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineExportObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceExport = (clientData != NULL); @@ -1823,11 +1879,11 @@ } clsPtr = oPtr->classPtr; if (!isInstanceExport && !clsPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); - Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } for (i = 1; i < objc; i++) { /* @@ -1843,14 +1899,14 @@ 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], + hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, objv[i], &isNew); } else { - hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)objv[i], + hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, objv[i], &isNew); } if (isNew) { mPtr = (Method *)Tcl_Alloc(sizeof(Method)); @@ -1873,11 +1929,11 @@ * Bump the right epoch if we actually changed anything. */ if (changed) { if (isInstanceExport) { - oPtr->epoch++; + BumpInstanceEpoch(oPtr); } else { BumpGlobalEpoch(interp, clsPtr); } } return TCL_OK; @@ -1894,11 +1950,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineForwardObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceForward = (clientData != NULL); @@ -1917,11 +1973,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } isPublic = Tcl_StringMatch(TclGetString(objv[1]), PUBLIC_PATTERN) ? PUBLIC_METHOD : 0; if (IsPrivateDefine(interp)) { @@ -1958,11 +2014,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineMethodObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { /* @@ -1995,16 +2051,16 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } if (objc == 5) { if (Tcl_GetIndexFromObj(interp, objv[2], exportModes, "export flag", - 0, (int *) &exportMode) != TCL_OK) { + 0, &exportMode) != TCL_OK) { return TCL_ERROR; } switch (exportMode) { case MODE_EXPORT: isPublic = PUBLIC_METHOD; @@ -2054,11 +2110,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineRenameMethodObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceRenameMethod = (clientData != NULL); @@ -2074,11 +2130,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } /* * Delete the method entry from the appropriate hash table, and transfer @@ -2091,11 +2147,11 @@ objv[1], objv[2]) != TCL_OK) { return TCL_ERROR; } if (isInstanceRenameMethod) { - oPtr->epoch++; + BumpInstanceEpoch(oPtr); } else { BumpGlobalEpoch(interp, oPtr->classPtr); } return TCL_OK; } @@ -2111,11 +2167,11 @@ * ---------------------------------------------------------------------- */ int TclOODefineUnexportObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceUnexport = (clientData != NULL); @@ -2136,11 +2192,11 @@ } clsPtr = oPtr->classPtr; if (!isInstanceUnexport && !clsPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); - Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } for (i = 1; i < objc; i++) { /* @@ -2156,14 +2212,14 @@ 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], + hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, objv[i], &isNew); } else { - hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)objv[i], + hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, objv[i], &isNew); } if (isNew) { mPtr = (Method *)Tcl_Alloc(sizeof(Method)); @@ -2185,11 +2241,11 @@ * Bump the right epoch if we actually changed anything. */ if (changed) { if (isInstanceUnexport) { - oPtr->epoch++; + BumpInstanceEpoch(oPtr); } else { BumpGlobalEpoch(interp, clsPtr); } } return TCL_OK; @@ -2270,30 +2326,30 @@ 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; + 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, -1, NULL, 0); + (Tcl_Class) slotCls, slotInfoPtr->name, NULL, TCL_INDEX_NONE, NULL, 0); if (slotObject == NULL) { continue; } - Tcl_NewInstanceMethod(fPtr->interp, slotObject, getName, 0, + TclNewInstanceMethod(fPtr->interp, slotObject, getName, 0, &slotInfoPtr->getterType, NULL); - Tcl_NewInstanceMethod(fPtr->interp, slotObject, setName, 0, + TclNewInstanceMethod(fPtr->interp, slotObject, setName, 0, &slotInfoPtr->setterType, NULL); if (slotInfoPtr->resolverType.callProc) { - Tcl_NewInstanceMethod(fPtr->interp, slotObject, resolveName, 0, + TclNewInstanceMethod(fPtr->interp, slotObject, resolveName, 0, &slotInfoPtr->resolverType, NULL); } } Tcl_DecrRefCount(getName); Tcl_DecrRefCount(setName); @@ -2312,19 +2368,19 @@ * ---------------------------------------------------------------------- */ static int ClassFilterGet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj, *filterObj; - int i; + Tcl_Size i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; @@ -2332,11 +2388,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } TclNewObj(resultObj); FOREACH(filterObj, oPtr->classPtr->filters) { @@ -2346,18 +2402,18 @@ return TCL_OK; } static int ClassFilterSet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); - int filterc; + Tcl_Size filterc; Tcl_Obj **filterv; if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "filterList"); @@ -2368,13 +2424,13 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; - } else if (Tcl_ListObjGetElements(interp, objv[0], &filterc, + } else if (TclListObjGetElementsM(interp, objv[0], &filterc, &filterv) != TCL_OK) { return TCL_ERROR; } TclOOClassSetFilters(interp, oPtr->classPtr, filterc, filterv); @@ -2392,20 +2448,20 @@ * ---------------------------------------------------------------------- */ static int ClassMixinGet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj; Class *mixinPtr; - int i; + Tcl_Size i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; @@ -2413,11 +2469,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } TclNewObj(resultObj); FOREACH(mixinPtr, oPtr->classPtr->mixins) { @@ -2429,18 +2485,18 @@ } static int ClassMixinSet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); - int mixinc, i; + Tcl_Size mixinc, i; Tcl_Obj **mixinv; Class **mixins; if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, @@ -2452,13 +2508,13 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; - } else if (Tcl_ListObjGetElements(interp, objv[0], &mixinc, + } else if (TclListObjGetElementsM(interp, objv[0], &mixinc, &mixinv) != TCL_OK) { return TCL_ERROR; } mixins = (Class **)TclStackAlloc(interp, sizeof(Class *) * mixinc); @@ -2471,11 +2527,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", (void *)NULL); goto freeAndError; } } TclOOClassSetMixins(interp, oPtr->classPtr, mixinc, mixins); @@ -2498,20 +2554,20 @@ * ---------------------------------------------------------------------- */ static int ClassSuperGet( - TCL_UNUSED(ClientData), + 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; - int i; + Tcl_Size i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; @@ -2519,11 +2575,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } TclNewObj(resultObj); FOREACH(superPtr, oPtr->classPtr->superclasses) { @@ -2534,18 +2590,19 @@ return TCL_OK; } static int ClassSuperSet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); - int superc, i, j; + 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, @@ -2557,18 +2614,18 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; - } else if (Tcl_ListObjGetElements(interp, objv[0], &superc, + } else if (TclListObjGetElementsM(interp, objv[0], &superc, &superv) != TCL_OK) { return TCL_ERROR; } /* @@ -2603,18 +2660,18 @@ for (j = 0; j < i; j++) { if (superclasses[j] == superclasses[i]) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "class should only be a direct superclass once", -1)); - Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS",NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS",(void *)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); + Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", (void *)NULL); failedAfterAlloc: for (; i-- > 0 ;) { TclOODecrRefCount(superclasses[i]->thisPtr); } Tcl_Free(superclasses); @@ -2665,19 +2722,19 @@ * ---------------------------------------------------------------------- */ static int ClassVarsGet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj; - int i; + Tcl_Size i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; @@ -2685,11 +2742,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; } TclNewObj(resultObj); if (IsPrivateDefine(interp)) { @@ -2709,20 +2766,20 @@ return TCL_OK; } static int ClassVarsSet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); - int varc; + Tcl_Size i; + Tcl_Size varc; Tcl_Obj **varv; - int i; if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "filterList"); return TCL_ERROR; @@ -2732,13 +2789,13 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (void *)NULL); return TCL_ERROR; - } else if (Tcl_ListObjGetElements(interp, objv[0], &varc, + } else if (TclListObjGetElementsM(interp, objv[0], &varc, &varv) != TCL_OK) { return TCL_ERROR; } for (i = 0; i < varc; i++) { @@ -2746,18 +2803,18 @@ if (strstr(varName, "::") != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid declared variable name \"%s\": must not %s", varName, "contain namespace separators")); - Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", (void *)NULL); return TCL_ERROR; } if (Tcl_StringMatch(varName, "*(*)")) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid declared variable name \"%s\": must not %s", varName, "refer to an array element")); - Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", (void *)NULL); return TCL_ERROR; } } if (IsPrivateDefine(interp)) { @@ -2780,19 +2837,19 @@ * ---------------------------------------------------------------------- */ static int ObjFilterGet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj, *filterObj; - int i; + Tcl_Size i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; @@ -2808,18 +2865,18 @@ return TCL_OK; } static int ObjFilterSet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); - int filterc; + Tcl_Size filterc; Tcl_Obj **filterv; if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "filterList"); @@ -2826,11 +2883,11 @@ return TCL_ERROR; } else if (oPtr == NULL) { return TCL_ERROR; } objv += Tcl_ObjectContextSkippedArgs(context); - if (Tcl_ListObjGetElements(interp, objv[0], &filterc, + if (TclListObjGetElementsM(interp, objv[0], &filterc, &filterv) != TCL_OK) { return TCL_ERROR; } TclOOObjectSetFilters(oPtr, filterc, filterv); @@ -2848,20 +2905,20 @@ * ---------------------------------------------------------------------- */ static int ObjMixinGet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj; Class *mixinPtr; - int i; + Tcl_Size i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; @@ -2880,31 +2937,31 @@ return TCL_OK; } static int ObjMixinSet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); - int mixinc; + Tcl_Size i; + Tcl_Size 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, + if (TclListObjGetElementsM(interp, objv[0], &mixinc, &mixinv) != TCL_OK) { return TCL_ERROR; } mixins = (Class **)TclStackAlloc(interp, sizeof(Class *) * mixinc); @@ -2934,19 +2991,19 @@ * ---------------------------------------------------------------------- */ static int ObjVarsGet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj; - int i; + Tcl_Size i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; @@ -2972,18 +3029,18 @@ return TCL_OK; } static int ObjVarsSet( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); - int varc, i; + Tcl_Size varc, i; Tcl_Obj **varv; if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "variableList"); @@ -2990,11 +3047,11 @@ return TCL_ERROR; } else if (oPtr == NULL) { return TCL_ERROR; } objv += Tcl_ObjectContextSkippedArgs(context); - if (Tcl_ListObjGetElements(interp, objv[0], &varc, + if (TclListObjGetElementsM(interp, objv[0], &varc, &varv) != TCL_OK) { return TCL_ERROR; } for (i = 0; i < varc; i++) { @@ -3002,18 +3059,18 @@ if (strstr(varName, "::") != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid declared variable name \"%s\": must not %s", varName, "contain namespace separators")); - Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", (void *)NULL); return TCL_ERROR; } if (Tcl_StringMatch(varName, "*(*)")) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid declared variable name \"%s\": must not %s", varName, "refer to an array element")); - Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL); + Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", (void *)NULL); return TCL_ERROR; } } if (IsPrivateDefine(interp)) { @@ -3037,11 +3094,11 @@ * ---------------------------------------------------------------------- */ static int ResolveClass( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { @@ -3075,13 +3132,407 @@ 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 ; ireadable) { + 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 ; ireadable.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", (void *)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", (void *)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 ; iwritable) { + 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 ; iwritable.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", (void *)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", (void *)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: */ Index: generic/tclOOInfo.c ================================================================== --- generic/tclOOInfo.c +++ generic/tclOOInfo.c @@ -2,11 +2,11 @@ * tclOODefineCmds.c -- * * This file contains the implementation of the ::oo-related [info] * subcommands. * - * Copyright (c) 2006-2011 by Donal K. Fellows + * Copyright © 2006-2019 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -15,10 +15,11 @@ #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; @@ -26,10 +27,11 @@ 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; @@ -39,10 +41,11 @@ 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; /* @@ -59,10 +62,11 @@ {"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} }; @@ -80,10 +84,11 @@ {"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} }; @@ -151,11 +156,11 @@ } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(objPtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", - TclGetString(objPtr), NULL); + TclGetString(objPtr), (void *)NULL); return NULL; } return oPtr->classPtr; } @@ -192,11 +197,11 @@ Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr->selfCls->thisPtr)); return TCL_OK; } else { Class *mixinPtr, *o2clsPtr; - int i; + Tcl_Size i; o2clsPtr = GetClassFromObj(interp, objv[2]); if (o2clsPtr == NULL) { return TCL_ERROR; } @@ -250,25 +255,25 @@ } if (!oPtr->methodsPtr) { goto unknownMethod; } - hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]); + 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]), NULL); + TclGetString(objv[2]), (void *)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); + TclGetString(objv[2]), (void *)NULL); return TCL_ERROR; } TclNewObj(resultObjs[0]); for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL; @@ -305,11 +310,11 @@ TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - int i; + Tcl_Size i; Tcl_Obj *filterObj, *resultObj; Object *oPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "objName"); @@ -361,26 +366,26 @@ } if (!oPtr->methodsPtr) { goto unknownMethod; } - hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]); + 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]), NULL); + TclGetString(objv[2]), (void *)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); + TclGetString(objv[2]), (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, prefixObj); return TCL_OK; @@ -406,13 +411,14 @@ static const char *const categories[] = { "class", "metaclass", "mixin", "object", "typeof", NULL }; enum IsACats { IsClass, IsMetaclass, IsMixin, IsObject, IsType - }; + } idx; Object *oPtr, *o2Ptr; - int idx, i, result = 0; + int result = 0; + Tcl_Size i; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "category objName ?arg ...?"); return TCL_ERROR; } @@ -424,11 +430,11 @@ /* * Now we know what test we are doing, we can check we've got the right * number of arguments. */ - switch ((enum IsACats) idx) { + switch (idx) { case IsObject: case IsClass: case IsMetaclass: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "objName"); @@ -452,11 +458,11 @@ oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]); if (oPtr == NULL) { goto failPrecondition; } - switch ((enum IsACats) idx) { + switch (idx) { case IsObject: result = 1; break; case IsClass: result = (oPtr->classPtr != NULL); @@ -530,11 +536,11 @@ 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, @@ -548,18 +554,18 @@ oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } if (objc != 2) { - int i, idx; + int i; for (i=2 ; i= objc) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "missing option for -scope")); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", - NULL); + (void *)NULL); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0, &scope) != TCL_OK) { return TCL_ERROR; @@ -657,17 +663,17 @@ } if (!oPtr->methodsPtr) { goto unknownMethod; } - hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]); + 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]), NULL); + TclGetString(objv[2]), (void *)NULL); return TCL_ERROR; } mPtr = (Method *)Tcl_GetHashValue(hPtr); if (mPtr->typePtr == NULL) { /* @@ -700,11 +706,11 @@ Tcl_Obj *const objv[]) { Class *mixinPtr; Object *oPtr; Tcl_Obj *resultObj; - int i; + Tcl_Size i; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "objName"); return TCL_ERROR; } @@ -807,11 +813,12 @@ int objc, Tcl_Obj *const objv[]) { Object *oPtr; Tcl_Obj *resultObj; - int i, isPrivate = 0; + Tcl_Size i; + int isPrivate = 0; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "objName ?-private?"); return TCL_ERROR; } @@ -940,11 +947,11 @@ } 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "METHOD_TYPE", (void *)NULL); return TCL_ERROR; } TclNewObj(resultObjs[0]); for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL; @@ -995,24 +1002,24 @@ } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) objv[2]); + hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, objv[2]); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", - TclGetString(objv[2]), NULL); + TclGetString(objv[2]), (void *)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); + TclGetString(objv[2]), (void *)NULL); return TCL_ERROR; } TclNewObj(resultObjs[0]); for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL; @@ -1118,11 +1125,11 @@ } 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); + Tcl_SetErrorCode(interp, "TCL", "OO", "METHOD_TYPE", (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, TclOOGetMethodBody(clsPtr->destructorPtr)); return TCL_OK; @@ -1143,11 +1150,11 @@ TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - int i; + Tcl_Size i; Tcl_Obj *filterObj, *resultObj; Class *clsPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); @@ -1193,25 +1200,25 @@ } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) objv[2]); + hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, objv[2]); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", - TclGetString(objv[2]), NULL); + TclGetString(objv[2]), (void *)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); + TclGetString(objv[2]), (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, prefixObj); return TCL_OK; @@ -1234,11 +1241,11 @@ int objc, Tcl_Obj *const objv[]) { Object *oPtr; Class *clsPtr; - int i; + Tcl_Size i; const char *pattern = NULL; Tcl_Obj *resultObj; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className ?pattern?"); @@ -1289,11 +1296,11 @@ 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 @@ -1306,18 +1313,18 @@ clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } if (objc != 2) { - int i, idx; + int i; for (i=2 ; i= objc) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "missing option for -scope")); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", - NULL); + (void *)NULL); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0, &scope) != TCL_OK) { return TCL_ERROR; @@ -1357,11 +1364,11 @@ } TclNewObj(resultObj); if (recurse) { const char **names; - int i, numNames = TclOOGetSortedClassMethodList(clsPtr, flag, &names); + Tcl_Size i, numNames = TclOOGetSortedClassMethodList(clsPtr, flag, &names); for (i=0 ; iclassMethods, (char *) objv[2]); + 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]), NULL); + TclGetString(objv[2]), (void *)NULL); return TCL_ERROR; } mPtr = (Method *)Tcl_GetHashValue(hPtr); if (mPtr->typePtr == NULL) { /* @@ -1450,11 +1457,11 @@ int objc, Tcl_Obj *const objv[]) { Class *clsPtr, *mixinPtr; Tcl_Obj *resultObj; - int i; + Tcl_Size i; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); return TCL_ERROR; } @@ -1492,11 +1499,11 @@ int objc, Tcl_Obj *const objv[]) { Class *clsPtr, *subclassPtr; Tcl_Obj *resultObj; - int i; + Tcl_Size i; const char *pattern = NULL; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className ?pattern?"); return TCL_ERROR; @@ -1547,11 +1554,11 @@ int objc, Tcl_Obj *const objv[]) { Class *clsPtr, *superPtr; Tcl_Obj *resultObj; - int i; + Tcl_Size i; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); return TCL_ERROR; } @@ -1586,11 +1593,12 @@ int objc, Tcl_Obj *const objv[]) { Class *clsPtr; Tcl_Obj *resultObj; - int i, isPrivate = 0; + Tcl_Size i; + int isPrivate = 0; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className ?-private?"); return TCL_ERROR; } @@ -1710,13 +1718,191 @@ } 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: */ Index: generic/tclOOInt.h ================================================================== --- generic/tclOOInt.h +++ generic/tclOOInt.h @@ -44,11 +44,11 @@ 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; + 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. */ @@ -81,11 +81,11 @@ * 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; + Tcl_Size refCount; void *clientData; TclOO_PmCDDeleteProc *deleteClientdataProc; TclOO_PmCDCloneProc *cloneClientdataProc; ProcErrorProc *errProc; /* Replacement error handler. */ TclOO_PreCallProc *preCallProc; @@ -147,21 +147,41 @@ * "list" field. When a "size" field exists, it describes how many elements * are present in the list; when absent, exactly "num" elements are present. */ #define LIST_STATIC(listType_t) \ - struct { int num; listType_t *list; } + struct { Tcl_Size num; listType_t *list; } #define LIST_DYNAMIC(listType_t) \ - struct { int num, size; listType_t *list; } + struct { Tcl_Size num, size; listType_t *list; } /* * These types are needed in function arguments. */ typedef LIST_STATIC(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 { @@ -180,20 +200,20 @@ 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. + * for everything else. It points to the class + * structure. */ + Tcl_Size refCount; /* Number of strong references to this object. * Note that there may be many more weak * references; this mechanism exists to * avoid Tcl_Preserve. */ int flags; - size_t creationEpoch; /* Unique value to make comparisons of objects + Tcl_Size creationEpoch; /* Unique value to make comparisons of objects * easier. */ - size_t epoch; /* Per-object epoch, incremented when the way + Tcl_Size epoch; /* Per-object epoch, incremented when the way * an object should resolve call chains is * changed. */ Tcl_HashTable *metadataPtr; /* Mapping from pointers to metadata type to * the void *values that are the values * of each piece of attached metadata. This @@ -209,16 +229,19 @@ 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 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 @@ -233,18 +256,18 @@ * 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 +#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. */ -#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. */ @@ -317,10 +340,13 @@ * 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 @@ -327,11 +353,11 @@ * 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 + 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). */ @@ -351,11 +377,11 @@ * "oo::objdefine" command acts as a special * kind of ensemble for this namespace. */ Tcl_Namespace *helpersNs; /* Namespace containing the commands that are * only valid when executing inside a * procedural method. */ - size_t epoch; /* Used to invalidate method chains when the + Tcl_Size epoch; /* Used to invalidate method chains when the * class structure changes. */ ThreadLocalData *tsdPtr; /* Counter so we can allocate a unique * namespace to each object. */ Tcl_Obj *unknownMethodNameObj; /* Shared object containing the name of the @@ -385,31 +411,31 @@ 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 + Tcl_Size objectCreationEpoch;/* The object's creation epoch. Note that the * object reference is not stored in the call * chain; it is in the call context. */ - size_t objectEpoch; /* Local (object structure) epoch counter + Tcl_Size objectEpoch; /* Local (object structure) epoch counter * snapshot. */ - size_t epoch; /* Global (class structure) epoch counter + Tcl_Size epoch; /* Global (class structure) epoch counter * snapshot. */ int flags; /* Assorted flags, see below. */ - size_t refCount; /* Reference count. */ - int numChain; /* Size of the call chain. */ + 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. */ - int index; /* Index into the call chain of the currently + Tcl_Size index; /* Index into the call chain of the currently * executing method implementation. */ - int skip; /* Current number of arguments to skip; can + Tcl_Size skip; /* Current number of arguments to skip; can * vary depending on whether it is a direct * method call or a continuation via the * [next] command. */ CallChain *callPtr; /* The actual call chain. */ } CallContext; @@ -445,126 +471,44 @@ * 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); +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 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); +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. */ @@ -572,14 +516,25 @@ 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, int objc, - Tcl_Obj *const *objv, int skip, + const char *nsNameStr, Tcl_Size objc, + Tcl_Obj *const *objv, Tcl_Size skip, Tcl_Object *objectPtr); MODULE_SCOPE Object * TclNewObjectInstanceCommon(Tcl_Interp *interp, Class *classPtr, const char *nameStr, const char *nsNameStr); @@ -590,10 +545,14 @@ 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( @@ -602,11 +561,11 @@ Tcl_Obj *methodNameObj, int flags); MODULE_SCOPE Foundation *TclOOGetFoundation(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclOOGetFwdFromMethod(Method *mPtr); MODULE_SCOPE Proc * TclOOGetProcFromMethod(Method *mPtr); MODULE_SCOPE Tcl_Obj * TclOOGetMethodBody(Method *mPtr); -MODULE_SCOPE int TclOOGetSortedClassMethodList(Class *clsPtr, +MODULE_SCOPE size_t TclOOGetSortedClassMethodList(Class *clsPtr, int flags, const char ***stringsPtr); MODULE_SCOPE int TclOOGetSortedMethodList(Object *oPtr, Object *contextObj, Class *contextCls, int flags, const char ***stringsPtr); MODULE_SCOPE int TclOOInit(Tcl_Interp *interp); @@ -613,12 +572,12 @@ 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); + 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); @@ -647,27 +606,27 @@ #define AddRef(ptr) ((ptr)->refCount++) /* * A convenience macro for iterating through the lists used in the internal * memory management of objects. - * REQUIRES DECLARATION: int i; + * REQUIRES DECLARATION: Tcl_Size i; */ #define FOREACH(var,ary) \ for(i=0 ; i<(ary).num; i++) if ((ary).list[i] == NULL) { \ continue; \ - } else if (var = (ary).list[i], 1) + } else if ((var) = (ary).list[i], 1) /* * A variation where the array is an array of structs. There's no issue with * possible NULLs; every element of the array will be iterated over and the - * varable set to a pointer to each of those elements in turn. - * REQUIRES DECLARATION: int i; + * variable set to a pointer to each of those elements in turn. + * REQUIRES DECLARATION: Tcl_Size i; See [96551aca55] for more FOREACH_STRUCT details. */ #define FOREACH_STRUCT(var,ary) \ - for(i=0 ; var=&((ary).list[i]), i<(ary).num; i++) + if (i=0, (ary).num>0) for(; var=&((ary).list[i]), i<(ary).num; i++) /* * Convenience macros for iterating through hash tables. FOREACH_HASH_DECLS * sets up the declarations needed for the main macro, FOREACH_HASH, which * does the actual iteration. FOREACH_HASH_VALUE is a restricted version that Index: generic/tclOOIntDecls.h ================================================================== --- generic/tclOOIntDecls.h +++ generic/tclOOIntDecls.h @@ -40,11 +40,11 @@ int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr); /* 5 */ TCLAPI int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp, - int objc, Tcl_Obj *const *objv, + Tcl_Size objc, Tcl_Obj *const *objv, int publicOnly, Class *startCls); /* 6 */ TCLAPI int TclOOIsReachable(Class *targetPtr, Class *startPtr); /* 7 */ TCLAPI Method * TclOONewForwardMethod(Tcl_Interp *interp, @@ -73,25 +73,25 @@ Tcl_Obj *bodyObj, int flags, void **internalTokenPtr); /* 11 */ TCLAPI int TclOOInvokeObject(Tcl_Interp *interp, Tcl_Object object, Tcl_Class startCls, - int publicPrivate, int objc, + int publicPrivate, Tcl_Size objc, Tcl_Obj *const *objv); /* 12 */ -TCLAPI void TclOOObjectSetFilters(Object *oPtr, int numFilters, - Tcl_Obj *const *filters); +TCLAPI void TclOOObjectSetFilters(Object *oPtr, + Tcl_Size numFilters, Tcl_Obj *const *filters); /* 13 */ TCLAPI void TclOOClassSetFilters(Tcl_Interp *interp, - Class *classPtr, int numFilters, + Class *classPtr, Tcl_Size numFilters, Tcl_Obj *const *filters); /* 14 */ -TCLAPI void TclOOObjectSetMixins(Object *oPtr, int numMixins, - Class *const *mixins); +TCLAPI void TclOOObjectSetMixins(Object *oPtr, + Tcl_Size numMixins, Class *const *mixins); /* 15 */ TCLAPI void TclOOClassSetMixins(Tcl_Interp *interp, - Class *classPtr, int numMixins, + Class *classPtr, Tcl_Size numMixins, Class *const *mixins); typedef struct TclOOIntStubs { int magic; void *hooks; @@ -99,21 +99,21 @@ Tcl_Object (*tclOOGetDefineCmdContext) (Tcl_Interp *interp); /* 0 */ Tcl_Method (*tclOOMakeProcInstanceMethod) (Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, void *clientData, Proc **procPtrPtr); /* 1 */ Tcl_Method (*tclOOMakeProcMethod) (Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, const char *namePtr, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, void *clientData, Proc **procPtrPtr); /* 2 */ Method * (*tclOONewProcInstanceMethod) (Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr); /* 3 */ Method * (*tclOONewProcMethod) (Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr); /* 4 */ - int (*tclOOObjectCmdCore) (Object *oPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, int publicOnly, Class *startCls); /* 5 */ + int (*tclOOObjectCmdCore) (Object *oPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const *objv, int publicOnly, Class *startCls); /* 5 */ int (*tclOOIsReachable) (Class *targetPtr, Class *startPtr); /* 6 */ Method * (*tclOONewForwardMethod) (Tcl_Interp *interp, Class *clsPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj); /* 7 */ Method * (*tclOONewForwardInstanceMethod) (Tcl_Interp *interp, Object *oPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj); /* 8 */ Tcl_Method (*tclOONewProcInstanceMethodEx) (Tcl_Interp *interp, Tcl_Object oPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, void *clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr); /* 9 */ Tcl_Method (*tclOONewProcMethodEx) (Tcl_Interp *interp, Tcl_Class clsPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, void *clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr); /* 10 */ - int (*tclOOInvokeObject) (Tcl_Interp *interp, Tcl_Object object, Tcl_Class startCls, int publicPrivate, int objc, Tcl_Obj *const *objv); /* 11 */ - void (*tclOOObjectSetFilters) (Object *oPtr, int numFilters, Tcl_Obj *const *filters); /* 12 */ - void (*tclOOClassSetFilters) (Tcl_Interp *interp, Class *classPtr, int numFilters, Tcl_Obj *const *filters); /* 13 */ - void (*tclOOObjectSetMixins) (Object *oPtr, int numMixins, Class *const *mixins); /* 14 */ - void (*tclOOClassSetMixins) (Tcl_Interp *interp, Class *classPtr, int numMixins, Class *const *mixins); /* 15 */ + int (*tclOOInvokeObject) (Tcl_Interp *interp, Tcl_Object object, Tcl_Class startCls, int publicPrivate, Tcl_Size objc, Tcl_Obj *const *objv); /* 11 */ + void (*tclOOObjectSetFilters) (Object *oPtr, Tcl_Size numFilters, Tcl_Obj *const *filters); /* 12 */ + void (*tclOOClassSetFilters) (Tcl_Interp *interp, Class *classPtr, Tcl_Size numFilters, Tcl_Obj *const *filters); /* 13 */ + void (*tclOOObjectSetMixins) (Object *oPtr, Tcl_Size numMixins, Class *const *mixins); /* 14 */ + void (*tclOOClassSetMixins) (Tcl_Interp *interp, Class *classPtr, Tcl_Size numMixins, Class *const *mixins); /* 15 */ } TclOOIntStubs; extern const TclOOIntStubs *tclOOIntStubsPtr; #ifdef __cplusplus Index: generic/tclOOMethod.c ================================================================== --- generic/tclOOMethod.c +++ generic/tclOOMethod.c @@ -1,11 +1,11 @@ /* * tclOOMethod.c -- * * This file contains code to create and manage methods. * - * Copyright (c) 2005-2011 by Donal K. Fellows + * Copyright © 2005-2011 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -16,11 +16,11 @@ #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. + * [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. */ @@ -124,11 +124,11 @@ * * ---------------------------------------------------------------------- */ Tcl_Method -Tcl_NewInstanceMethod( +TclNewInstanceMethod( TCL_UNUSED(Tcl_Interp *), Tcl_Object object, /* The object that has the method attached to * it. */ Tcl_Obj *nameObj, /* The name of the method. May be NULL; if so, * up to caller to manage storage (e.g., when @@ -155,11 +155,11 @@ 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); + hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, nameObj, &isNew); if (isNew) { mPtr = (Method *)Tcl_Alloc(sizeof(Method)); mPtr->namePtr = nameObj; mPtr->refCount = 1; Tcl_IncrRefCount(nameObj); @@ -185,10 +185,54 @@ } } 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 -- @@ -197,11 +241,11 @@ * * ---------------------------------------------------------------------- */ Tcl_Method -Tcl_NewMethod( +TclNewMethod( TCL_UNUSED(Tcl_Interp *), Tcl_Class cls, /* The class to attach the method to. */ Tcl_Obj *nameObj, /* The name of the object. May be NULL (e.g., * for constructors or destructors); if so, up * to caller to manage storage. */ @@ -222,11 +266,11 @@ mPtr = (Method *)Tcl_Alloc(sizeof(Method)); mPtr->namePtr = NULL; mPtr->refCount = 1; goto populate; } - hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)nameObj,&isNew); + hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, nameObj,&isNew); if (isNew) { mPtr = (Method *)Tcl_Alloc(sizeof(Method)); mPtr->refCount = 1; mPtr->namePtr = nameObj; Tcl_IncrRefCount(nameObj); @@ -253,10 +297,52 @@ } } 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 -- @@ -302,11 +388,11 @@ * and the function to implement it. */ { Tcl_Obj *namePtr = Tcl_NewStringObj(dcm->name, -1); Tcl_IncrRefCount(namePtr); - Tcl_NewMethod(interp, (Tcl_Class) clsPtr, namePtr, + TclNewMethod(interp, (Tcl_Class) clsPtr, namePtr, (dcm->isPublic ? PUBLIC_METHOD : 0), &dcm->definition, NULL); Tcl_DecrRefCount(namePtr); } /* @@ -333,15 +419,15 @@ ProcedureMethod **pmPtrPtr) /* Place to write pointer to procedure method * structure to allow for deeper tuning of the * structure's contents. NULL if caller is not * interested. */ { - int argsLen; + Tcl_Size argsLen; ProcedureMethod *pmPtr; Tcl_Method method; - if (Tcl_ListObjLength(interp, argsObj, &argsLen) != TCL_OK) { + if (TclListObjLengthM(interp, argsObj, &argsLen) != TCL_OK) { return NULL; } pmPtr = (ProcedureMethod *)Tcl_Alloc(sizeof(ProcedureMethod)); memset(pmPtr, 0, sizeof(ProcedureMethod)); pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION; @@ -385,21 +471,21 @@ ProcedureMethod **pmPtrPtr) /* Place to write pointer to procedure method * structure to allow for deeper tuning of the * structure's contents. NULL if caller is not * interested. */ { - int argsLen; /* -1 => delete argsObj before exit */ + Tcl_Size argsLen; /* TCL_INDEX_NONE => delete argsObj before exit */ ProcedureMethod *pmPtr; const char *procName; Tcl_Method method; if (argsObj == NULL) { - argsLen = -1; + argsLen = TCL_INDEX_NONE; TclNewObj(argsObj); Tcl_IncrRefCount(argsObj); procName = ""; - } else if (Tcl_ListObjLength(interp, argsObj, &argsLen) != TCL_OK) { + } else if (TclListObjLengthM(interp, argsObj, &argsLen) != TCL_OK) { return NULL; } else { procName = (nameObj==NULL ? "" : TclGetString(nameObj)); } @@ -410,11 +496,11 @@ pmPtr->refCount = 1; method = TclOOMakeProcMethod(interp, clsPtr, flags, nameObj, procName, argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr); - if (argsLen == -1) { + if (argsLen == TCL_INDEX_NONE) { Tcl_DecrRefCount(argsObj); } if (method == NULL) { Tcl_Free(pmPtr); } else if (pmPtrPtr != NULL) { @@ -500,11 +586,11 @@ 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 = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size)); cfPtr->line[0] = context.line[3]; cfPtr->nline = 1; cfPtr->framePtr = NULL; cfPtr->nextPtr = NULL; @@ -513,11 +599,11 @@ cfPtr->cmd = NULL; cfPtr->len = 0; hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr, - (char *) procPtr, &isNew); + procPtr, &isNew); Tcl_SetHashValue(hPtr, cfPtr); } /* * 'context' is going out of scope; account for the reference that @@ -527,11 +613,11 @@ Tcl_DecrRefCount(context.data.eval.path); context.data.eval.path = NULL; } } - return Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, nameObj, flags, + return TclNewInstanceMethod(interp, (Tcl_Object) oPtr, nameObj, flags, typePtr, clientData); } /* * ---------------------------------------------------------------------- @@ -613,11 +699,11 @@ 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 = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size)); cfPtr->line[0] = context.line[3]; cfPtr->nline = 1; cfPtr->framePtr = NULL; cfPtr->nextPtr = NULL; @@ -626,11 +712,11 @@ cfPtr->cmd = NULL; cfPtr->len = 0; hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr, - (char *) procPtr, &isNew); + procPtr, &isNew); Tcl_SetHashValue(hPtr, cfPtr); } /* * 'context' is going out of scope; account for the reference that @@ -640,11 +726,11 @@ Tcl_DecrRefCount(context.data.eval.path); context.data.eval.path = NULL; } } - return Tcl_NewMethod(interp, (Tcl_Class) clsPtr, nameObj, flags, typePtr, + return TclNewMethod(interp, (Tcl_Class) clsPtr, nameObj, flags, typePtr, clientData); } /* * ---------------------------------------------------------------------- @@ -857,11 +943,11 @@ * 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); + ByteCodeGetInternalRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, codePtr); if (codePtr) { codePtr->nsPtr = nsPtr; } result = TclProcCompileProc(interp, pmPtr->procPtr, pmPtr->procPtr->bodyPtr, nsPtr, "body of method", namePtr); @@ -985,12 +1071,12 @@ CallFrame *framePtr = iPtr->varFramePtr; CallContext *contextPtr; Tcl_Obj *variableObj; PrivateVariableMapping *privateVar; Tcl_HashEntry *hPtr; - int i, isNew, cacheIt; - size_t varLen, len; + int isNew, cacheIt; + Tcl_Size i, varLen, len; const char *match, *varName; /* * Check that the variable is being requested in a context that is also a * method call; if not (i.e. we're evaluating in the object's namespace or @@ -1015,41 +1101,41 @@ * Check if the variable is one we want to resolve at all (i.e. whether it * is in the list provided by the user). If not, we mustn't do anything * either. */ - varName = TclGetStringFromObj(infoPtr->variableObj, &varLen); + varName = Tcl_GetStringFromObj(infoPtr->variableObj, &varLen); if (contextPtr->callPtr->chain[contextPtr->index] .mPtr->declaringClassPtr != NULL) { FOREACH_STRUCT(privateVar, contextPtr->callPtr->chain[contextPtr->index] .mPtr->declaringClassPtr->privateVariables) { - match = TclGetStringFromObj(privateVar->variableObj, &len); + match = Tcl_GetStringFromObj(privateVar->variableObj, &len); if ((len == varLen) && !memcmp(match, varName, len)) { variableObj = privateVar->fullNameObj; cacheIt = 0; goto gotMatch; } } FOREACH(variableObj, contextPtr->callPtr->chain[contextPtr->index] .mPtr->declaringClassPtr->variables) { - match = TclGetStringFromObj(variableObj, &len); + match = Tcl_GetStringFromObj(variableObj, &len); if ((len == varLen) && !memcmp(match, varName, len)) { cacheIt = 0; goto gotMatch; } } } else { FOREACH_STRUCT(privateVar, contextPtr->oPtr->privateVariables) { - match = TclGetStringFromObj(privateVar->variableObj, &len); + match = Tcl_GetStringFromObj(privateVar->variableObj, &len); if ((len == varLen) && !memcmp(match, varName, len)) { variableObj = privateVar->fullNameObj; cacheIt = 1; goto gotMatch; } } FOREACH(variableObj, contextPtr->oPtr->variables) { - match = TclGetStringFromObj(variableObj, &len); + match = Tcl_GetStringFromObj(variableObj, &len); if ((len == varLen) && !memcmp(match, varName, len)) { cacheIt = 1; goto gotMatch; } } @@ -1060,11 +1146,11 @@ * It is a variable we want to resolve, so resolve it. */ gotMatch: hPtr = Tcl_CreateHashEntry(TclVarTable(contextPtr->oPtr->namespacePtr), - (char *) variableObj, &isNew); + variableObj, &isNew); if (isNew) { TclSetVarNamespaceVar((Var *) TclVarHashGetValue(hPtr)); } if (cacheIt) { infoPtr->cachedObjectVar = TclVarHashGetValue(hPtr); @@ -1100,11 +1186,11 @@ static int ProcedureMethodCompiledVarResolver( TCL_UNUSED(Tcl_Interp *), const char *varName, - int length, + Tcl_Size length, TCL_UNUSED(Tcl_Namespace *), Tcl_ResolvedVarInfo **rPtrPtr) { OOResVarInfo *infoPtr; Tcl_Obj *variableObj = Tcl_NewStringObj(varName, length); @@ -1181,15 +1267,15 @@ 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; + Tcl_Size nameLen, objectNameLen; CallContext *contextPtr = (CallContext *)((Interp *) interp)->varFramePtr->clientData; Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; const char *objectName, *kindName, *methodName = - TclGetStringFromObj(mPtr->namePtr, &nameLen); + Tcl_GetStringFromObj(mPtr->namePtr, &nameLen); Object *declarerPtr; if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; kindName = "object"; @@ -1199,11 +1285,11 @@ } declarerPtr = mPtr->declaringClassPtr->thisPtr; kindName = "class"; } - objectName = TclGetStringFromObj(TclOOObjectName(interp, declarerPtr), + objectName = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr), &objectNameLen); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (%s \"%.*s%s\" method \"%.*s%s\" line %d)", kindName, ELLIPSIFY(objectName, objectNameLen), ELLIPSIFY(methodName, nameLen), Tcl_GetErrorLine(interp))); @@ -1217,11 +1303,11 @@ { CallContext *contextPtr = (CallContext *)((Interp *) interp)->varFramePtr->clientData; Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; Object *declarerPtr; const char *objectName, *kindName; - size_t objectNameLen; + Tcl_Size objectNameLen; if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; kindName = "object"; } else { @@ -1230,11 +1316,11 @@ } declarerPtr = mPtr->declaringClassPtr->thisPtr; kindName = "class"; } - objectName = TclGetStringFromObj(TclOOObjectName(interp, declarerPtr), + objectName = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr), &objectNameLen); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (%s \"%.*s%s\" constructor line %d)", kindName, ELLIPSIFY(objectName, objectNameLen), Tcl_GetErrorLine(interp))); } @@ -1247,11 +1333,11 @@ { CallContext *contextPtr = (CallContext *)((Interp *) interp)->varFramePtr->clientData; Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; Object *declarerPtr; const char *objectName, *kindName; - size_t objectNameLen; + Tcl_Size objectNameLen; if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; kindName = "object"; } else { @@ -1260,11 +1346,11 @@ } declarerPtr = mPtr->declaringClassPtr->thisPtr; kindName = "class"; } - objectName = TclGetStringFromObj(TclOOObjectName(interp, declarerPtr), + objectName = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr), &objectNameLen); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (%s \"%.*s%s\" destructor line %d)", kindName, ELLIPSIFY(objectName, objectNameLen), Tcl_GetErrorLine(interp))); } @@ -1337,11 +1423,11 @@ * bound references to instance variables are removed. [Bug 3609693] */ bodyObj = Tcl_DuplicateObj(pmPtr->procPtr->bodyPtr); TclGetString(bodyObj); - Tcl_StoreIntRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, NULL); + Tcl_StoreInternalRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, NULL); /* * Create the actual copy of the method record, manufacturing a new proc * record. */ @@ -1385,27 +1471,27 @@ int flags, /* Whether the method is public or not. */ Tcl_Obj *nameObj, /* The name of the method. */ Tcl_Obj *prefixObj) /* List of arguments that form the command * prefix to forward to. */ { - int prefixLen; + Tcl_Size prefixLen; ForwardMethod *fmPtr; - if (Tcl_ListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) { + if (TclListObjLengthM(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); + Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", (void *)NULL); return NULL; } fmPtr = (ForwardMethod *)Tcl_Alloc(sizeof(ForwardMethod)); fmPtr->prefixObj = prefixObj; Tcl_IncrRefCount(prefixObj); - return (Method *) Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, + return (Method *) TclNewInstanceMethod(interp, (Tcl_Object) oPtr, nameObj, flags, &fwdMethodType, fmPtr); } /* * ---------------------------------------------------------------------- @@ -1424,27 +1510,27 @@ int flags, /* Whether the method is public or not. */ Tcl_Obj *nameObj, /* The name of the method. */ Tcl_Obj *prefixObj) /* List of arguments that form the command * prefix to forward to. */ { - int prefixLen; + Tcl_Size prefixLen; ForwardMethod *fmPtr; - if (Tcl_ListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) { + if (TclListObjLengthM(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); + Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", (void *)NULL); return NULL; } fmPtr = (ForwardMethod *)Tcl_Alloc(sizeof(ForwardMethod)); fmPtr->prefixObj = prefixObj; Tcl_IncrRefCount(prefixObj); - return (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, nameObj, + return (Method *) TclNewMethod(interp, (Tcl_Class) clsPtr, nameObj, flags, &fwdMethodType, fmPtr); } /* * ---------------------------------------------------------------------- @@ -1466,20 +1552,21 @@ 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; + Tcl_Size numPrefixes, skip = contextPtr->skip; + int len; /* * Build the real list of arguments to use. Note that we know that the * prefixObj field of the ForwardMethod structure holds a reference to a * non-empty list, so there's a whole class of failures ("not a list") we * can ignore here. */ - Tcl_ListObjGetElements(NULL, fmPtr->prefixObj, &numPrefixes, &prefixObjs); + TclListObjGetElementsM(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 @@ -1618,11 +1705,11 @@ 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; + 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)); @@ -1669,23 +1756,63 @@ 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; } Index: generic/tclOOScript.h ================================================================== --- generic/tclOOScript.h +++ generic/tclOOScript.h @@ -17,21 +17,21 @@ #define TCL_OO_SCRIPT_H /* * The scripted part of the definitions of TclOO. * - * Compiled from generic/tclOOScript.tcl by tools/makeHeader.tcl, which + * Compiled from tools/tclOOScript.tcl by tools/makeHeader.tcl, which * contains the commented version of everything; *this* file is automatically * generated. */ static const char *tclOOSetupScript = /* !BEGIN!: Do not edit below this line. */ "::namespace eval ::oo {\n" "\t::namespace path {}\n" "\tnamespace eval Helpers {\n" -"\t\t::namespace path {}\n" +"\t\tnamespace path {}\n" "\t\tproc callback {method args} {\n" "\t\t\tlist [uplevel 1 {::namespace which my}] $method {*}$args\n" "\t\t}\n" "\t\tnamespace export callback\n" "\t\tnamespace eval tmp {namespace import ::oo::Helpers::callback}\n" @@ -96,13 +96,13 @@ "\t\tforeach c [info class superclass $class] {\n" "\t\t\tset d [DelegateName $c]\n" "\t\t\tif {![info object isa class $d]} {\n" "\t\t\t\tcontinue\n" "\t\t\t}\n" -"\t\t\tdefine $delegate ::oo::define::superclass -append $d\n" +"\t\t\tdefine $delegate ::oo::define::superclass -appendifnew $d\n" "\t\t}\n" -"\t\tobjdefine $class ::oo::objdefine::mixin -append $delegate\n" +"\t\tobjdefine $class ::oo::objdefine::mixin -appendifnew $delegate\n" "\t}\n" "\tproc UpdateClassDelegatesAfterClone {originObject targetObject} {\n" "\t\tset originDelegate [DelegateName $originObject]\n" "\t\tset targetDelegate [DelegateName $targetObject]\n" "\t\tif {\n" @@ -114,20 +114,20 @@ "\t\t\t\t{*}[lmap c [info object mixin $targetObject] {\n" "\t\t\t\t\tif {$c eq $originDelegate} {set targetDelegate} {set c}\n" "\t\t\t\t}]\n" "\t\t}\n" "\t}\n" -"\tproc define::classmethod {name {args {}} {body {}}} {\n" +"\tproc define::classmethod {name args} {\n" "\t\t::set argc [::llength [::info level 0]]\n" "\t\t::if {$argc == 3} {\n" "\t\t\t::return -code error -errorcode {TCL WRONGARGS} [::format \\\n" "\t\t\t\t{wrong # args: should be \"%s name \?args body\?\"} \\\n" "\t\t\t\t[::lindex [::info level 0] 0]]\n" "\t\t}\n" "\t\t::set cls [::uplevel 1 self]\n" "\t\t::if {$argc == 4} {\n" -"\t\t\t::oo::define [::oo::DelegateName $cls] method $name $args $body\n" +"\t\t\t::oo::define [::oo::DelegateName $cls] method $name {*}$args\n" "\t\t}\n" "\t\t::tailcall forward $name myclass $name\n" "\t}\n" "\tproc define::initialise {body} {\n" "\t\t::set clsns [::info object namespace [::uplevel 1 self]]\n" @@ -139,62 +139,72 @@ "\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\tmethod Get -unexport {} {\n" "\t\t\treturn -code error -errorcode {TCLOO ABSTRACT_SLOT} \"unimplemented\"\n" "\t\t}\n" -"\t\tmethod Set list {\n" +"\t\tmethod Set -unexport list {\n" "\t\t\treturn -code error -errorcode {TCLOO ABSTRACT_SLOT} \"unimplemented\"\n" "\t\t}\n" -"\t\tmethod Resolve list {\n" +"\t\tmethod Resolve -unexport list {\n" "\t\t\treturn $list\n" "\t\t}\n" -"\t\tmethod -set args {\n" +"\t\tmethod -set -export args {\n" "\t\t\tset my [namespace which my]\n" "\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n" "\t\t\ttailcall my Set $args\n" "\t\t}\n" -"\t\tmethod -append args {\n" +"\t\tmethod -append -export args {\n" "\t\t\tset my [namespace which my]\n" "\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n" "\t\t\tset current [uplevel 1 [list $my Get]]\n" "\t\t\ttailcall my Set [list {*}$current {*}$args]\n" "\t\t}\n" -"\t\tmethod -clear {} {tailcall my Set {}}\n" -"\t\tmethod -prepend args {\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 args {\n" +"\t\tmethod -remove -export args {\n" "\t\t\tset my [namespace which my]\n" "\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n" "\t\t\tset current [uplevel 1 [list $my Get]]\n" "\t\t\ttailcall my Set [lmap val $current {\n" "\t\t\t\tif {$val in $args} continue else {set val}\n" "\t\t\t}]\n" "\t\t}\n" "\t\tforward --default-operation my -append\n" -"\t\tmethod unknown {args} {\n" +"\t\tmethod unknown -unexport {args} {\n" "\t\t\tset def --default-operation\n" "\t\t\tif {[llength $args] == 0} {\n" "\t\t\t\ttailcall my $def\n" "\t\t\t} elseif {![string match -* [lindex $args 0]]} {\n" "\t\t\t\ttailcall my $def {*}$args\n" "\t\t\t}\n" "\t\t\tnext {*}$args\n" "\t\t}\n" -"\t\texport -set -append -clear -prepend -remove\n" -"\t\tunexport unknown destroy\n" +"\t\tunexport destroy\n" "\t}\n" "\tobjdefine define::superclass forward --default-operation my -set\n" "\tobjdefine define::mixin forward --default-operation my -set\n" "\tobjdefine objdefine::mixin forward --default-operation my -set\n" -"\tdefine object method {originObject} {\n" +"\tdefine object method -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" @@ -217,11 +227,11 @@ "\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 {originObject} {\n" +"\tdefine class method -unexport {originObject} {\n" "\t\tnext $originObject\n" "\t\t::oo::UpdateClassDelegatesAfterClone $originObject [self]\n" "\t}\n" "\tclass create singleton {\n" "\t\tsuperclass class\n" @@ -233,11 +243,11 @@ "\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 {originObject} {\n" +"\t\t\t\t\tmethod -unexport {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" @@ -246,10 +256,230 @@ "\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 {TCLOO 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 {TCLOO 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 {TCLOO 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 {TCLOO 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 \n" +"\t\t\t\tset writer \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 ]\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 {TCLOO 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 {TCLOO 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 ]\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 {TCLOO 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 {TCLOO 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 $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 {TCLOO 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 {TCLOO 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 */ Index: generic/tclOOStubInit.c ================================================================== --- generic/tclOOStubInit.c +++ generic/tclOOStubInit.c @@ -72,8 +72,13 @@ 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. */ Index: generic/tclOOStubLib.c ================================================================== --- generic/tclOOStubLib.c +++ generic/tclOOStubLib.c @@ -33,18 +33,23 @@ TclOOInitializeStubs( Tcl_Interp *interp, const char *version) { int exact = 0; - const char *packageName = "TclOO"; + const char *packageName = "tcl::oo"; const char *errMsg = NULL; TclOOStubs *stubsPtr = NULL; const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, exact, &stubsPtr); if (actualVersion == NULL) { - return 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; Index: generic/tclObj.c ================================================================== --- generic/tclObj.c +++ generic/tclObj.c @@ -2,15 +2,15 @@ * 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 + * 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 * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -78,11 +78,11 @@ 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 + * 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 @@ -95,11 +95,11 @@ #endif /* TCL_MEM_DEBUG && TCL_THREADS */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; -static void TclThreadFinalizeContLines(ClientData clientData); +static void TclThreadFinalizeContLines(void *clientData); static ThreadSpecificData *TclGetContLineTable(void); /* * Nested Tcl_Obj deletion management support * @@ -109,18 +109,18 @@ * freed without taking a vast depth of C stack (which could cause all sorts * of breakage.) */ typedef struct PendingObjData { - int deletionCount; /* Count of the number of invokations of + int deletionCount; /* Count of the number of invocations of * TclFreeObj() are on the stack (at least * conceptually; many are actually expanded * macros). */ Tcl_Obj *deletionStack; /* Stack of objects that have had TclFreeObj() * invoked upon them but which can't be * deleted yet because they are in a nested - * invokation of TclFreeObj(). By postponing + * invocation of TclFreeObj(). By postponing * this way, we limit the maximum overall C * stack depth when deleting a complex object. * The down-side is that we alter the overall * behaviour by altering the order in which * objects are deleted, and we change the @@ -223,37 +223,41 @@ * means of functions that can be invoked by generic object code. See also * tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager * implementations. */ -const Tcl_ObjType tclBooleanType = { +const Tcl_ObjType tclBooleanType= { "boolean", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ NULL, /* updateStringProc */ - TclSetBooleanFromAny /* setFromAnyProc */ + TclSetBooleanFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V1(TclLengthOne) }; -const Tcl_ObjType tclDoubleType = { +const Tcl_ObjType tclDoubleType= { "double", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfDouble, /* updateStringProc */ - SetDoubleFromAny /* setFromAnyProc */ + SetDoubleFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V1(TclLengthOne) }; const Tcl_ObjType tclIntType = { "int", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfInt, /* updateStringProc */ - SetIntFromAny /* setFromAnyProc */ + SetIntFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V1(TclLengthOne) }; const Tcl_ObjType tclBignumType = { "bignum", /* name */ FreeBignum, /* freeIntRepProc */ DupBignum, /* dupIntRepProc */ UpdateStringOfBignum, /* updateStringProc */ - NULL /* setFromAnyProc */ + NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V1(TclLengthOne) }; /* * The structure below defines the Tcl obj hash key type. */ @@ -293,11 +297,12 @@ Tcl_ObjType tclCmdNameType = { "cmdName", /* name */ FreeCmdNameInternalRep, /* freeIntRepProc */ DupCmdNameInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetCmdNameFromAny /* setFromAnyProc */ + SetCmdNameFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; /* * Structure containing a cached pointer to a command that is the result of * resolving the command's name in some namespace. It is the internal @@ -314,16 +319,16 @@ size_t refNsId; /* refNsPtr's unique namespace id. Used to * verify that refNsPtr is still valid (e.g., * it's possible that the cmd's containing * namespace was deleted and a new one created * at the same address). */ - size_t refNsCmdEpoch; /* Value of the referencing namespace's + Tcl_Size refNsCmdEpoch; /* Value of the referencing namespace's * cmdRefEpoch when the pointer was cached. * Before using the cached pointer, we check * if the namespace's epoch was incremented; * if so, this cached pointer is invalid. */ - size_t cmdEpoch; /* Value of the command's cmdEpoch when this + Tcl_Size cmdEpoch; /* Value of the command's cmdEpoch when this * pointer was cached. Before using the cached * pointer, we check if the cmd's epoch was * incremented; if so, the cmd was renamed, * deleted, hidden, or exposed, and so the * pointer is invalid. */ @@ -331,10 +336,22 @@ * 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 -- @@ -358,11 +375,10 @@ 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); @@ -524,18 +540,18 @@ */ ContLineLoc * TclContinuationsEnter( Tcl_Obj *objPtr, - int num, - int *loc) + Tcl_Size num, + Tcl_Size *loc) { int newEntry; ThreadSpecificData *tsdPtr = TclGetContLineTable(); Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(tsdPtr->lineCLPtr, objPtr, &newEntry); - ContLineLoc *clLocPtr = (ContLineLoc *)Tcl_Alloc(offsetof(ContLineLoc, loc) + (num + 1) *sizeof(int)); + ContLineLoc *clLocPtr = (ContLineLoc *)Tcl_Alloc(offsetof(ContLineLoc, loc) + (num + 1U) *sizeof(Tcl_Size)); if (!newEntry) { /* * We're entering ContLineLoc data for the same value more than one * time. Taking care not to leak the old entry. @@ -543,11 +559,11 @@ * This can happen when literals in a proc body are shared. See for * example test info-30.19 where the action (code) for all branches of * the switch command is identical, mapping them all to the same * literal. An interesting result of this is that the number and * locations (offset) of invisible continuation lines in the literal - * are the same for all occurences. + * are the same for all occurrences. * * Note that while reusing the existing entry is possible it requires * the same actions as for a new entry because we have to copy the * incoming num/loc data even so. Because we are called from * TclContinuationsEnterDerived for this case, which modified the @@ -559,11 +575,11 @@ Tcl_Free(Tcl_GetHashValue(hPtr)); } clLocPtr->num = num; - memcpy(&clLocPtr->loc, loc, num*sizeof(int)); + memcpy(&clLocPtr->loc, loc, num*sizeof(Tcl_Size)); clLocPtr->loc[num] = CLL_END; /* Sentinel */ Tcl_SetHashValue(hPtr, clLocPtr); return clLocPtr; } @@ -588,16 +604,16 @@ */ void TclContinuationsEnterDerived( Tcl_Obj *objPtr, - int start, - int *clNext) + Tcl_Size start, + Tcl_Size *clNext) { - size_t length; - int end, num; - int *wordCLLast = clNext; + Tcl_Size length; + Tcl_Size end, num; + Tcl_Size *wordCLLast = clNext; /* * We have to handle invisible continuations lines here as well, despite * the code we have in TclSubstTokens (TST) for that. Why ? Nesting. If * our script is the sole argument to an 'eval' command, for example, the @@ -619,11 +635,11 @@ /* * First compute the range of the word within the script. (Is there a * better way which doesn't shimmer?) */ - (void)TclGetStringFromObj(objPtr, &length); + (void)Tcl_GetStringFromObj(objPtr, &length); end = start + length; /* First char after the word */ /* * Then compute the table slice covering the range of the word. */ @@ -636,11 +652,11 @@ * And generate the table from the slice, if it was not empty. */ num = wordCLLast - clNext; if (num) { - int i; + Tcl_Size i; ContLineLoc *clLocPtr = TclContinuationsEnter(objPtr, num, clNext); /* * Re-base the locations. */ @@ -748,11 +764,11 @@ *---------------------------------------------------------------------- */ static void TclThreadFinalizeContLines( - TCL_UNUSED(ClientData)) + TCL_UNUSED(void *)) { /* * Release the hashtable tracking invisible continuation lines. */ @@ -834,17 +850,17 @@ * name of each registered type is appended as * a list element. */ { Tcl_HashEntry *hPtr; Tcl_HashSearch search; - int numElems; + Tcl_Size numElems; /* * Get the test for a valid list out of the way first. */ - if (TclListObjLength(interp, objPtr, &numElems) != TCL_OK) { + if (TclListObjLengthM(interp, objPtr, &numElems) != TCL_OK) { return TCL_ERROR; } /* * Type names are NUL-terminated, not counted strings. This code relies on @@ -932,11 +948,11 @@ if (typePtr->setFromAnyProc == NULL) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't convert value to type %s", typePtr->name)); - Tcl_SetErrorCode(interp, "TCL", "API_ABUSE", NULL); + Tcl_SetErrorCode(interp, "TCL", "API_ABUSE", (void *)NULL); } return TCL_ERROR; } return typePtr->setFromAnyProc(interp, objPtr); @@ -970,11 +986,11 @@ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); tablePtr = tsdPtr->objThreadMap; if (tablePtr != NULL) { - fprintf(outFile, "total objects: %" TCL_Z_MODIFIER "u\n", tablePtr->numEntries); + fprintf(outFile, "total objects: %" TCL_SIZE_MODIFIER "d\n", tablePtr->numEntries); for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { ObjData *objData = (ObjData *)Tcl_GetHashValue(hPtr); if (objData != NULL) { @@ -1002,11 +1018,11 @@ * * TclDbInitNewObj -- * * Called via the TclNewObj or TclDbNewObj macros when TCL_MEM_DEBUG is * enabled. This function will initialize the members of a Tcl_Obj - * struct. Initilization would be done inline via the TclNewObj macro + * struct. Initialization would be done inline via the TclNewObj macro * when compiling without TCL_MEM_DEBUG. * * Results: * The Tcl_Obj struct members are initialized. * @@ -1024,11 +1040,11 @@ int line) /* Line number in the source file; used for * debugging. */ { objPtr->refCount = 0; objPtr->typePtr = NULL; - TclInitStringRep(objPtr, NULL, 0); + TclInitEmptyStringRep(objPtr); #if TCL_THREADS /* * Add entry to a thread local map used to check if a Tcl_Obj was * allocated by the currently executing thread. @@ -1166,11 +1182,13 @@ Tcl_Obj * Tcl_DbNewObj( TCL_UNUSED(const char *) /*file*/, TCL_UNUSED(int) /*line*/) { - return Tcl_NewObj(); + Tcl_Obj *objPtr; + TclNewObj(objPtr); + return objPtr; } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- @@ -1276,11 +1294,11 @@ tablePtr = tsdPtr->objThreadMap; if (!tablePtr) { Tcl_Panic("TclFreeObj: object table not initialized"); } - hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr); + hPtr = Tcl_FindHashEntry(tablePtr, objPtr); if (hPtr) { /* * As the Tcl_Obj is going to be deleted we remove the entry. */ @@ -1299,11 +1317,11 @@ * Check for a double free of the same value. This is slightly tricky * because it is customary to free a Tcl_Obj when its refcount falls * either from 1 to 0, or from 0 to -1. Falling from -1 to -2, though, * and so on, is always a sign of a botch in the caller. */ - if (objPtr->refCount == (size_t)-2) { + if (objPtr->refCount == (Tcl_Size)-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. @@ -1338,11 +1356,11 @@ while (ObjOnStack(context)) { Tcl_Obj *objToFree; PopObjToDelete(context, objToFree); TCL_DTRACE_OBJ_FREE(objToFree); - TclFreeIntRep(objToFree); + TclFreeInternalRep(objToFree); Tcl_MutexLock(&tclObjMutex); Tcl_Free(objToFree); Tcl_MutexUnlock(&tclObjMutex); TclIncrObjsFreed(); @@ -1354,11 +1372,11 @@ * We cannot use TclGetContinuationTable() here, because that may * re-initialize the thread-data for calls coming after the finalization. * We have to access it using the low-level call and then check for * validity. This function can be called after TclFinalizeThreadData() has * already killed the thread-global data structures. Performing - * TCL_TSD_INIT will leave us with an un-initialized memory block upon + * TCL_TSD_INIT will leave us with an uninitialized memory block upon * which we crash (if we where to access the uninitialized hashtable). */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -1445,11 +1463,11 @@ * We cannot use TclGetContinuationTable() here, because that may * re-initialize the thread-data for calls coming after the finalization. * We have to access it using the low-level call and then check for * validity. This function can be called after TclFinalizeThreadData() has * already killed the thread-global data structures. Performing - * TCL_TSD_INIT will leave us with an un-initialized memory block upon + * TCL_TSD_INIT will leave us with an uninitialized memory block upon * which we crash (if we where to access the uninitialized hashtable). */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -1557,11 +1575,11 @@ { if (Tcl_IsShared(dupPtr)) { Tcl_Panic("%s called with shared object", "TclSetDuplicateObj"); } TclInvalidateStringRep(dupPtr); - TclFreeIntRep(dupPtr); + TclFreeInternalRep(dupPtr); SetDuplicateObj(dupPtr, objPtr); } /* *---------------------------------------------------------------------- @@ -1582,10 +1600,11 @@ * representation from the internal representation. * *---------------------------------------------------------------------- */ +#undef Tcl_GetString char * Tcl_GetString( Tcl_Obj *objPtr) /* Object whose string rep byte pointer should * be returned. */ { @@ -1618,11 +1637,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_GetStringFromObj -- + * Tcl_GetStringFromObj/TclGetStringFromObj -- * * Returns the string representation's byte array pointer and length for * an object. * * Results: @@ -1638,15 +1657,16 @@ * representation from the internal representation. * *---------------------------------------------------------------------- */ +#if !defined(TCL_NO_DEPRECATED) char * -Tcl_GetStringFromObj( +TclGetStringFromObj( Tcl_Obj *objPtr, /* Object whose string rep byte pointer should * be returned. */ - int *lengthPtr) /* If non-NULL, the location where the string + void *lengthPtr) /* If non-NULL, the location where the string * rep's byte array length should * be stored. * If NULL, no length is stored. */ { if (objPtr->bytes == NULL) { /* @@ -1672,14 +1692,60 @@ "failed to create a valid string rep", objPtr->typePtr->name); } } if (lengthPtr != NULL) { - *lengthPtr = (objPtr->length < INT_MAX)? objPtr->length: INT_MAX; + if (objPtr->length > INT_MAX) { + Tcl_Panic("Tcl_GetStringFromObj with 'int' lengthPtr" + " cannot handle such long strings. Please use 'Tcl_Size'"); + } + *(int *)lengthPtr = (int)objPtr->length; + } + return objPtr->bytes; +} +#endif /* !defined(TCL_NO_DEPRECATED) */ + +#undef Tcl_GetStringFromObj +char * +Tcl_GetStringFromObj( + Tcl_Obj *objPtr, /* Object whose string rep byte pointer should + * be returned. */ + Tcl_Size *lengthPtr) /* If non-NULL, the location where the string + * rep's byte array length should * be stored. + * If NULL, no length is stored. */ +{ + if (objPtr->bytes == NULL) { + /* + * Note we do not check for objPtr->typePtr == NULL. An invariant + * of a properly maintained Tcl_Obj is that at least one of + * objPtr->bytes and objPtr->typePtr must not be NULL. If broken + * extensions fail to maintain that invariant, we can crash here. + */ + + if (objPtr->typePtr->updateStringProc == NULL) { + /* + * Those Tcl_ObjTypes which choose not to define an + * updateStringProc must be written in such a way that + * (objPtr->bytes) never becomes NULL. + */ + Tcl_Panic("UpdateStringProc should not be invoked for type %s", + objPtr->typePtr->name); + } + objPtr->typePtr->updateStringProc(objPtr); + if (objPtr->bytes == NULL + || objPtr->bytes[objPtr->length] != '\0') { + Tcl_Panic("UpdateStringProc for type '%s' " + "failed to create a valid string rep", + objPtr->typePtr->name); + } + } + if (lengthPtr != NULL) { + *lengthPtr = objPtr->length; } return objPtr->bytes; } + /* *---------------------------------------------------------------------- * * Tcl_InitStringRep -- @@ -1729,35 +1795,51 @@ 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'; + 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; } /* @@ -1806,17 +1888,17 @@ } /* *---------------------------------------------------------------------- * - * Tcl_StoreIntRep -- + * Tcl_StoreInternalRep -- * - * This function is called to set the object's internal - * representation to match a particular type. + * Called to set the object's internal representation to match a + * particular type. * * It is the caller's responsibility to guarantee that - * the value of the submitted IntRep is in agreement with + * the value of the submitted internalrep is in agreement with * the value of any existing string rep. * * Results: * None. * @@ -1826,21 +1908,21 @@ * *---------------------------------------------------------------------- */ void -Tcl_StoreIntRep( +Tcl_StoreInternalRep( Tcl_Obj *objPtr, /* Object whose internal rep should be set. */ const Tcl_ObjType *typePtr, /* New type for the object */ - const Tcl_ObjIntRep *irPtr) /* New IntRep for the object */ + const Tcl_ObjInternalRep *irPtr) /* New internalrep for the object */ { - /* Clear out any existing IntRep ( "shimmer" ) */ - TclFreeIntRep(objPtr); + /* Clear out any existing internalrep ( "shimmer" ) */ + TclFreeInternalRep(objPtr); - /* When irPtr == NULL, just leave objPtr with no IntRep for typePtr */ + /* When irPtr == NULL, just leave objPtr with no internalrep for typePtr */ if (irPtr) { - /* Copy the new IntRep into place */ + /* Copy the new internalrep into place */ objPtr->internalRep = *irPtr; /* Set the type to match */ objPtr->typePtr = typePtr; } @@ -1847,38 +1929,38 @@ } /* *---------------------------------------------------------------------- * - * Tcl_FetchIntRep -- + * Tcl_FetchInternalRep -- * * This function is called to retrieve the object's internal * representation matching a requested type, if any. * * Results: - * A read-only pointer to the associated Tcl_ObjIntRep, or + * A read-only pointer to the associated Tcl_ObjInternalRep, or * NULL if no such internal representation exists. * * Side effects: * Calls the freeIntRepProc of the current Tcl_ObjType, if any. * Sets the internalRep and typePtr fields to the submitted values. * *---------------------------------------------------------------------- */ -Tcl_ObjIntRep * -Tcl_FetchIntRep( +Tcl_ObjInternalRep * +Tcl_FetchInternalRep( Tcl_Obj *objPtr, /* Object to fetch from. */ const Tcl_ObjType *typePtr) /* Requested type */ { - return TclFetchIntRep(objPtr, typePtr); + return TclFetchInternalRep(objPtr, typePtr); } /* *---------------------------------------------------------------------- * - * Tcl_FreeIntRep -- + * Tcl_FreeInternalRep -- * * This function is called to free an object's internal representation. * * Results: * None. @@ -1889,20 +1971,20 @@ * *---------------------------------------------------------------------- */ void -Tcl_FreeIntRep( +Tcl_FreeInternalRep( Tcl_Obj *objPtr) /* Object whose internal rep should be freed. */ { - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); } /* *---------------------------------------------------------------------- * - * Tcl_GetBooleanFromObj -- + * Tcl_GetBoolFromObj, Tcl_GetBooleanFromObj -- * * Attempt to return a boolean from the Tcl object "objPtr". This * includes conversion from any of Tcl's numeric types. * * Results: @@ -1909,30 +1991,46 @@ * The return value is a standard Tcl object result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * * Side effects: - * The intrep of *objPtr may be changed. + * The internalrep of *objPtr may be changed. * *---------------------------------------------------------------------- */ +#undef Tcl_GetBoolFromObj int -Tcl_GetBooleanFromObj( +Tcl_GetBoolFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr, /* The object from which to get boolean. */ - int *boolPtr) /* Place to store resulting 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 (objPtr->typePtr == &tclIntType || objPtr->typePtr == &tclBooleanType) { - *boolPtr = (objPtr->internalRep.wideValue != 0); - return TCL_OK; + result = (objPtr->internalRep.wideValue != 0); + goto boolEnd; } 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 + * 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. */ @@ -1939,22 +2037,49 @@ double d; if (Tcl_GetDoubleFromObj(interp, objPtr, &d) != TCL_OK) { return TCL_ERROR; } - *boolPtr = (d != 0.0); - return TCL_OK; + result = (d != 0.0); + goto boolEnd; } if (objPtr->typePtr == &tclBignumType) { - *boolPtr = 1; + 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, "boolean value", NULL,-1,NULL,0))); + TclParseNumber(interp, objPtr, (flags & TCL_NULL_OK) + ? "boolean value or \"\"" : "boolean value", NULL,-1,NULL,0))); return TCL_ERROR; } +#undef Tcl_GetBooleanFromObj +int +Tcl_GetBooleanFromObj( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tcl_Obj *objPtr, /* The object from which to get boolean. */ + int *intPtr) /* Place to store resulting boolean. */ +{ + return Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof(int), (char *)(void *)intPtr); +} + /* *---------------------------------------------------------------------- * * TclSetBooleanFromAny -- * @@ -2005,19 +2130,19 @@ return TCL_OK; } badBoolean: if (interp != NULL) { - size_t length; - const char *str = TclGetStringFromObj(objPtr, &length); + Tcl_Size length; + const char *str = Tcl_GetStringFromObj(objPtr, &length); Tcl_Obj *msg; TclNewLiteralStringObj(msg, "expected boolean value but got \""); Tcl_AppendLimitedToObj(msg, str, length, 50, ""); Tcl_AppendToObj(msg, "\"", -1); Tcl_SetObjResult(interp, msg); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "BOOLEAN", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "BOOLEAN", (void *)NULL); } return TCL_ERROR; } static int @@ -2024,17 +2149,17 @@ ParseBoolean( Tcl_Obj *objPtr) /* The object to parse/convert. */ { int newBool; char lowerCase[6]; - size_t i, length; - const char *str = TclGetStringFromObj(objPtr, &length); + Tcl_Size i, length; + const char *str = Tcl_GetStringFromObj(objPtr, &length); - if ((length == 0) || (length > 5)) { + if ((length <= 0) || (length > 5)) { /* - * Longest valid boolean string rep. is "false". - */ + * Longest valid boolean string rep. is "false". + */ return TCL_ERROR; } switch (str[0]) { @@ -2123,17 +2248,17 @@ * as possible to allow the conversion code, in particular * Tcl_GetStringFromObj, to use that old internalRep. */ goodBoolean: - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); objPtr->internalRep.wideValue = newBool; objPtr->typePtr = &tclBooleanType; return TCL_OK; numericBoolean: - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); objPtr->internalRep.wideValue = newBool; objPtr->typePtr = &tclIntType; return TCL_OK; } @@ -2297,16 +2422,16 @@ 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 (isnan(objPtr->internalRep.doubleValue)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "floating point value is Not a Number", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DOUBLE", "NAN", - NULL); + (void *)NULL); } return TCL_ERROR; } *dblPtr = (double) objPtr->internalRep.doubleValue; return TCL_OK; @@ -2431,20 +2556,21 @@ return TCL_ERROR; } if ((ULONG_MAX > UINT_MAX) && ((l > UINT_MAX) || (l < INT_MIN))) { if (interp != NULL) { const char *s = - "integer value too large to represent as non-long integer"; + "integer value too large to represent"; Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1)); - Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL); + Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (void *)NULL); } return TCL_ERROR; } *intPtr = (int) l; return TCL_OK; #endif } + /* *---------------------------------------------------------------------- * * SetIntFromAny -- @@ -2544,11 +2670,11 @@ Tcl_WideInt w = objPtr->internalRep.wideValue; if (w >= (Tcl_WideInt)(LONG_MIN) && w <= (Tcl_WideInt)(ULONG_MAX)) { - *longPtr = (long) w; + *longPtr = (long)w; return TCL_OK; } goto tooLarge; } #endif @@ -2555,11 +2681,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (void *)NULL); } return TCL_ERROR; } if (objPtr->typePtr == &tclBignumType) { /* @@ -2580,16 +2706,16 @@ while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } if (big.sign) { if (value <= 1 + (unsigned long)LONG_MAX) { - *longPtr = - (long) value; + *longPtr = (long)(-value); return TCL_OK; } } else { if (value <= (unsigned long)ULONG_MAX) { - *longPtr = (long) value; + *longPtr = (long)value; return TCL_OK; } } } } @@ -2599,11 +2725,11 @@ if (interp != NULL) { const char *s = "integer value too large to represent"; Tcl_Obj *msg = Tcl_NewStringObj(s, -1); Tcl_SetObjResult(interp, msg); - Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL); + Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (void *)NULL); } return TCL_ERROR; } } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL, TCL_PARSE_INTEGER_ONLY)==TCL_OK); @@ -2796,11 +2922,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (void *)NULL); } return TCL_ERROR; } if (objPtr->typePtr == &tclBignumType) { /* @@ -2819,34 +2945,118 @@ while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } if (big.sign) { if (value <= 1 + ~(Tcl_WideUInt)WIDE_MIN) { - *wideIntPtr = - (Tcl_WideInt) value; + *wideIntPtr = (Tcl_WideInt)(-value); return TCL_OK; } } else { if (value <= (Tcl_WideUInt)WIDE_MAX) { - *wideIntPtr = (Tcl_WideInt) value; + *wideIntPtr = (Tcl_WideInt)value; return TCL_OK; } } } if (interp != NULL) { const char *s = "integer value too large to represent"; Tcl_Obj *msg = Tcl_NewStringObj(s, -1); Tcl_SetObjResult(interp, msg); - Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL); + Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (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 (objPtr->typePtr == &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 (objPtr->typePtr == &tclDoubleType) { + goto wideUIntOutOfRange; + } + if (objPtr->typePtr == &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 -- * @@ -2881,11 +3091,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (void *)NULL); } return TCL_ERROR; } if (objPtr->typePtr == &tclBignumType) { mp_int big; @@ -2912,10 +3122,35 @@ } } 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. */ +{ + return TclGetSizeIntFromObj(interp, objPtr, sizePtr); +} /* *---------------------------------------------------------------------- * * FreeBignum -- @@ -2951,11 +3186,11 @@ * * Results: * None. * * Side effects: - * The destination object receies a copy of the source object + * The destination object receives a copy of the source object * *---------------------------------------------------------------------- */ static void @@ -3023,19 +3258,18 @@ TclOOM(stringVal, size); if (MP_OKAY != mp_to_radix(&bignumVal, stringVal, size, NULL, 10)) { Tcl_Panic("conversion failure in UpdateStringOfBignum"); } - (void) Tcl_InitStringRep(objPtr, NULL, size - 1); } /* *---------------------------------------------------------------------- * * Tcl_NewBignumObj -- * - * Creates an initializes a bignum object. + * Creates and initializes a bignum object. * * Results: * Returns the newly created object. * * Side effects: @@ -3145,21 +3379,21 @@ if (mp_init_copy(bignumValue, &temp) != MP_OKAY) { return TCL_ERROR; } } else { TclUnpackBignum(objPtr, *bignumValue); - /* Optimized TclFreeIntRep */ + /* Optimized TclFreeInternalRep */ objPtr->internalRep.twoPtrValue.ptr1 = NULL; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = NULL; /* * TODO: If objPtr has a string rep, this leaves * it undisturbed. Not clear that's proper. Pure * bignum values are converted to empty string. */ if (objPtr->bytes == NULL) { - TclInitStringRep(objPtr, NULL, 0); + TclInitEmptyStringRep(objPtr); } } return TCL_OK; } if (objPtr->typePtr == &tclIntType) { @@ -3172,11 +3406,11 @@ 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); + 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); @@ -3228,11 +3462,11 @@ * Results: * Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise. * * Side effects: * A copy of bignum is stored in *bignumValue, which is expected to be - * uninitialized or cleared. If conversion fails, an the 'interp' + * uninitialized or cleared. If conversion fails and the 'interp' * argument is not NULL, an error message is stored in the interpreter * result. * * It is expected that the caller will NOT have invoked mp_init on the * bignum value before passing it in. Tcl will initialize the mp_int as @@ -3291,26 +3525,26 @@ } if (value > ((Tcl_WideUInt)WIDE_MAX + bignumValue->sign)) { goto tooLargeForWide; } if (bignumValue->sign) { - TclSetIntObj(objPtr, -(Tcl_WideInt)value); + TclSetIntObj(objPtr, (Tcl_WideInt)(-value)); } else { TclSetIntObj(objPtr, (Tcl_WideInt)value); } mp_clear(bignumValue); return; tooLargeForWide: TclInvalidateStringRep(objPtr); - TclFreeIntRep(objPtr); - TclSetBignumIntRep(objPtr, bignumValue); + TclFreeInternalRep(objPtr); + TclSetBignumInternalRep(objPtr, bignumValue); } /* *---------------------------------------------------------------------- * - * TclSetBignumIntRep -- + * TclSetBignumInternalRep -- * * Install a bignum into the internal representation of an object. * * Results: * None. @@ -3322,11 +3556,11 @@ * *---------------------------------------------------------------------- */ void -TclSetBignumIntRep( +TclSetBignumInternalRep( Tcl_Obj *objPtr, void *big) { mp_int *bignumValue = (mp_int *)big; objPtr->typePtr = &tclBignumType; @@ -3345,11 +3579,11 @@ } /* *---------------------------------------------------------------------- * - * TclGetNumberFromObj -- + * Tcl_GetNumberFromObj -- * * Extracts a number (of any possible numeric type) from an object. * * Results: * Whether the extraction worked. The type is stored in the variable @@ -3363,19 +3597,19 @@ * *---------------------------------------------------------------------- */ int -TclGetNumberFromObj( +Tcl_GetNumberFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, - ClientData *clientDataPtr, + void **clientDataPtr, int *typePtr) { do { if (objPtr->typePtr == &tclDoubleType) { - if (TclIsNaN(objPtr->internalRep.doubleValue)) { + if (isnan(objPtr->internalRep.doubleValue)) { *typePtr = TCL_NUMBER_NAN; } else { *typePtr = TCL_NUMBER_DOUBLE; } *clientDataPtr = &objPtr->internalRep.doubleValue; @@ -3398,10 +3632,46 @@ } } 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 -- @@ -3428,11 +3698,11 @@ * Tcl_DecrRefCount -- * * Decrements the reference count of the object. * * Results: - * None. + * The storage for objPtr may be freed. * *---------------------------------------------------------------------- */ #undef Tcl_DecrRefCount @@ -3442,10 +3712,32 @@ { 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 -- @@ -3461,11 +3753,11 @@ #undef Tcl_IsShared int Tcl_IsShared( Tcl_Obj *objPtr) /* The object to test for being shared. */ { - return ((objPtr)->refCount + 1 > 2); + return ((objPtr)->refCount > 1); } /* *---------------------------------------------------------------------- * @@ -3495,11 +3787,11 @@ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { - if (objPtr->refCount == 0x61616161) { + if (objPtr->refCount == FREEDREFCOUNTFILLER) { fprintf(stderr, "file = %s, line = %d\n", file, line); fflush(stderr); Tcl_Panic("incrementing refCount of previously disposed object"); } @@ -3568,11 +3860,11 @@ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { - if (objPtr->refCount == 0x61616161) { + if (objPtr->refCount == FREEDREFCOUNTFILLER) { fprintf(stderr, "file = %s, line = %d\n", file, line); fflush(stderr); Tcl_Panic("decrementing refCount of previously disposed object"); } @@ -3650,11 +3942,11 @@ TCL_UNUSED(const char *) /*file*/, TCL_UNUSED(int) /*line*/) #endif { #ifdef TCL_MEM_DEBUG - if (objPtr->refCount == 0x61616161) { + if (objPtr->refCount == FREEDREFCOUNTFILLER) { fprintf(stderr, "file = %s, line = %d\n", file, line); fflush(stderr); Tcl_Panic("checking whether previously disposed object is shared"); } @@ -3860,19 +4152,19 @@ * None. * *---------------------------------------------------------------------- */ -TCL_HASH_TYPE +size_t TclHashObjKey( TCL_UNUSED(Tcl_HashTable *), void *keyPtr) /* Key from which to compute hash value. */ { Tcl_Obj *objPtr = (Tcl_Obj *)keyPtr; - const char *string = TclGetString(objPtr); - size_t length = objPtr->length; - TCL_HASH_TYPE result = 0; + 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 @@ -3904,11 +4196,11 @@ * See also HashString in tclLiteral.c. * * See [tcl-Feature Request #2958832] */ - if (length) { + if (length > 0) { result = UCHAR(*string); while (--length) { result += (result << 3) + UCHAR(*++string); } } @@ -4007,11 +4299,11 @@ * * Results: * None. * * Side effects: - * The object's old internal rep is freed. It's string rep is not + * The object's old internal rep is freed. Its string rep is not * changed. The refcount in the Command structure is incremented to keep * it from being freed if the command is later deleted until * TclNRExecuteByteCode has a chance to recognize that it was deleted. * *---------------------------------------------------------------------- @@ -4060,11 +4352,11 @@ fillPtr->refNsId = currNsPtr->nsId; fillPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch; } if (resPtr == NULL) { - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = fillPtr; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = &tclCmdNameType; } @@ -4263,11 +4555,11 @@ *---------------------------------------------------------------------- */ int Tcl_RepresentationCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *descObj; Index: generic/tclOptimize.c ================================================================== --- generic/tclOptimize.c +++ generic/tclOptimize.c @@ -1,11 +1,11 @@ /* * tclOptimize.c -- * * This file contains the bytecode optimizer. * - * Copyright (c) 2013 by Donal Fellows. + * Copyright © 2013 Donal Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -26,11 +26,11 @@ /* * Helper macros. */ #define DefineTargetAddress(tablePtr, address) \ - ((void) Tcl_CreateHashEntry((tablePtr), (void *) (address), &isNew)) + ((void) Tcl_CreateHashEntry((tablePtr), (address), &isNew)) #define IsTargetAddress(tablePtr, address) \ (Tcl_FindHashEntry((tablePtr), (void *) (address)) != NULL) #define AddrLength(address) \ (tclInstructionTable[*(unsigned char *)(address)].numBytes) #define InstLength(instruction) \ @@ -52,11 +52,12 @@ LocateTargetAddresses( CompileEnv *envPtr, Tcl_HashTable *tablePtr) { unsigned char *currentInstPtr, *targetInstPtr; - int isNew, i; + int isNew; + Tcl_Size i; Tcl_HashEntry *hPtr; Tcl_HashSearch hSearch; Tcl_InitHashTable(tablePtr, TCL_ONE_WORD_KEYS); @@ -63,12 +64,11 @@ /* * The starts of commands represent target addresses. */ for (i=0 ; inumCommands ; i++) { - DefineTargetAddress(tablePtr, - envPtr->codeStart + envPtr->cmdMapPtr[i].codeOffset); + DefineTargetAddress(tablePtr, TclCmdStartAddress(envPtr, i)); } /* * Find places where we should be careful about replacing instructions * because they are the targets of various types of jumps. @@ -131,11 +131,11 @@ targetInstPtr = envPtr->codeStart + rangePtr->catchOffset; DefineTargetAddress(tablePtr, targetInstPtr); } else { targetInstPtr = envPtr->codeStart + rangePtr->breakOffset; DefineTargetAddress(tablePtr, targetInstPtr); - if (rangePtr->continueOffset >= 0) { + if (rangePtr->continueOffset != TCL_INDEX_NONE) { targetInstPtr = envPtr->codeStart + rangePtr->continueOffset; DefineTargetAddress(tablePtr, targetInstPtr); } } } @@ -229,13 +229,13 @@ blank = size + InstLength(nextInst); } else if (nextInst == INST_STR_CONCAT1 && TclGetUInt1AtPtr(currentInstPtr + size + 1) == 2) { Tcl_Obj *litPtr = TclFetchLiteral(envPtr, TclGetUInt1AtPtr(currentInstPtr + 1)); - size_t numBytes; + Tcl_Size numBytes; - (void) TclGetStringFromObj(litPtr, &numBytes); + (void) Tcl_GetStringFromObj(litPtr, &numBytes); if (numBytes == 0) { blank = size + InstLength(nextInst); } } break; @@ -244,13 +244,13 @@ blank = size + 1; } else if (nextInst == INST_STR_CONCAT1 && TclGetUInt1AtPtr(currentInstPtr + size + 1) == 2) { Tcl_Obj *litPtr = TclFetchLiteral(envPtr, TclGetUInt4AtPtr(currentInstPtr + 1)); - size_t numBytes; + Tcl_Size numBytes; - (void) TclGetStringFromObj(litPtr, &numBytes); + (void) Tcl_GetStringFromObj(litPtr, &numBytes); if (numBytes == 0) { blank = size + InstLength(nextInst); } } break; Index: generic/tclPanic.c ================================================================== --- generic/tclPanic.c +++ generic/tclPanic.c @@ -3,13 +3,13 @@ * * Source code for the "Tcl_Panic" library procedure for Tcl; individual * applications will probably call Tcl_SetPanicProc() to set an * application-specific panic procedure. * - * Copyright (c) 1988-1993 The Regents of the University of California. - * Copyright (c) 1994 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1988-1993 The Regents of the University of California. + * Copyright © 1994 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -39,16 +39,16 @@ * Sets the panicProc variable. * *---------------------------------------------------------------------- */ -void +const char * Tcl_SetPanicProc( TCL_NORETURN1 Tcl_PanicProc *proc) { panicProc = proc; - Tcl_InitSubsystems(); + return Tcl_InitSubsystems(); } /* *---------------------------------------------------------------------- * @@ -64,11 +64,11 @@ * *---------------------------------------------------------------------- */ /* - * The following comment is here so that Coverity's static analizer knows that + * The following comment is here so that Coverity's static analyzer knows that * a Tcl_Panic() call can never return and avoids lots of false positives. */ /* coverity[+kill] */ void Index: generic/tclParse.c ================================================================== --- generic/tclParse.c +++ generic/tclParse.c @@ -3,12 +3,12 @@ * * This file contains functions that parse Tcl scripts. They do so in a * general-purpose fashion that can be used for many different purposes, * including compilation, direct execution, code analysis, etc. * - * Copyright (c) 1997 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 Ajuba Solutions. + * Copyright © 1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Ajuba Solutions. * Contributions from Don Porter, NIST, 2002. (not subject to US copyright) * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -31,16 +31,17 @@ * TYPE_COMMAND_END - Character is newline or semicolon. * TYPE_SUBS - Character begins a substitution or has other special * meaning in ParseTokens: backslash, dollar sign, or * open bracket. * TYPE_QUOTE - Character is a double quote. + * TYPE_OPEN_PAREN - Character is a left parenthesis. * TYPE_CLOSE_PAREN - Character is a right parenthesis. * TYPE_CLOSE_BRACK - Character is a right square bracket. * TYPE_BRACE - Character is a curly brace (either left or right). */ -const char tclCharTypeTable[] = { +const unsigned char tclCharTypeTable[] = { /* * Positive character values, from 0-127: */ @@ -52,11 +53,11 @@ TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_SPACE, TYPE_NORMAL, TYPE_QUOTE, TYPE_NORMAL, TYPE_SUBS, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, - TYPE_NORMAL, TYPE_CLOSE_PAREN, TYPE_NORMAL, TYPE_NORMAL, + TYPE_OPEN_PAREN, TYPE_CLOSE_PAREN, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_COMMAND_END, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, @@ -113,25 +114,482 @@ TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, }; +/* Set of parsing error messages */ + +static const char *parseErrorMsg[] = { + "", + "extra characters after close-quote", + "extra characters after close-brace", + "missing close-brace", + "missing close-bracket", + "missing )", + "missing \"", + "missing close-brace for variable name", + "syntax error in expression", + "bad number in expression" +}; + /* * Prototypes for local functions defined in this file: */ -static int CommandComplete(const char *script, size_t numBytes); -static size_t ParseComment(const char *src, size_t numBytes, +static int CommandComplete(const char *script, Tcl_Size numBytes); +static int ParseBraces(Tcl_Interp *interp, const char *start, + Tcl_Size numBytes, Tcl_Parse *parsePtr, int flags, + const char **termPtr); +static Tcl_Size ParseComment(const char *src, Tcl_Size numBytes, Tcl_Parse *parsePtr); -static int ParseTokens(const char *src, size_t numBytes, int mask, +void ParseScript(const char *script, Tcl_Size numBytes, int flags, Tcl_Parse *parsePtr); -static size_t ParseWhiteSpace(const char *src, size_t numBytes, +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 size_t ParseAllWhiteSpace(const char *src, size_t numBytes, +static Tcl_Size ParseAllWhiteSpace(const char *src, Tcl_Size numBytes, int *incompletePtr); -static int ParseHex(const char *src, size_t numBytes, +static int ParseHex(const char *src, Tcl_Size numBytes, int *resultPtr); + +/* + * Prototypes for the Tokens object type. + */ + +static void DupTokensInternalRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); +static void FreeTokensInternalRep(Tcl_Obj *objPtr); +static int SetTokensFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); +static void UpdateStringOfTokens(Tcl_Obj *objPtr); + +/* + * The structure below defines the "tokens" Tcl object type. + */ + +static Tcl_ObjType tokensType = { + "tokens", /* name */ + FreeTokensInternalRep, /* freeIntRepProc */ + DupTokensInternalRep, /* dupIntRepProc */ + UpdateStringOfTokens, /* updateStringProc */ + SetTokensFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V0 +}; + +/* Structure to hold the data of the "tokens" internal rep */ +typedef struct TokenIntRep { + int copyCount; + int originalShimmered; + Tcl_Obj * scriptObjPtr; + Tcl_Token * tokenPtr; + Tcl_Token * lastTokenPtr; +} TokenIntRep; + +/* + *---------------------------------------------------------------------- + * + * FreeTokensInternalRep -- + * + * Frees the resources associated with a tokens object's internal + * representation. + * + * Results: + * None. + * + * Side effects: + * Frees the cached Tcl_Token array. + * + *---------------------------------------------------------------------- + */ + +static void +FreeTokensInternalRep( + Tcl_Obj *objPtr) +{ + TokenIntRep *tirPtr = (TokenIntRep *)objPtr->internalRep.otherValuePtr; + + if (tirPtr->scriptObjPtr) { + if (tirPtr->scriptObjPtr == objPtr) { + /* Must be an attempt to shimmer the original. */ + /* Cannot be an attempt to free the original, since + * we still hold a refcount on it. */ + tirPtr->originalShimmered = 1; + return; + } else { + Tcl_Obj *releaseMe; + int originalShimmered; + + /* Attempt to shimmer or free a copy */ + if (--tirPtr->copyCount) { + return; + } + /* All copies are gone; */ + originalShimmered = tirPtr->originalShimmered; + releaseMe = tirPtr->scriptObjPtr; + tirPtr->scriptObjPtr = NULL; + Tcl_DecrRefCount(releaseMe); + if (originalShimmered == 0) { + return; + } + } + } + Tcl_Free(tirPtr->tokenPtr); + Tcl_Free(tirPtr); +} + +/* + *---------------------------------------------------------------------- + * + * DupTokensInternalRep -- + * + * Called by Tcl_DuplicateObj() and by TclTokensCopy to share + * a Tcl_Token array produced by the parse of the bytes of some + * other (Tcl_Obj *). + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +DupTokensInternalRep( + Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ + Tcl_Obj *dupPtr) /* Object with internal rep to set. */ +{ + TokenIntRep *tirPtr = (TokenIntRep *)srcPtr->internalRep.otherValuePtr; + + if (tirPtr->scriptObjPtr == NULL) { + /* Record and preserve the objPtr holding the parsed script */ + /* Now that original objPtr cannot be freed while we retain + * interest in it. The reference cycle preserves it. */ + tirPtr->scriptObjPtr = srcPtr; + Tcl_IncrRefCount(srcPtr); + } + tirPtr->copyCount++; + dupPtr->internalRep.otherValuePtr = tirPtr; + dupPtr->typePtr = &tokensType; + return; +} + +/* + *---------------------------------------------------------------------- + * + * SetTokensFromAny -- + * + * Generates an internal representation, an array of Tcl_Token's, + * by parsing the string representation as a Tcl script. + * + * Results: + * Returns TCL_OK. (Parsing always succeeds, in the sense that + * a sequence of Tcl_Token's is always generated. Parse errors + * get represented by a special Tcl_Token type.) + * + * Side effects: + * Frees the old internal representation. Sets the otherValuePtr + * of the internal rep pointing to a sharable TokenIntRep. + * See comments below regarding rules for valid sharing. + * + *---------------------------------------------------------------------- + */ + +static int +SetTokensFromAny ( + Tcl_Interp *interp, /* Not used. */ + Tcl_Obj *objPtr) /* Value for which to generate Tcl_Token array by + * parsing the string value */ +{ + Tcl_Size numBytes; + const char *script = Tcl_GetStringFromObj(objPtr, &numBytes); + TokenIntRep *tirPtr = (TokenIntRep *)Tcl_Alloc(sizeof(TokenIntRep)); + + /* + * Free the old internal rep, parse the string as a Tcl script, and + * stash the Tcl_Token array into a new internal rep + * + * NOTE: the Tcl_Token array contains pointers pointing into the + * parsed string rep, which in this situation is objPtr->bytes. + * The Tcl_Token array is only usable while the string objPtr->bytes + * exists. By Tcl's object model, that string belongs to objPtr. + * We can only preserve it by preserving objPtr. + * + * When the TokenIntRep is first created and attached to the same + * objPtr whose objPtr->bytes was parsed, there is no trouble to + * solve. The Tcl_Token array cannot live longer than objPtr->bytes. + * + * Things get tricky only when the internalRep is copied. See + * DupTokensInternalRep(). + */ + + TclFreeInternalRep(objPtr); + tirPtr->tokenPtr = TclParseScript(interp, script, numBytes, 0, + &(tirPtr->lastTokenPtr), NULL); + tirPtr->scriptObjPtr = NULL; + tirPtr->copyCount = 0; + tirPtr->originalShimmered = 0; + objPtr->internalRep.otherValuePtr = tirPtr; + objPtr->typePtr = &tokensType; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * UpdateStringOfTokens -- + * + * The Tcl_Obj returned by TclTokensCopy is pure -- it has no valid + * string rep. When we have to have one, this routine generates it. + * + * Results: + * Returns TCL_OK. + * + * Side effects: + * Allocates new string rep to hold copy of the original string + * parsed to make the tokens. + * + *---------------------------------------------------------------------- + */ + +static void +UpdateStringOfTokens( + Tcl_Obj *objPtr) +{ + TokenIntRep *tirPtr = (TokenIntRep *)objPtr->internalRep.otherValuePtr; + int length; + char *bytes; + + if (tirPtr->scriptObjPtr == NULL) { + Tcl_Panic("Lost scriptObjPtr in tokens value"); + } + bytes = Tcl_GetStringFromObj(tirPtr->scriptObjPtr, &length); + TclInitStringRep(objPtr, bytes, length); +} + +/* + *---------------------------------------------------------------------- + * + * TclTokensCopy -- + * + * Make a pure copy of a list value. Cheap operation so caller can + * call TclGetTokensFromObj without fear of shimmering. + * + * Results: + * Returns pointer to new Tcl_Obj with refCount zero. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +Tcl_Obj * +TclTokensCopy( + Tcl_Obj *objPtr) +{ + Tcl_Obj *copyPtr; + + if (objPtr->typePtr != &tokensType) { + SetTokensFromAny(NULL, objPtr); + } + + TclNewObj(copyPtr); + TclInvalidateStringRep(copyPtr); + DupTokensInternalRep(objPtr, copyPtr); + return copyPtr; +} + +/* + *------------------------------------------------------------------------- + * + * TclGetTokensFromObj -- + * + * Returns a Tcl_Token sequence derived from parsing a Tcl_Obj. + * + * Results: + * Parses the string rep of the Tcl_Obj, if not already done. + * + * Side effects: + * Initializes the table of defined object types "typeTable" with + * builtin object types defined in this file. + * + *------------------------------------------------------------------------- + */ + +Tcl_Token * +TclGetTokensFromObj( + Tcl_Obj *objPtr, /* Value to parse and return tokens for */ + Tcl_Token **lastTokenPtrPtr) /* If not NULL, fill with pointer to last + * token in the token array */ +{ + TokenIntRep *tirPtr; + + if (objPtr->typePtr != &tokensType) { + SetTokensFromAny(NULL, objPtr); + } + tirPtr = (TokenIntRep *)objPtr->internalRep.otherValuePtr; + if (lastTokenPtrPtr != NULL) { + *lastTokenPtrPtr = tirPtr->lastTokenPtr; + } + return tirPtr->tokenPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TclParseScript -- + * + * Results: + * + * Side effects: + * + *---------------------------------------------------------------------- + */ + +Tcl_Token * +TclParseScript( + Tcl_Interp *interp, + const char *script, /* The string to parse */ + Tcl_Size numBytes, /* Length of string in bytes */ + int flags, /* Bit flags that control parsing details. */ + Tcl_Token **lastTokenPtrPtr,/* Return pointer to last token */ + const char **termPtr) /* Return the terminating character in string */ +{ + Tcl_Parse *parsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse)); + Tcl_Token *result; + + assert( script ); /* Caller must pass a valid pointer to string */ + + if (numBytes < 0) { + numBytes = strlen(script); + } + TclParseInit(NULL, script, numBytes, parsePtr); + ParseScript(script, numBytes, flags, parsePtr); + + if (termPtr != NULL) { + *termPtr = parsePtr->term; + } + /* + * Note no call to Tcl_FreeParse(). + * We'll transfer the tokens to the caller. + */ + if (parsePtr->tokenPtr != parsePtr->staticTokens) { + result = (Tcl_Token *)Tcl_Realloc(parsePtr->tokenPtr, + parsePtr->numTokens * sizeof(Tcl_Token)); + } else { + result = (Tcl_Token *)Tcl_Alloc(parsePtr->numTokens * sizeof(Tcl_Token)); + memcpy(result, parsePtr->tokenPtr, + (size_t) (parsePtr->numTokens * sizeof(Tcl_Token))); + } + + if (lastTokenPtrPtr != NULL) { + *lastTokenPtrPtr = &(result[parsePtr->numTokens - 1]); + } + TclStackFree(interp, parsePtr); + return result; +} + +void +ParseScript( + const char *script, /* The string to parse */ + Tcl_Size numBytes, /* Length of string in bytes */ + int flags, /* Bit flags that control parsing details. */ + Tcl_Parse *parsePtr) +{ + const char *p, *end; + int nested = (flags & PARSE_NESTED); + int scriptToken, numValidTokens; + Tcl_Token *scriptTokenPtr; + + TclGrowParseTokenArray(parsePtr, 1); + scriptToken = parsePtr->numTokens++; + scriptTokenPtr = &parsePtr->tokenPtr[scriptToken]; + scriptTokenPtr->type = TCL_TOKEN_SCRIPT; + scriptTokenPtr->start = script; + scriptTokenPtr->size = numBytes; + scriptTokenPtr->numComponents = 0; + + p = script; + end = p + numBytes; + numValidTokens = parsePtr->numTokens; + + while (p < end) { + int cmdToken; + Tcl_Token *cmdTokenPtr; + + TclGrowParseTokenArray(parsePtr, 1); + cmdToken = parsePtr->numTokens++; + + parsePtr->errorType = TCL_PARSE_SUCCESS; + parsePtr->term = parsePtr->end; + if (TCL_OK != TclParseCommand(parsePtr->interp, p, (int) (end - p), + flags | PARSE_APPEND | PARSE_USE_INTERNAL_TOKENS, parsePtr)) { + break; + } + + p = parsePtr->commandStart + parsePtr->commandSize; + + /* + * Check for missing close-brace for nested script substitution. + * If close-brace is missing, blame it on the last command parsed, + * and do not add it to the token array. + */ + + if (nested && (parsePtr->term >= end)) { + break; + } + + cmdTokenPtr = &parsePtr->tokenPtr[cmdToken]; + cmdTokenPtr->type = TCL_TOKEN_CMD; + cmdTokenPtr->start = parsePtr->commandStart; + if (parsePtr->commandStart + parsePtr->commandSize == parsePtr->term) { + cmdTokenPtr->size = parsePtr->commandSize; + } else { + cmdTokenPtr->size = parsePtr->commandSize - 1; + } + cmdTokenPtr->numComponents = parsePtr->numWords; + + scriptTokenPtr = &parsePtr->tokenPtr[scriptToken]; + scriptTokenPtr->numComponents++; /* Another command parsed */ + numValidTokens = parsePtr->numTokens; + + if (nested && (parsePtr->term < end) && (*parsePtr->term == ']')) { + scriptTokenPtr->size = parsePtr->term - scriptTokenPtr->start; + break; + } + } + /* Check all cases that indicate missing ] */ + if (nested && (p >= end) && ((parsePtr->term >= parsePtr->end) + || (*parsePtr->term != ']'))) { + parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; + parsePtr->term = script - 1; + parsePtr->incomplete = 1; + if (parsePtr->interp != NULL) { + Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( + parseErrorMsg[parsePtr->errorType], -1)); + } + } + + parsePtr->numTokens = numValidTokens; + + if ((parsePtr->errorType != TCL_PARSE_SUCCESS)) { + int errorToken; + Tcl_Token *errorTokenPtr; + + TclGrowParseTokenArray(parsePtr, 1); + errorToken = parsePtr->numTokens++; + errorTokenPtr = &parsePtr->tokenPtr[errorToken]; + errorTokenPtr->type = TCL_TOKEN_ERROR; + errorTokenPtr->start = parsePtr->commandStart; + if (parsePtr->term + 1 > parsePtr->commandStart) { + errorTokenPtr->size = parsePtr->term + 1 - parsePtr->commandStart; + } else { + errorTokenPtr->size = end - parsePtr->commandStart; + } + errorTokenPtr->numComponents = parsePtr->errorType; + } +} /* *---------------------------------------------------------------------- * * TclParseInit -- @@ -149,11 +607,11 @@ void TclParseInit( Tcl_Interp *interp, /* Interpreter to use for error reporting */ const char *start, /* Start of string to be parsed. */ - size_t numBytes, /* Total number of bytes in string. If -1, + Tcl_Size numBytes, /* Total number of bytes in string. If -1, * the script consists of all bytes up to the * first null character. */ Tcl_Parse *parsePtr) /* Points to struct to initialize */ { parsePtr->numWords = 0; @@ -191,41 +649,66 @@ *---------------------------------------------------------------------- */ int Tcl_ParseCommand( + Tcl_Interp *interp, /* See TclParseCommand */ + const char *start, /* See TclParseCommand */ + Tcl_Size numBytes, /* See TclParseCommand */ + 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) + /* See TclParseCommand */ +{ + int code = TclParseCommand(interp, start, numBytes, + (nested != 0) ? PARSE_NESTED : 0, parsePtr); + if (code == TCL_ERROR) { + Tcl_FreeParse(parsePtr); + } + return code; +} + +int +TclParseCommand( Tcl_Interp *interp, /* Interpreter to use for error reporting; if * NULL, then no error message is provided. */ const char *start, /* First character of string containing one or * more Tcl commands. */ - size_t numBytes, /* Total number of bytes in string. If -1, + Tcl_Size numBytes, /* Total number of bytes in string. If -1, * the script consists of all bytes up to the * first null character. */ - int nested, /* Non-zero means this is a nested command: - * close bracket should be considered a - * command terminator. If zero, then close - * bracket has no special meaning. */ + int flags, /* Bit flags to control details of the parsing. + * Only the PARSE_NESTED flag has an effect + * here. Other flags are passed along. */ Tcl_Parse *parsePtr) /* Structure to fill in with information about * the parsed command; any previous * information in the structure is ignored. */ { const char *src; /* Points to current character in the * command. */ char type; /* Result returned by CHAR_TYPE(*src). */ Tcl_Token *tokenPtr; /* Pointer to token being filled in. */ - int wordIndex; /* Index of word token for current word. */ + Tcl_Size wordIndex; /* Index of word token for current word. */ int terminators; /* CHAR_TYPE bits that indicate the end of a * command. */ const char *termPtr; /* Set by Tcl_ParseBraces/QuotedString to * point to char after terminating one. */ - size_t scanned; + Tcl_Size scanned; + int nested = (flags & PARSE_NESTED); + int append = (flags & PARSE_APPEND); + const char *commandStart; + int numWords = 0; - if (numBytes == TCL_INDEX_NONE && start) { + if (numBytes < 0 && start) { numBytes = strlen(start); } - TclParseInit(interp, start, numBytes, parsePtr); + if (!append) { + 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)); } @@ -258,44 +741,44 @@ /* * The following loop parses the words of the command, one word in each * iteration through the loop. */ - parsePtr->commandStart = src; + commandStart = parsePtr->commandStart = src; type = CHAR_TYPE(*src); scanned = 1; /* Can't have missing whitepsace before first word. */ while (1) { int expandWord = 0; /* Are we at command termination? */ if ((numBytes == 0) || (type & terminators) != 0) { parsePtr->term = src; + parsePtr->numWords = numWords; + parsePtr->commandStart = commandStart; + parsePtr->commandSize = src - parsePtr->commandStart; parsePtr->commandSize = src + (numBytes != 0) - parsePtr->commandStart; return TCL_OK; } /* Are we missing white space after previous word? */ if (scanned == 0) { if (src[-1] == '"') { - if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "extra characters after close-quote", -1)); - } parsePtr->errorType = TCL_PARSE_QUOTE_EXTRA; } else { - if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "extra characters after close-brace", -1)); - } parsePtr->errorType = TCL_PARSE_BRACE_EXTRA; } + if (parsePtr->interp != NULL) { + Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( + parseErrorMsg[parsePtr->errorType], -1)); + } parsePtr->term = src; error: - Tcl_FreeParse(parsePtr); + parsePtr->numWords = numWords; + parsePtr->commandStart = commandStart; parsePtr->commandSize = parsePtr->end - parsePtr->commandStart; return TCL_ERROR; } /* @@ -307,32 +790,32 @@ tokenPtr = &parsePtr->tokenPtr[wordIndex]; tokenPtr->type = TCL_TOKEN_WORD; tokenPtr->start = src; parsePtr->numTokens++; - parsePtr->numWords++; + numWords++; /* * At this point the word can have one of four forms: something * enclosed in quotes, something enclosed in braces, and expanding * word, or an unquoted word (anything else). */ parseWord: if (*src == '"') { - if (Tcl_ParseQuotedString(interp, src, numBytes, parsePtr, 1, - &termPtr) != TCL_OK) { + if (TclParseQuotedString(NULL, src, numBytes, parsePtr, + flags | PARSE_APPEND, &termPtr) != TCL_OK) { goto error; } src = termPtr; numBytes = parsePtr->end - src; } else if (*src == '{') { - int expIdx = wordIndex + 1; + Tcl_Size expIdx = wordIndex + 1; Tcl_Token *expPtr; - if (Tcl_ParseBraces(interp, src, numBytes, parsePtr, 1, - &termPtr) != TCL_OK) { + if (ParseBraces(NULL, src, numBytes, parsePtr, + flags | PARSE_APPEND, &termPtr) != TCL_OK) { goto error; } src = termPtr; numBytes = parsePtr->end - src; @@ -342,11 +825,11 @@ */ expPtr = &parsePtr->tokenPtr[expIdx]; if ((0 == expandWord) /* Haven't seen prefix already */ - && (1 == parsePtr->numTokens - expIdx) + && (expIdx + 1 == parsePtr->numTokens) /* Only one token */ && (((1 == expPtr->size) /* Same length as prefix */ && (expPtr->start[0] == '*'))) /* Is the prefix */ @@ -363,11 +846,11 @@ * This is an unquoted word. Call ParseTokens and let it do all of * the work. */ if (ParseTokens(src, numBytes, TYPE_SPACE|terminators, - TCL_SUBST_ALL, parsePtr) != TCL_OK) { + flags | TCL_SUBST_ALL, parsePtr) != TCL_OK) { goto error; } src = parsePtr->term; numBytes = parsePtr->end - src; } @@ -379,11 +862,11 @@ tokenPtr = &parsePtr->tokenPtr[wordIndex]; tokenPtr->size = src - tokenPtr->start; tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1); if (expandWord) { - size_t i; + Tcl_Size i; int isLiteral = 1; /* * When a command includes a word that is an expanded literal; for * example, {*}{1 2 3}, the parser performs that expansion @@ -404,11 +887,12 @@ break; } } if (isLiteral) { - int elemCount = 0, code = TCL_OK, literal = 1; + 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 @@ -426,11 +910,11 @@ * Step through the literal string, parsing and counting list * elements. */ while (nextElem < listEnd) { - size_t size; + Tcl_Size size; code = TclFindElement(NULL, nextElem, listEnd - nextElem, &elemStart, &nextElem, &size, &literal); if ((code != TCL_OK) || !literal) { break; @@ -459,23 +943,23 @@ * the expanding word completely disappears, leaving no * word generated this pass through the loop. Adjust * accounting appropriately. */ - parsePtr->numWords--; + numWords--; parsePtr->numTokens = wordIndex; } else { /* * Recalculate the number of Tcl_Tokens needed to store * tokens representing the expanded list. */ const char *listStart; - int growthNeeded = wordIndex + 2*elemCount + Tcl_Size growthNeeded = wordIndex + 2*elemCount - parsePtr->numTokens; - parsePtr->numWords += elemCount - 1; + numWords += elemCount - 1; if (growthNeeded > 0) { TclGrowParseTokenArray(parsePtr, growthNeeded); tokenPtr = &parsePtr->tokenPtr[wordIndex]; } parsePtr->numTokens = wordIndex + 2*elemCount; @@ -618,14 +1102,14 @@ * None. * *---------------------------------------------------------------------- */ -static size_t +static Tcl_Size ParseWhiteSpace( const char *src, /* First character to parse. */ - size_t numBytes, /* Max number of bytes to scan. */ + Tcl_Size numBytes, /* Max number of bytes to scan. */ int *incompletePtr, /* Set this boolean memory to true if parsing * indicates an incomplete command. */ char *typePtr) /* Points to location to store character type * of character that ends run of whitespace */ { @@ -672,32 +1156,32 @@ * Returns the number of bytes recognized as white space. * *---------------------------------------------------------------------- */ -static size_t +static Tcl_Size ParseAllWhiteSpace( const char *src, /* First character to parse. */ - size_t numBytes, /* Max number of byes to scan */ + Tcl_Size numBytes, /* Max number of byes to scan */ int *incompletePtr) /* Set true if parse is incomplete. */ { char type; const char *p = src; do { - size_t scanned = ParseWhiteSpace(p, numBytes, incompletePtr, &type); + Tcl_Size scanned = ParseWhiteSpace(p, numBytes, incompletePtr, &type); p += scanned; numBytes -= scanned; } while (numBytes && (*p == '\n') && (p++, --numBytes)); return (p-src); } -size_t +Tcl_Size TclParseAllWhiteSpace( const char *src, /* First character to parse. */ - size_t numBytes) /* Max number of byes to scan */ + Tcl_Size numBytes) /* Max number of byes to scan */ { int dummy; return ParseAllWhiteSpace(src, numBytes, &dummy); } @@ -724,11 +1208,11 @@ */ int ParseHex( const char *src, /* First character to parse. */ - size_t numBytes, /* Max number of byes to scan */ + Tcl_Size numBytes, /* Max number of byes to scan */ int *resultPtr) /* Points to storage provided by caller where * the character resulting from the * conversion is to be written. */ { int result = 0; @@ -778,23 +1262,23 @@ *---------------------------------------------------------------------- */ int TclParseBackslash( - const char *src, /* Points to the backslash character of a a + const char *src, /* Points to the backslash character of a * backslash sequence. */ - size_t numBytes, /* Max number of bytes to scan. */ - size_t *readPtr, /* NULL, or points to storage where the number + Tcl_Size numBytes, /* Max number of bytes to scan. */ + Tcl_Size *readPtr, /* NULL, or points to storage where the number * of bytes scanned should be written. */ char *dst) /* NULL, or points to buffer where the UTF-8 * encoding of the backslash sequence is to be * written. At most 4 bytes will be written there. */ { const char *p = src+1; - Tcl_UniChar unichar = 0; + int unichar; int result; - size_t count; + Tcl_Size count; char buf[4] = ""; if (numBytes == 0) { if (readPtr != NULL) { *readPtr = 0; @@ -867,32 +1351,19 @@ 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 { @@ -935,17 +1406,17 @@ * 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 '\' */ + count = Tcl_UtfToUniChar(p, &unichar) + 1; /* +1 for '\' */ } else { - char utfBytes[4]; + char utfBytes[8]; memcpy(utfBytes, p, numBytes - 1); utfBytes[numBytes - 1] = '\0'; - count = TclUtfToUniChar(utfBytes, &unichar) + 1; + count = Tcl_UtfToUniChar(utfBytes, &unichar) + 1; } result = unichar; break; } @@ -952,14 +1423,10 @@ 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; } /* *---------------------------------------------------------------------- @@ -977,23 +1444,23 @@ * None. * *---------------------------------------------------------------------- */ -static size_t +static Tcl_Size ParseComment( const char *src, /* First character to parse. */ - size_t numBytes, /* Max number of bytes to scan. */ + Tcl_Size numBytes, /* Max number of bytes to scan. */ Tcl_Parse *parsePtr) /* Information about parse in progress. * Updated if parsing indicates an incomplete * command. */ { const char *p = src; int incomplete = parsePtr->incomplete; while (numBytes) { - size_t scanned = ParseAllWhiteSpace(p, numBytes, &incomplete); + Tcl_Size scanned = ParseAllWhiteSpace(p, numBytes, &incomplete); p += scanned; numBytes -= scanned; if ((numBytes == 0) || (*p != '#')) { break; @@ -1053,11 +1520,11 @@ */ static int ParseTokens( const char *src, /* First character to parse. */ - size_t numBytes, /* Max number of bytes to scan. */ + Tcl_Size numBytes, /* Max number of bytes to scan. */ int 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 @@ -1067,14 +1534,15 @@ Tcl_Parse *parsePtr) /* Information about parse in progress. * Updated with additional tokens and * termination information. */ { char type; - int originalTokens; + Tcl_Size originalTokens; int noSubstCmds = !(flags & TCL_SUBST_COMMANDS); int noSubstVars = !(flags & TCL_SUBST_VARIABLES); int noSubstBS = !(flags & TCL_SUBST_BACKSLASHES); + int useInternalTokens = (flags & PARSE_USE_INTERNAL_TOKENS); Tcl_Token *tokenPtr; /* * Each iteration through the following loop adds one token of type * TCL_TOKEN_TEXT, TCL_TOKEN_BS, TCL_TOKEN_COMMAND, or TCL_TOKEN_VARIABLE @@ -1101,11 +1569,11 @@ } tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = src - tokenPtr->start; parsePtr->numTokens++; } else if (*src == '$') { - int varToken; + Tcl_Size varToken; if (noSubstVars) { tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = 1; parsePtr->numTokens++; @@ -1118,12 +1586,12 @@ * This is a variable reference. Call Tcl_ParseVarName to do all * the dirty work of parsing the name. */ varToken = parsePtr->numTokens; - if (Tcl_ParseVarName(parsePtr->interp, src, numBytes, parsePtr, - 1) != TCL_OK) { + if (TclParseVarName(NULL, src, numBytes, parsePtr, + flags | PARSE_APPEND) != TCL_OK) { return TCL_ERROR; } src += parsePtr->tokenPtr[varToken].size; numBytes -= parsePtr->tokenPtr[varToken].size; } else if (*src == '[') { @@ -1138,22 +1606,33 @@ continue; } /* * Command substitution. Call Tcl_ParseCommand recursively (and - * repeatedly) to parse the nested command(s), then throw away the - * parse information. + * repeatedly) to parse the nested command(s). If internal tokens + * are acceptable, keep all the parsing information; otherwise, + * throw away the nested parse information. */ + + if (useInternalTokens) { + if (TclParseScriptSubst(src, numBytes, parsePtr, flags) + != TCL_OK) { + return TCL_ERROR; + } + src = parsePtr->term + 1; + numBytes = parsePtr->end - src; + continue; + } src++; numBytes--; nestedPtr = (Tcl_Parse *)TclStackAlloc(parsePtr->interp, sizeof(Tcl_Parse)); while (1) { const char *curEnd; - if (Tcl_ParseCommand(parsePtr->interp, src, numBytes, 1, - nestedPtr) != TCL_OK) { + if (TCL_OK != TclParseCommand(parsePtr->interp, src, numBytes, + (flags | PARSE_NESTED) & ~PARSE_APPEND, nestedPtr)) { parsePtr->errorType = nestedPtr->errorType; parsePtr->term = nestedPtr->term; parsePtr->incomplete = nestedPtr->incomplete; TclStackFree(parsePtr->interp, nestedPtr); return TCL_ERROR; @@ -1173,15 +1652,15 @@ && (*(nestedPtr->term) == ']') && !(nestedPtr->incomplete)) { break; } if (numBytes == 0) { + parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; if (parsePtr->interp != NULL) { Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( - "missing close-bracket", -1)); + parseErrorMsg[parsePtr->errorType], -1)); } - parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; parsePtr->term = tokenPtr->start; parsePtr->incomplete = 1; TclStackFree(parsePtr->interp, nestedPtr); return TCL_ERROR; } @@ -1301,10 +1780,50 @@ } /* *---------------------------------------------------------------------- * + * TclParseScriptSubst -- + * + * Given a string starting with a [ sign, parse the script substitution + * and return information about the parse. No more than numBytes bytes + * will be scanned. + * + * Results: + * + * Side effects: + * + *---------------------------------------------------------------------- + */ + +int +TclParseScriptSubst( + const char *src, + Tcl_Size numBytes, + Tcl_Parse *parsePtr, + int flags) +{ + int scriptToken; + Tcl_Token *scriptTokenPtr; + + TclGrowParseTokenArray(parsePtr, 1); + scriptToken = parsePtr->numTokens++; + ParseScript(src+1, numBytes-1, flags | PARSE_NESTED, parsePtr); + scriptTokenPtr = &parsePtr->tokenPtr[scriptToken]; + scriptTokenPtr->type = TCL_TOKEN_SCRIPT_SUBST; + scriptTokenPtr->start = src; + scriptTokenPtr->size = parsePtr->term - src + 1; + scriptTokenPtr->numComponents = parsePtr->numTokens - scriptToken - 1; + if (parsePtr->errorType != TCL_PARSE_SUCCESS) { + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * Tcl_ParseVarName -- * * Given a string starting with a $ sign, parse off a variable name and * return information about the parse. No more than numBytes bytes will * be scanned. @@ -1327,30 +1846,49 @@ *---------------------------------------------------------------------- */ int Tcl_ParseVarName( + Tcl_Interp *interp, /* See TclParseVarName */ + const char *start, /* See TclParseVarName */ + Tcl_Size numBytes, /* See TclParseVarName */ + Tcl_Parse *parsePtr, /* See TclParseVarName */ + int append) /* Non-zero means append tokens to existing + * information in parsePtr; zero means ignore + * existing tokens in parsePtr and reinitialize + * it. */ +{ + int code = TclParseVarName(interp, start, numBytes, parsePtr, + (append != 0) ? PARSE_APPEND : 0); + if (code == TCL_ERROR) { + Tcl_FreeParse(parsePtr); + } + return code; +} + +int +TclParseVarName( Tcl_Interp *interp, /* Interpreter to use for error reporting; if * NULL, then no error message is provided. */ const char *start, /* Start of variable substitution string. * First character must be "$". */ - size_t numBytes, /* Total number of bytes in string. If -1, + Tcl_Size numBytes, /* Total number of bytes in string. If -1, * the string consists of all bytes up to the * first null character. */ Tcl_Parse *parsePtr, /* Structure to fill in with information about * the variable name. */ - int append) /* Non-zero means append tokens to existing - * information in parsePtr; zero means ignore - * existing tokens in parsePtr and - * reinitialize it. */ + int flags) /* Bit flags to control details of the parsing. + * Only the PARSE_APPEND flag has an effect + * here. Other flags are passed along. */ { Tcl_Token *tokenPtr; const char *src; int varIndex; unsigned array; + int append = (flags & PARSE_APPEND); - if (numBytes == TCL_INDEX_NONE && start) { + if (numBytes < 0 && start) { numBytes = strlen(start); } if (!append) { TclParseInit(interp, start, numBytes, parsePtr); } @@ -1395,26 +1933,39 @@ * 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; - while (numBytes && (*src != '}')) { + 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) { + parsePtr->errorType = TCL_PARSE_MISSING_VAR_BRACE; if (parsePtr->interp != NULL) { Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( - "missing close-brace for variable name", -1)); + parseErrorMsg[parsePtr->errorType], -1)); } - parsePtr->errorType = TCL_PARSE_MISSING_VAR_BRACE; parsePtr->term = tokenPtr->start-1; parsePtr->incomplete = 1; goto error; } tokenPtr->size = src - tokenPtr->start; @@ -1459,22 +2010,30 @@ * 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)) { + if (TCL_OK != ParseTokens(src+1, numBytes-1, TYPE_BAD_ARRAY_INDEX, + flags | TCL_SUBST_ALL, parsePtr)) { goto error; } - if ((parsePtr->term == src+numBytes) || (*parsePtr->term != ')')){ + if (parsePtr->term == src+numBytes){ + parsePtr->errorType = TCL_PARSE_MISSING_PAREN; if (parsePtr->interp != NULL) { - Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( - "missing )", -1)); + Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( + parseErrorMsg[parsePtr->errorType], -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; } } @@ -1495,11 +2054,15 @@ tokenPtr->size = 1; tokenPtr->numComponents = 0; return TCL_OK; error: - Tcl_FreeParse(parsePtr); + /* Convert variable substitution token to error token */ + tokenPtr = &parsePtr->tokenPtr[varIndex]; + tokenPtr->type = TCL_TOKEN_ERROR; + tokenPtr->numComponents = parsePtr->errorType; + tokenPtr->size = parsePtr->term + 1 - tokenPtr->start; return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -1533,11 +2096,13 @@ { Tcl_Obj *objPtr; int code; Tcl_Parse *parsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse)); - if (Tcl_ParseVarName(interp, start, -1, parsePtr, 0) != TCL_OK) { + if (TCL_OK != TclParseVarName(interp, start, -1, parsePtr, + PARSE_USE_INTERNAL_TOKENS)) { + Tcl_FreeParse(parsePtr); TclStackFree(interp, parsePtr); return NULL; } if (termPtr != NULL) { @@ -1551,11 +2116,11 @@ TclStackFree(interp, parsePtr); return "$"; } code = TclSubstTokens(interp, parsePtr->tokenPtr, parsePtr->numTokens, - NULL, 1, NULL, NULL); + NULL, 1, NULL, NULL, 0); Tcl_FreeParse(parsePtr); TclStackFree(interp, parsePtr); if (code != TCL_OK) { return NULL; } @@ -1604,35 +2169,55 @@ *---------------------------------------------------------------------- */ int Tcl_ParseBraces( + Tcl_Interp *interp, /* See ParseBraces */ + const char *start, /* See ParseBraces */ + Tcl_Size numBytes, /* See ParseBraces */ + Tcl_Parse *parsePtr, /* See ParseBraces */ + 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) /* See ParseBraces */ + +{ + int code = ParseBraces(interp, start, numBytes, parsePtr, + (append != 0) ? PARSE_APPEND : 0, termPtr); + if (code == TCL_ERROR) { + Tcl_FreeParse(parsePtr); + } + return code; +} + +static int +ParseBraces( Tcl_Interp *interp, /* Interpreter to use for error reporting; if * NULL, then no error message is provided. */ const char *start, /* Start of string enclosed in braces. The * first character must be {'. */ - size_t numBytes, /* Total number of bytes in string. If -1, + Tcl_Size numBytes, /* Total number of bytes in string. If -1, * the string consists of all bytes up to the * first null character. */ Tcl_Parse *parsePtr, /* Structure to fill in with information about * the string. */ - int append, /* Non-zero means append tokens to existing - * information in parsePtr; zero means ignore - * existing tokens in parsePtr and - * reinitialize it. */ + int flags, /* Bit flags to control details of the parsing. + * Only the PARSE_APPEND flag has an effect + * here. Other flags are passed along. */ 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; + Tcl_Size length, startIndex, level; + int append = (flags & PARSE_APPEND); - if (numBytes == TCL_INDEX_NONE && start) { + if (numBytes < 0 && start) { numBytes = strlen(start); } if (!append) { TclParseInit(interp, start, numBytes, parsePtr); } @@ -1740,11 +2325,11 @@ goto error; } Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( - "missing close-brace", -1)); + parseErrorMsg[parsePtr->errorType], -1)); /* * Guess if the problem is due to comments by searching the source string * for a possible open brace within the context of a comment. Since we * aren't performing a full Tcl parse, just look for an open brace @@ -1772,11 +2357,10 @@ } } } error: - Tcl_FreeParse(parsePtr); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -1806,49 +2390,71 @@ *---------------------------------------------------------------------- */ int Tcl_ParseQuotedString( + Tcl_Interp *interp, /* See TclParseQuotedString */ + const char *start, /* See TclParseQuotedString */ + Tcl_Size numBytes, /* See TclParseQuotedString */ + Tcl_Parse *parsePtr, + /* See TclParseQuotedString */ + 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) /* See TclParseQuotedString */ +{ + int code = TclParseQuotedString(interp, start, numBytes, parsePtr, + (append != 0) ? PARSE_APPEND : 0, termPtr); + if (code == TCL_ERROR) { + Tcl_FreeParse(parsePtr); + } + return code; +} + +int +TclParseQuotedString( Tcl_Interp *interp, /* Interpreter to use for error reporting; if * NULL, then no error message is provided. */ const char *start, /* Start of the quoted string. The first * character must be '"'. */ - size_t numBytes, /* Total number of bytes in string. If -1, + Tcl_Size numBytes, /* Total number of bytes in string. If -1, * the string consists of all bytes up to the * first null character. */ Tcl_Parse *parsePtr, /* Structure to fill in with information about * the string. */ - int append, /* Non-zero means append tokens to existing - * information in parsePtr; zero means ignore - * existing tokens in parsePtr and - * reinitialize it. */ + int flags, /* Bit flags to control details of the parsing. + * Only the PARSE_APPEND flag has an effect + * here. Other flags are passed along. */ 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) { + int append = (flags & PARSE_APPEND); + + if (numBytes < 0 && start) { numBytes = strlen(start); } if (!append) { TclParseInit(interp, start, numBytes, parsePtr); } if ((numBytes == 0) || (start == NULL)) { return TCL_ERROR; } - if (TCL_OK != ParseTokens(start+1, numBytes-1, TYPE_QUOTE, TCL_SUBST_ALL, - parsePtr)) { + if (TCL_OK != ParseTokens(start+1, numBytes-1, TYPE_QUOTE, + flags | TCL_SUBST_ALL, parsePtr)) { goto error; } if (*parsePtr->term != '"') { + parsePtr->errorType = TCL_PARSE_MISSING_QUOTE; if (parsePtr->interp != NULL) { Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( - "missing \"", -1)); + parseErrorMsg[parsePtr->errorType], -1)); } - parsePtr->errorType = TCL_PARSE_MISSING_QUOTE; parsePtr->term = start; parsePtr->incomplete = 1; goto error; } if (termPtr != NULL) { @@ -1855,11 +2461,10 @@ *termPtr = (parsePtr->term + 1); } return TCL_OK; error: - Tcl_FreeParse(parsePtr); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -1878,191 +2483,25 @@ * Side effects: * The Tcl_Parse struct '*parsePtr' is filled with parse results. * The caller is expected to eventually call Tcl_FreeParse() to properly * cleanup the value written there. * - * If a parse error occurs, the Tcl_InterpState value '*statePtr' is - * filled with the state created by that error. When *statePtr is written - * to, the caller is expected to make the required calls to either - * Tcl_RestoreInterpState() or Tcl_DiscardInterpState() to dispose of the - * value written there. - * *---------------------------------------------------------------------- */ 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 - * inhibit types of substitution. - */ - - if (TCL_OK != ParseTokens(p, length, /* mask */ 0, flags, parsePtr)) { - /* - * There was a parse error. Save the interpreter state for possible - * error reporting later. - */ - - *statePtr = Tcl_SaveInterpState(interp, TCL_ERROR); - - /* - * We need to re-parse to get the portion of the string we can [subst] - * before the parse error. Sadly, all the Tcl_Token's created by the - * first parse attempt are gone, freed according to the public spec - * for the Tcl_Parse* routines. The only clue we have is parse.term, - * which points to either the unmatched opener, or to characters that - * follow a close brace or close quote. - * - * Call ParseTokens again, working on the string up to parse.term. - * Keep repeating until we get a good parse on a prefix. - */ - - do { - parsePtr->numTokens = 0; - parsePtr->tokensAvailable = NUM_STATIC_TOKENS; - parsePtr->end = parsePtr->term; - parsePtr->incomplete = 0; - parsePtr->errorType = TCL_PARSE_SUCCESS; - } while (TCL_OK != - ParseTokens(p, parsePtr->end - p, 0, flags, parsePtr)); - - /* - * The good parse will have to be followed by {, (, or [. - */ - - switch (*(parsePtr->term)) { - case '{': - /* - * Parse error was a missing } in a ${varname} variable - * substitution at the toplevel. We will subst everything up to - * that broken variable substitution before reporting the parse - * error. Substituting the leftover '$' will have no side-effects, - * so the current token stream is fine. - */ - break; - - case '(': - /* - * Parse error was during the parsing of the index part of an - * array variable substitution at the toplevel. - */ - - if (*(parsePtr->term - 1) == '$') { - /* - * Special case where removing the array index left us with - * just a dollar sign (array variable with name the empty - * string as its name), instead of with a scalar variable - * reference. - * - * As in the previous case, existing token stream is OK. - */ - } else { - /* - * The current parse includes a successful parse of a scalar - * variable substitution where there should have been an array - * variable substitution. We remove that mistaken part of the - * parse before moving on. A scalar variable substitution is - * two tokens. - */ - - Tcl_Token *varTokenPtr = - parsePtr->tokenPtr + parsePtr->numTokens - 2; - - if (varTokenPtr->type != TCL_TOKEN_VARIABLE) { - Tcl_Panic("TclSubstParse: programming error"); - } - if (varTokenPtr[1].type != TCL_TOKEN_TEXT) { - Tcl_Panic("TclSubstParse: programming error"); - } - parsePtr->numTokens -= 2; - } - break; - case '[': - /* - * Parse error occurred during parsing of a toplevel command - * substitution. - */ - - parsePtr->end = p + length; - p = parsePtr->term + 1; - length = parsePtr->end - p; - if (length == 0) { - /* - * No commands, just an unmatched [. As in previous cases, - * existing token stream is OK. - */ - } else { - /* - * We want to add the parsing of as many commands as we can - * within that substitution until we reach the actual parse - * error. We'll do additional parsing to determine what length - * to claim for the final TCL_TOKEN_COMMAND token. - */ - - Tcl_Token *tokenPtr; - const char *lastTerm = parsePtr->term; - Tcl_Parse *nestedPtr = (Tcl_Parse *) - TclStackAlloc(interp, sizeof(Tcl_Parse)); - - while (TCL_OK == - Tcl_ParseCommand(NULL, p, length, 0, nestedPtr)) { - Tcl_FreeParse(nestedPtr); - p = nestedPtr->term + (nestedPtr->term < nestedPtr->end); - length = nestedPtr->end - p; - if ((length == 0) && (nestedPtr->term == nestedPtr->end)) { - /* - * If we run out of string, blame the missing close - * bracket on the last command, and do not evaluate it - * during substitution. - */ - - break; - } - lastTerm = nestedPtr->term; - } - TclStackFree(interp, nestedPtr); - - if (lastTerm == parsePtr->term) { - /* - * Parse error in first command. No commands to subst, add - * no more tokens. - */ - break; - } - - /* - * Create a command substitution token for whatever commands - * got parsed. - */ - - TclGrowParseTokenArray(parsePtr, 1); - tokenPtr = &(parsePtr->tokenPtr[parsePtr->numTokens]); - tokenPtr->start = parsePtr->term; - tokenPtr->numComponents = 0; - tokenPtr->type = TCL_TOKEN_COMMAND; - tokenPtr->size = lastTerm - tokenPtr->start + 1; - parsePtr->numTokens++; - } - break; - - default: - Tcl_Panic("bad parse in TclSubstParse: %c", p[length]); - } - } + Tcl_Size numBytes, + int flags, + Tcl_Parse *parsePtr) +{ + TclParseInit(interp, bytes, numBytes, parsePtr); + flags &= TCL_SUBST_ALL; + flags |= PARSE_USE_INTERNAL_TOKENS; + ParseTokens(bytes, numBytes, /* mask */ 0, flags, parsePtr); } /* *---------------------------------------------------------------------- * @@ -2090,18 +2529,18 @@ Tcl_Interp *interp, /* Interpreter in which to lookup variables, * execute nested commands, and report * errors. */ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to * evaluate and concatenate. */ - int count, /* Number of tokens to consider at tokenPtr. + Tcl_Size count, /* Number of tokens to consider at tokenPtr. * Must be at least 1. */ int *tokensLeftPtr, /* If not NULL, points to memory where an * integer representing the number of tokens * left to be substituted will be written */ - int line, /* The line the script starts on. */ - int *clNextOuter, /* Information about an outer context for */ - const char *outerScript) /* continuation line data. This is set by + 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 @@ -2113,16 +2552,18 @@ * 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. */ + int flags) { Tcl_Obj *result; int code = TCL_OK; #define NUM_STATIC_POS 20 - int isLiteral, maxNumCL, numCL, i, adjust; - int *clPosition = NULL; + int isLiteral; + Tcl_Size i, maxNumCL, numCL, adjust; + Tcl_Size *clPosition = NULL; Interp *iPtr = (Interp *) interp; int inFile = iPtr->evalFlags & TCL_EVAL_FILE; /* * Each pass through this loop will substitute one token, and its @@ -2133,13 +2574,13 @@ * Further optimization opportunities might be to check for the equivalent * of Tcl_SetObjResult(interp, Tcl_GetObjResult(interp)) and omit them. */ /* - * For the handling of continuation lines in literals we first check if - * this is actually a literal. For if not we can forego the additional - * processing. Otherwise we pre-allocate a small table to store the + * For the handling of continuation lines in literals, first check if + * this is actually a literal. If not then forego the additional + * processing. Otherwise preallocate a small table to store the * locations of all continuation lines we find in this literal, if any. * The table is extended if needed. */ numCL = 0; @@ -2153,11 +2594,11 @@ } } if (isLiteral) { maxNumCL = NUM_STATIC_POS; - clPosition = (int *)Tcl_Alloc(maxNumCL * sizeof(int)); + clPosition = (Tcl_Size *)Tcl_Alloc(maxNumCL * sizeof(Tcl_Size)); } adjust = 0; result = NULL; for (; count>0 && code==TCL_OK ; count--, tokenPtr++) { @@ -2193,46 +2634,52 @@ */ if ((appendByteLength == 1) && (utfCharBytes[0] == ' ') && (tokenPtr->start[1] == '\n')) { if (isLiteral) { - size_t clPos; + Tcl_Size clPos; if (result == 0) { clPos = 0; } else { - (void)TclGetStringFromObj(result, &clPos); + (void)Tcl_GetStringFromObj(result, &clPos); } if (numCL >= maxNumCL) { maxNumCL *= 2; - clPosition = (int *)Tcl_Realloc(clPosition, - maxNumCL * sizeof(int)); + clPosition = (Tcl_Size *)Tcl_Realloc(clPosition, + maxNumCL * sizeof(Tcl_Size)); } clPosition[numCL] = clPos; numCL++; } adjust++; } break; case TCL_TOKEN_COMMAND: { + /* + * This case exists only for the sake of the public routines + * Tcl_EvalTokens(Standard)(). All internal parsing avoids + * generation of the TCL_TOKEN_COMMAND token type. + */ + /* TIP #280: Transfer line information to nested command */ iPtr->numLevels++; code = TclInterpReady(interp); if (code == TCL_OK) { /* * Test cases: info-30.{6,8,9} */ - int theline; + Tcl_Size theline; TclAdvanceContinuations(&line, &clNextOuter, tokenPtr->start - outerScript); theline = line + adjust; code = TclEvalEx(interp, tokenPtr->start+1, tokenPtr->size-2, - 0, theline, clNextOuter, outerScript); + flags, theline, clNextOuter, outerScript); TclAdvanceLines(&line, tokenPtr->start+1, tokenPtr->start + tokenPtr->size - 1); /* @@ -2252,26 +2699,31 @@ case TCL_TOKEN_VARIABLE: { Tcl_Obj *arrayIndex = NULL; Tcl_Obj *varName = NULL; + if (count <= tokenPtr->numComponents) { + Tcl_Panic("token components overflow token array"); + } if (tokenPtr->numComponents > 1) { /* * Subst the index part of an array variable reference. */ code = TclSubstTokens(interp, tokenPtr+2, - tokenPtr->numComponents - 1, NULL, line, NULL, NULL); + tokenPtr->numComponents - 1, NULL, line, NULL, NULL, + flags); arrayIndex = Tcl_GetObjResult(interp); Tcl_IncrRefCount(arrayIndex); } if (code == TCL_OK) { varName = Tcl_NewStringObj(tokenPtr[1].start, tokenPtr[1].size); appendObj = Tcl_ObjGetVar2(interp, varName, arrayIndex, - TCL_LEAVE_ERR_MSG); + TCL_LEAVE_ERR_MSG | + ((flags & TCL_EVAL_GLOBAL) ? TCL_GLOBAL_ONLY : 0)); Tcl_DecrRefCount(varName); if (appendObj == NULL) { code = TCL_ERROR; } } @@ -2282,11 +2734,11 @@ case TCL_BREAK: /* Will not substitute anyway */ case TCL_CONTINUE: /* Will not substitute anyway */ break; default: /* - * All other return codes, we will subst the result from the + * All other return codes, we will subst the ulesult from the * code-throwing evaluation. */ appendObj = Tcl_GetObjResult(interp); } @@ -2296,10 +2748,49 @@ } count -= tokenPtr->numComponents; tokenPtr += tokenPtr->numComponents; break; } + + case TCL_TOKEN_SCRIPT_SUBST: { + iPtr->numLevels++; + code = TclInterpReady(interp); + if (code == TCL_OK) { + Tcl_Size theline; + if (count <= tokenPtr->numComponents) { + Tcl_Panic("token components overflow token array"); + } + TclAdvanceContinuations (&line, &clNextOuter, + tokenPtr->start - outerScript); + theline = line + adjust; + code = TclEvalScriptTokens(interp, tokenPtr+1, + tokenPtr->numComponents, flags, theline, + clNextOuter, outerScript); + + TclAdvanceLines(&line, tokenPtr->start+1, + tokenPtr->start + tokenPtr->size - 1); + + /* + * Restore flag reset by nested eval for future bracketed + * commands and their cmdframe setup + */ + if (inFile) { + iPtr->evalFlags |= TCL_EVAL_FILE; + } + count -= tokenPtr->numComponents; + tokenPtr += tokenPtr->numComponents; + } + iPtr->numLevels--; + appendObj = Tcl_GetObjResult(interp); + break; + } + + case TCL_TOKEN_ERROR: + Tcl_SetResult(interp, (char *) + parseErrorMsg[tokenPtr->numComponents], TCL_STATIC); + code = TCL_ERROR; + break; default: Tcl_Panic("unexpected token type in TclSubstTokens: %d", tokenPtr->type); } @@ -2399,32 +2890,31 @@ */ static int CommandComplete( const char *script, /* Script to check. */ - size_t numBytes) /* Number of bytes in script. */ + Tcl_Size numBytes) /* Number of bytes in script. */ { Tcl_Parse parse; const char *p, *end; - int result; + + /* + * NOTE: This set of routines should not be converted to make use of + * TclParseScript, because [info complete] is defined to operate only + * one parsing level deep, while TclParseScript digs out parsing errors + * in nested script substitutions. See test parse-6.8, etc. + */ p = script; end = p + numBytes; - while (Tcl_ParseCommand(NULL, p, end - p, 0, &parse) == TCL_OK) { - p = parse.commandStart + parse.commandSize; - if (p >= end) { - break; - } - Tcl_FreeParse(&parse); - } - if (parse.incomplete) { - result = 0; - } else { - result = 1; - } - Tcl_FreeParse(&parse); - return result; + parse.incomplete = 0; + while ((p < end) + && (Tcl_ParseCommand(NULL, p, end - p, 0, &parse)) == TCL_OK) { + p = parse.commandStart + parse.commandSize; + Tcl_FreeParse(&parse); + } + return (parse.incomplete == 0); } /* *---------------------------------------------------------------------- * @@ -2447,11 +2937,11 @@ int Tcl_CommandComplete( const char *script) /* Script to check. */ { - return CommandComplete(script, (int) strlen(script)); + return CommandComplete(script, strlen(script)); } /* *---------------------------------------------------------------------- * @@ -2473,12 +2963,12 @@ int TclObjCommandComplete( Tcl_Obj *objPtr) /* Points to object holding script to * check. */ { - size_t length; - const char *script = TclGetStringFromObj(objPtr, &length); + Tcl_Size length; + const char *script = Tcl_GetStringFromObj(objPtr, &length); return CommandComplete(script, length); } /* Index: generic/tclParse.h ================================================================== --- generic/tclParse.h +++ generic/tclParse.h @@ -9,9 +9,11 @@ #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 char tclCharTypeTable[]; +MODULE_SCOPE const unsigned char tclCharTypeTable[]; Index: generic/tclPathObj.c ================================================================== --- generic/tclPathObj.c +++ generic/tclPathObj.c @@ -3,11 +3,11 @@ * * This file contains the implementation of Tcl's "path" object type used * to represent and manipulate a general (virtual) filesystem entity in * an efficient manner. * - * Copyright (c) 2003 Vince Darley. + * Copyright © 2003 Vince Darley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -23,15 +23,18 @@ static void DupFsPathInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void FreeFsPathInternalRep(Tcl_Obj *pathPtr); static void UpdateStringOfFsPath(Tcl_Obj *pathPtr); static int SetFsPathFromAny(Tcl_Interp *interp, Tcl_Obj *pathPtr); -static size_t FindSplitPos(const char *path, int separator); +static Tcl_Size FindSplitPos(const char *path, int separator); static int IsSeparatorOrNull(int ch); static Tcl_Obj * GetExtension(Tcl_Obj *pathPtr); static int MakePathFromNormalized(Tcl_Interp *interp, Tcl_Obj *pathPtr); +static int MakeTildeRelativePath(Tcl_Interp *interp, + const char *user, const char *subPath, + Tcl_DString *dsPtr); /* * Define the 'path' object type, which Tcl uses to represent file paths * internally. */ @@ -39,11 +42,12 @@ static const Tcl_ObjType fsPathType = { "path", /* name */ FreeFsPathInternalRep, /* freeIntRepProc */ DupFsPathInternalRep, /* dupIntRepProc */ UpdateStringOfFsPath, /* updateStringProc */ - SetFsPathFromAny /* setFromAnyProc */ + SetFsPathFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; /* * struct FsPath -- * @@ -62,11 +66,11 @@ * relative to cwdPtr. */ Tcl_Obj *cwdPtr; /* If NULL, either translatedPtr exists or * normPathPtr exists and is absolute. */ int flags; /* Flags to describe interpretation - see * below. */ - ClientData nativePathPtr; /* Native representation of this path, which + void *nativePathPtr; /* Native representation of this path, which * is filesystem dependent. */ size_t filesystemEpoch; /* Used to ensure the path representation was * generated during the correct filesystem * epoch. The epoch changes when * filesystem-mounts are changed. */ @@ -83,17 +87,17 @@ /* * Define some macros to give us convenient access to path-object specific * fields. */ -#define PATHOBJ(pathPtr) ((FsPath *) (TclFetchIntRep((pathPtr), &fsPathType)->twoPtrValue.ptr1)) +#define PATHOBJ(pathPtr) ((FsPath *) (TclFetchInternalRep((pathPtr), &fsPathType)->twoPtrValue.ptr1)) #define SETPATHOBJ(pathPtr,fsPathPtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (void *) (fsPathPtr); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreIntRep((pathPtr), &fsPathType, &ir); \ + Tcl_StoreInternalRep((pathPtr), &fsPathType, &ir); \ } while (0) #define PATHFLAGS(pathPtr) (PATHOBJ(pathPtr)->flags) /* *--------------------------------------------------------------------------- @@ -138,13 +142,21 @@ 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); - if (tclPlatform == TCL_PLATFORM_WINDOWS) { + 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 */ @@ -203,18 +215,18 @@ again: if (IsSeparatorOrNull(dirSep[2])) { /* * Need to skip '.' in the path. */ - size_t curLen; + Tcl_Size curLen; if (retVal == NULL) { const char *path = TclGetString(pathPtr); retVal = Tcl_NewStringObj(path, dirSep - path); Tcl_IncrRefCount(retVal); } - (void)TclGetStringFromObj(retVal, &curLen); + (void)Tcl_GetStringFromObj(retVal, &curLen); if (curLen == 0) { Tcl_AppendToObj(retVal, dirSep, 1); } dirSep += 2; oldDirSep = dirSep; @@ -223,11 +235,11 @@ } continue; } if (dirSep[2] == '.' && IsSeparatorOrNull(dirSep[3])) { Tcl_Obj *linkObj; - size_t curLen; + Tcl_Size curLen; char *linkStr; /* * Have '..' so need to skip previous directory. */ @@ -236,22 +248,26 @@ const char *path = TclGetString(pathPtr); retVal = Tcl_NewStringObj(path, dirSep - path); Tcl_IncrRefCount(retVal); } - (void)TclGetStringFromObj(retVal, &curLen); + (void)Tcl_GetStringFromObj(retVal, &curLen); if (curLen == 0) { Tcl_AppendToObj(retVal, dirSep, 1); } if (!first || (tclPlatform == TCL_PLATFORM_UNIX)) { - linkObj = Tcl_FSLink(retVal, NULL, 0); + 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); + /* 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 @@ -267,11 +283,11 @@ * to retVal's directory. This means concatenating * the link onto the directory of the path so far. */ const char *path = - TclGetStringFromObj(retVal, &curLen); + Tcl_GetStringFromObj(retVal, &curLen); while (curLen-- > 0) { if (IsSeparatorOrNull(path[curLen])) { break; } @@ -282,11 +298,11 @@ */ Tcl_SetObjLength(retVal, curLen+1); Tcl_AppendObjToObj(retVal, linkObj); TclDecrRefCount(linkObj); - linkStr = TclGetStringFromObj(retVal, &curLen); + linkStr = Tcl_GetStringFromObj(retVal, &curLen); } else { /* * Absolute link. */ @@ -295,36 +311,38 @@ retVal = Tcl_DuplicateObj(linkObj); TclDecrRefCount(linkObj); } else { retVal = linkObj; } - linkStr = TclGetStringFromObj(retVal, &curLen); + linkStr = Tcl_GetStringFromObj(retVal, &curLen); /* * Convert to forward-slashes on windows. */ if (tclPlatform == TCL_PLATFORM_WINDOWS) { - size_t i; + Tcl_Size i; for (i = 0; i < curLen; i++) { if (linkStr[i] == '\\') { linkStr[i] = '/'; } } } } } else { - linkStr = TclGetStringFromObj(retVal, &curLen); + linkStr = Tcl_GetStringFromObj(retVal, &curLen); } /* * Either way, we now remove the last path element (but - * not the first character of the path). + * not the first character of the path). In the case of + * zipfs, make sure not to go beyond the zipfs volume. */ - while (curLen-- > 0) { + int minLen = zipVolumeLen ? zipVolumeLen - 1 : 0; + while (--curLen >= minLen) { if (IsSeparatorOrNull(linkStr[curLen])) { if (curLen) { Tcl_SetObjLength(retVal, curLen); } else { Tcl_SetObjLength(retVal, 1); @@ -379,17 +397,25 @@ } } /* * Ensure a windows drive like C:/ has a trailing separator. + * Likewise for zipfs volumes. */ - - if (tclPlatform == TCL_PLATFORM_WINDOWS) { - size_t len; - const char *path = TclGetStringFromObj(retVal, &len); - - if (len == 2 && path[0] != 0 && path[1] == ':') { + if (zipVolumeLen || (tclPlatform == TCL_PLATFORM_WINDOWS)) { + int needTrailingSlash = 0; + Tcl_Size len; + const char *path = Tcl_GetStringFromObj(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); } @@ -474,11 +500,11 @@ Tcl_PathType TclFSGetPathType( Tcl_Obj *pathPtr, const Tcl_Filesystem **filesystemPtrPtr, - int *driveNameLengthPtr) + Tcl_Size *driveNameLengthPtr) { FsPath *fsPathPtr; if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) { return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr, @@ -538,15 +564,15 @@ *--------------------------------------------------------------------------- */ Tcl_Obj * TclPathPart( - Tcl_Interp *interp, /* Used for error reporting */ + TCL_UNUSED(Tcl_Interp *), /* Used for error reporting */ Tcl_Obj *pathPtr, /* Path to take dirname of */ Tcl_PathPart portion) /* Requested portion of name */ { - if (TclHasIntRep(pathPtr, &fsPathType)) { + if (TclHasInternalRep(pathPtr, &fsPathType)) { FsPath *fsPathPtr = PATHOBJ(pathPtr); if (PATHFLAGS(pathPtr) != 0) { switch (portion) { case TCL_PATH_DIRNAME: { @@ -556,12 +582,12 @@ * 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); + Tcl_Size numBytes; + const char *rest = Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes); if (strchr(rest, '/') != NULL) { goto standardPath; } /* @@ -593,12 +619,12 @@ * 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); + Tcl_Size numBytes; + const char *rest = Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes); if (strchr(rest, '/') != NULL) { goto standardPath; } /* @@ -621,13 +647,13 @@ } case TCL_PATH_EXTENSION: return GetExtension(fsPathPtr->normPathPtr); case TCL_PATH_ROOT: { const char *fileName, *extension; - size_t length; + Tcl_Size length; - fileName = TclGetStringFromObj(fsPathPtr->normPathPtr, + fileName = Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &length); extension = TclGetExtension(fileName); if (extension == NULL) { /* * There is no extension so the root is the same as the @@ -664,22 +690,22 @@ } else { /* Absolute path */ goto standardPath; } } else { - int splitElements; + Tcl_Size splitElements; Tcl_Obj *splitPtr, *resultPtr; standardPath: resultPtr = NULL; if (portion == TCL_PATH_EXTENSION) { return GetExtension(pathPtr); } else if (portion == TCL_PATH_ROOT) { - size_t length; + Tcl_Size length; const char *fileName, *extension; - fileName = TclGetStringFromObj(pathPtr, &length); + fileName = Tcl_GetStringFromObj(pathPtr, &length); extension = TclGetExtension(fileName); if (extension == NULL) { Tcl_IncrRefCount(pathPtr); return pathPtr; } else { @@ -697,22 +723,12 @@ * 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) { + + if (portion == TCL_PATH_TAIL) { /* * Return the last component, unless it is the only component, and * it is the root of an absolute path. */ @@ -802,48 +818,47 @@ Tcl_Obj * Tcl_FSJoinPath( Tcl_Obj *listObj, /* Path elements to join, may have a zero * reference count. */ - int elements) /* Number of elements to use (-1 = all) */ + Tcl_Size elements) /* Number of elements to use (-1 = all) */ { Tcl_Obj *res; - int objc; + Tcl_Size objc; Tcl_Obj **objv; - if (Tcl_ListObjLength(NULL, listObj, &objc) != TCL_OK) { + if (TclListObjLengthM(NULL, listObj, &objc) != TCL_OK) { return NULL; } elements = ((elements >= 0) && (elements <= objc)) ? elements : objc; - Tcl_ListObjGetElements(NULL, listObj, &objc, &objv); + TclListObjGetElementsM(NULL, listObj, &objc, &objv); res = TclJoinPath(elements, objv, 0); return res; } Tcl_Obj * TclJoinPath( - int elements, /* Number of elements to use (-1 = all) */ + Tcl_Size elements, /* Number of elements to use */ Tcl_Obj * const objv[], /* Path elements to join */ int forceRelative) /* If non-zero, assume all more paths are - * relative (e. g. simple normalization) */ + * relative (e.g. simple normalization) */ { Tcl_Obj *res = NULL; - int i; + Tcl_Size i; const Tcl_Filesystem *fsPtr = NULL; - assert ( elements >= 0 ); - if (elements == 0) { - return Tcl_NewObj(); + TclNewObj(res); + return res; } assert ( elements > 0 ); if (elements == 2) { Tcl_Obj *elt = objv[0]; - Tcl_ObjIntRep *eltIr = TclFetchIntRep(elt, &fsPathType); + Tcl_ObjInternalRep *eltIr = TclFetchInternalRep(elt, &fsPathType); /* * This is a special case where we can be much more efficient, where * we are joining a single relative path onto an object that is * already of path type. The 'TclNewFSPathObj' call below creates an @@ -864,13 +879,13 @@ /* if forceRelative - second path is relative */ type = forceRelative ? TCL_PATH_RELATIVE : TclGetPathType(tailObj, NULL, NULL, NULL); if (type == TCL_PATH_RELATIVE) { const char *str; - size_t len; + Tcl_Size len; - str = TclGetStringFromObj(tailObj, &len); + str = Tcl_GetStringFromObj(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! @@ -878,11 +893,11 @@ return elt; } /* - * If it doesn't begin with '.' and is a unix path or it a + * If it doesn't begin with '.' and is a Unix path or it a * windows path without backslashes, then we can be very * efficient here. (In fact even a windows path with * backslashes can be joined efficiently, but the path object * would not have forward slashes only, and this would * therefore contradict our 'file join' documentation). @@ -931,18 +946,18 @@ } assert ( res == NULL ); for (i = 0; i < elements; i++) { - int driveNameLength; - size_t strEltLen, length; + Tcl_Size driveNameLength; + Tcl_Size strEltLen, length; Tcl_PathType type; char *strElt, *ptr; Tcl_Obj *driveName = NULL; Tcl_Obj *elt = objv[i]; - strElt = TclGetStringFromObj(elt, &strEltLen); + strElt = Tcl_GetStringFromObj(elt, &strEltLen); driveNameLength = 0; /* if forceRelative - all paths excepting first one are relative */ type = (forceRelative && (i > 0)) ? TCL_PATH_RELATIVE : TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName); if (type != TCL_PATH_RELATIVE) { @@ -1035,24 +1050,14 @@ 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 + ptr = Tcl_GetStringFromObj(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') { @@ -1080,11 +1085,11 @@ } } if (length > 0 && ptr[length -1] != '/') { Tcl_AppendToObj(res, &separator, 1); - (void)TclGetStringFromObj(res, &length); + (void)Tcl_GetStringFromObj(res, &length); } Tcl_SetObjLength(res, length + strlen(strElt)); ptr = TclGetString(res) + length; for (; *strElt != '\0'; strElt++) { @@ -1146,17 +1151,17 @@ * object is already of FsPath type, and is a relative path, we do have to * worry about the cwd. If the cwd has changed, we must recompute the * path. */ - if (TclHasIntRep(pathPtr, &fsPathType)) { + if (TclHasInternalRep(pathPtr, &fsPathType)) { if (TclFSEpochOk(PATHOBJ(pathPtr)->filesystemEpoch)) { return TCL_OK; } TclGetString(pathPtr); - Tcl_StoreIntRep(pathPtr, &fsPathType, NULL); + Tcl_StoreInternalRep(pathPtr, &fsPathType, NULL); } return SetFsPathFromAny(interp, pathPtr); } @@ -1184,11 +1189,11 @@ * Helper function for SetFsPathFromAny. Returns position of first directory * delimiter in the path. If no separator is found, then returns the position * of the end of the string. */ -static size_t +static Tcl_Size FindSplitPos( const char *path, int separator) { int count = 0; @@ -1238,18 +1243,21 @@ Tcl_Obj * TclNewFSPathObj( Tcl_Obj *dirPtr, const char *addStrRep, - size_t len) + Tcl_Size len) { FsPath *fsPathPtr; Tcl_Obj *pathPtr; const char *p; int state = 0, count = 0; - /* [Bug 2806250] - this is only a partial solution of the problem. + /* + * 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. * @@ -1261,17 +1269,10 @@ * 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)); /* @@ -1295,11 +1296,11 @@ * Look for path components made up of only "." * This is overly conservative analysis to keep simple. It may mark some * things as needing more aggressive normalization that don't actually * need it. No harm done. */ - for (p = addStrRep; len+1 > 1; p++, len--) { + for (p = addStrRep; len > 0; p++, len--) { switch (state) { case 0: /* So far only "." since last dirsep or start */ switch (*p) { case '.': count = 1; @@ -1339,21 +1340,21 @@ Tcl_Obj *head, Tcl_Obj *tail) { const char *bytes; Tcl_Obj *copy = Tcl_DuplicateObj(head); - size_t length; + Tcl_Size length; /* * This is likely buggy when dealing with virtual filesystem drivers * that use some character other than "/" as a path separator. I know * of no evidence that such a foolish thing exists. This solution was * chosen so that "JoinPath" operations that pass through either path - * intrep produce the same results; that is, bugward compatibility. If + * internalrep produce the same results; that is, bugward compatibility. If * we need to fix that bug here, it needs fixing in TclJoinPath() too. */ - bytes = TclGetStringFromObj(tail, &length); + bytes = Tcl_GetStringFromObj(tail, &length); if (length == 0) { Tcl_AppendToObj(copy, "/", 1); } else { TclpNativeJoinPath(copy, bytes); } @@ -1386,13 +1387,13 @@ TclFSMakePathRelative( TCL_UNUSED(Tcl_Interp *), Tcl_Obj *pathPtr, /* The path we have. */ Tcl_Obj *cwdPtr) /* Make it relative to this. */ { - size_t cwdLen, len; + Tcl_Size cwdLen, len; const char *tempStr; - Tcl_ObjIntRep *irPtr = TclFetchIntRep(pathPtr, &fsPathType); + Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(pathPtr, &fsPathType); if (irPtr) { FsPath *fsPathPtr = PATHOBJ(pathPtr); if (PATHFLAGS(pathPtr) != 0 && fsPathPtr->cwdPtr == cwdPtr) { @@ -1409,11 +1410,11 @@ * * Note that if we get this wrong, we will strip off either too much or * too little below, leading to wrong answers returned by glob. */ - tempStr = TclGetStringFromObj(cwdPtr, &cwdLen); + tempStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen); /* * Should we perhaps use 'Tcl_FSPathSeparator'? But then what about the * Windows special case? Perhaps we should just check if cwd is a root * volume. @@ -1429,11 +1430,11 @@ if (tempStr[cwdLen-1] != '/' && tempStr[cwdLen-1] != '\\') { cwdLen++; } break; } - tempStr = TclGetStringFromObj(pathPtr, &len); + tempStr = Tcl_GetStringFromObj(pathPtr, &len); return Tcl_NewStringObj(tempStr + cwdLen, len - cwdLen); } /* @@ -1458,11 +1459,11 @@ TCL_UNUSED(Tcl_Interp *), Tcl_Obj *pathPtr) /* The object to convert. */ { FsPath *fsPathPtr; - if (TclHasIntRep(pathPtr, &fsPathType)) { + if (TclHasInternalRep(pathPtr, &fsPathType)) { return TCL_OK; } fsPathPtr = (FsPath *)Tcl_Alloc(sizeof(FsPath)); @@ -1511,11 +1512,11 @@ */ Tcl_Obj * Tcl_FSNewNativePath( const Tcl_Filesystem *fromFilesystem, - ClientData clientData) + void *clientData) { Tcl_Obj *pathPtr = NULL; FsPath *fsPathPtr; @@ -1529,11 +1530,11 @@ /* * Free old representation; shouldn't normally be any, but best to be * safe. */ - Tcl_StoreIntRep(pathPtr, &fsPathType, NULL); + Tcl_StoreInternalRep(pathPtr, &fsPathType, NULL); fsPathPtr = (FsPath *)Tcl_Alloc(sizeof(FsPath)); fsPathPtr->translatedPathPtr = NULL; Tcl_IncrRefCount(fsPathPtr->normPathPtr = Tcl_DuplicateObj(pathPtr)); @@ -1595,20 +1596,20 @@ * translated result we need, and can store it for future use. */ Tcl_Obj *translatedCwdPtr = Tcl_FSGetTranslatedPath(interp, srcFsPathPtr->cwdPtr); - Tcl_ObjIntRep *translatedCwdIrPtr; + Tcl_ObjInternalRep *translatedCwdIrPtr; if (translatedCwdPtr == NULL) { return NULL; } retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1, &srcFsPathPtr->normPathPtr); Tcl_IncrRefCount(srcFsPathPtr->translatedPathPtr = retObj); - translatedCwdIrPtr = TclFetchIntRep(translatedCwdPtr, &fsPathType); + translatedCwdIrPtr = TclFetchInternalRep(translatedCwdPtr, &fsPathType); if (translatedCwdIrPtr) { srcFsPathPtr->filesystemEpoch = PATHOBJ(translatedCwdPtr)->filesystemEpoch; } else { srcFsPathPtr->filesystemEpoch = 0; @@ -1654,12 +1655,12 @@ Tcl_Obj *pathPtr) { Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(interp, pathPtr); if (transPtr != NULL) { - size_t len; - const char *orig = TclGetStringFromObj(transPtr, &len); + Tcl_Size len; + const char *orig = Tcl_GetStringFromObj(transPtr, &len); char *result = (char *)Tcl_Alloc(len+1); memcpy(result, orig, len+1); TclDecrRefCount(transPtr); return result; @@ -1704,11 +1705,11 @@ * This is a special path object which is the result of something like * 'file join' */ Tcl_Obj *dir, *copy; - size_t tailLen, cwdLen; + Tcl_Size tailLen, cwdLen; int pathType; pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr); dir = Tcl_FSGetNormalizedPath(interp, fsPathPtr->cwdPtr); if (dir == NULL) { @@ -1715,11 +1716,11 @@ return NULL; } /* TODO: Figure out why this is needed. */ TclGetString(pathPtr); - (void)TclGetStringFromObj(fsPathPtr->normPathPtr, &tailLen); + (void)Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &tailLen); if (tailLen) { copy = AppendPath(dir, fsPathPtr->normPathPtr); } else { copy = Tcl_DuplicateObj(dir); } @@ -1728,11 +1729,11 @@ /* * We now own a reference on both 'dir' and 'copy' */ - (void) TclGetStringFromObj(dir, &cwdLen); + (void) Tcl_GetStringFromObj(dir, &cwdLen); /* Normalize the combined string. */ if (PATHFLAGS(pathPtr) & TCLPATH_NEEDNORM) { /* @@ -1800,22 +1801,22 @@ */ if (fsPathPtr->cwdPtr != NULL) { if (!TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) { TclGetString(pathPtr); - Tcl_StoreIntRep(pathPtr, &fsPathType, NULL); + Tcl_StoreInternalRep(pathPtr, &fsPathType, NULL); if (SetFsPathFromAny(interp, pathPtr) != TCL_OK) { return NULL; } fsPathPtr = PATHOBJ(pathPtr); } else if (fsPathPtr->normPathPtr == NULL) { - size_t cwdLen; + Tcl_Size cwdLen; Tcl_Obj *copy; copy = AppendPath(fsPathPtr->cwdPtr, pathPtr); - (void) TclGetStringFromObj(fsPathPtr->cwdPtr, &cwdLen); + (void) Tcl_GetStringFromObj(fsPathPtr->cwdPtr, &cwdLen); cwdLen += (TclGetString(copy)[cwdLen] == '/'); /* * Normalize the combined string, but only starting after the end * of the previously normalized 'dir'. This should be much faster! @@ -1949,11 +1950,11 @@ * handle, which is then stored in the internal representation of pathPtr. * *--------------------------------------------------------------------------- */ -ClientData +void * Tcl_FSGetInternalRep( Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr) { FsPath *srcFsPathPtr; @@ -2046,11 +2047,11 @@ Tcl_Obj *pathPtr, const Tcl_Filesystem **fsPtrPtr) { FsPath *srcFsPathPtr; - if (!TclHasIntRep(pathPtr, &fsPathType)) { + if (!TclHasInternalRep(pathPtr, &fsPathType)) { return TCL_OK; } srcFsPathPtr = PATHOBJ(pathPtr); @@ -2060,11 +2061,11 @@ * representation for this object was calculated. Discard the stale * representation and recalculate it. */ TclGetString(pathPtr); - Tcl_StoreIntRep(pathPtr, &fsPathType, NULL); + Tcl_StoreInternalRep(pathPtr, &fsPathType, NULL); if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) { return TCL_ERROR; } srcFsPathPtr = PATHOBJ(pathPtr); } @@ -2096,19 +2097,19 @@ void TclFSSetPathDetails( Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr, - ClientData clientData) + void *clientData) { FsPath *srcFsPathPtr; /* * Make sure pathPtr is of the correct type. */ - if (!TclHasIntRep(pathPtr, &fsPathType)) { + if (!TclHasInternalRep(pathPtr, &fsPathType)) { if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) { return; } } @@ -2139,22 +2140,22 @@ Tcl_FSEqualPaths( Tcl_Obj *firstPtr, Tcl_Obj *secondPtr) { const char *firstStr, *secondStr; - size_t firstLen, secondLen; + Tcl_Size firstLen, secondLen; int tempErrno; if (firstPtr == secondPtr) { return 1; } if (firstPtr == NULL || secondPtr == NULL) { return 0; } - firstStr = TclGetStringFromObj(firstPtr, &firstLen); - secondStr = TclGetStringFromObj(secondPtr, &secondLen); + firstStr = Tcl_GetStringFromObj(firstPtr, &firstLen); + secondStr = Tcl_GetStringFromObj(secondPtr, &secondLen); if ((firstLen == secondLen) && !memcmp(firstStr, secondStr, firstLen)) { return 1; } /* @@ -2169,12 +2170,12 @@ if (firstPtr == NULL || secondPtr == NULL) { return 0; } - firstStr = TclGetStringFromObj(firstPtr, &firstLen); - secondStr = TclGetStringFromObj(secondPtr, &secondLen); + firstStr = Tcl_GetStringFromObj(firstPtr, &firstLen); + secondStr = Tcl_GetStringFromObj(secondPtr, &secondLen); return ((firstLen == secondLen) && !memcmp(firstStr, secondStr, firstLen)); } /* *--------------------------------------------------------------------------- @@ -2182,14 +2183,10 @@ * 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 "~" indicates a particular - * user's directory. - * * Results: * Standard Tcl error code. * * Side effects: * The old representation may be freed, and new memory allocated. @@ -2197,19 +2194,18 @@ *--------------------------------------------------------------------------- */ static int SetFsPathFromAny( - Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + TCL_UNUSED(Tcl_Interp *), /* Used for error reporting if not NULL. */ Tcl_Obj *pathPtr) /* The object to convert. */ { - size_t len; + Tcl_Size len; FsPath *fsPathPtr; Tcl_Obj *transPtr; - const char *name; - if (TclHasIntRep(pathPtr, &fsPathType)) { + if (TclHasInternalRep(pathPtr, &fsPathType)) { return TCL_OK; } /* * First step is to translate the filename. This is similar to @@ -2223,140 +2219,27 @@ * 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); - } + Tcl_GetStringFromObj(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) { - transPtr = Tcl_DuplicateObj(pathPtr); - fsPathPtr->filesystemEpoch = 0; + (void) Tcl_GetString(pathPtr); + TclFreeInternalRep(pathPtr); + transPtr = Tcl_DuplicateObj(pathPtr); + fsPathPtr->filesystemEpoch = 0; } else { - fsPathPtr->filesystemEpoch = TclFSEpoch(); + fsPathPtr->filesystemEpoch = TclFSEpoch(); } Tcl_IncrRefCount(transPtr); fsPathPtr->translatedPathPtr = transPtr; fsPathPtr->normPathPtr = NULL; fsPathPtr->cwdPtr = NULL; @@ -2466,27 +2349,32 @@ static void UpdateStringOfFsPath( Tcl_Obj *pathPtr) /* path obj with string rep to update. */ { FsPath *fsPathPtr = PATHOBJ(pathPtr); - size_t cwdLen; + Tcl_Size cwdLen; Tcl_Obj *copy; if (PATHFLAGS(pathPtr) == 0 || fsPathPtr->cwdPtr == NULL) { - Tcl_Panic("Called UpdateStringOfFsPath with invalid object"); + if (fsPathPtr->translatedPathPtr == NULL) { + Tcl_Panic("Called UpdateStringOfFsPath with invalid object"); + } else { + copy = Tcl_DuplicateObj(fsPathPtr->translatedPathPtr); + } + } else { + copy = AppendPath(fsPathPtr->cwdPtr, fsPathPtr->normPathPtr); } - 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->bytes = Tcl_GetStringFromObj(copy, &cwdLen); pathPtr->length = cwdLen; - TclInitStringRep(copy, NULL, 0); + TclInitEmptyStringRep(copy); TclDecrRefCount(copy); } /* *--------------------------------------------------------------------------- @@ -2510,20 +2398,20 @@ */ int TclNativePathInFilesystem( Tcl_Obj *pathPtr, - TCL_UNUSED(ClientData *)) + TCL_UNUSED(void **)) { /* * A special case is required to handle the empty path "". This is a valid * path (i.e. the user should be able to do 'file exists ""' without * throwing an error), but equally the path doesn't exist. Those are the * semantics of Tcl (at present anyway), so we have to abide by them here. */ - if (TclHasIntRep(pathPtr, &fsPathType)) { + if (TclHasInternalRep(pathPtr, &fsPathType)) { if (pathPtr->bytes != NULL && pathPtr->bytes[0] == '\0') { /* * We reject the empty path "". */ @@ -2538,13 +2426,13 @@ * It is somewhat unusual to reach this code path without the object * being of fsPathType. However, we do our best to deal with the * situation. */ - size_t len; + Tcl_Size len; - (void) TclGetStringFromObj(pathPtr, &len); + (void) Tcl_GetStringFromObj(pathPtr, &len); if (len == 0) { /* * We reject the empty path "". */ @@ -2556,13 +2444,260 @@ * 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 = Tcl_GetStringFromObj(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: */ Index: generic/tclPipe.c ================================================================== --- generic/tclPipe.c +++ generic/tclPipe.c @@ -2,11 +2,11 @@ * tclPipe.c -- * * This file contains the generic portion of the command channel driver * as well as various utility routines used in managing subprocesses. * - * Copyright (c) 1997 by Sun Microsystems, Inc. + * Copyright © 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -109,11 +109,11 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" wasn't opened for %s", Tcl_GetChannelName(chan), ((writing) ? "writing" : "reading"))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", - "BADCHAN", NULL); + "BADCHAN", (void *)NULL); } return NULL; } *releasePtr = 1; if (writing) { @@ -153,11 +153,11 @@ return file; badLastArg: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't specify \"%s\" as last word in command", arg)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "SYNTAX", NULL); + Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "SYNTAX", (void *)NULL); return NULL; } /* *---------------------------------------------------------------------- @@ -177,16 +177,16 @@ *---------------------------------------------------------------------- */ void Tcl_DetachPids( - int numPids, /* Number of pids to detach: gives size of + Tcl_Size numPids, /* Number of pids to detach: gives size of * array pointed to by pidPtr. */ Tcl_Pid *pidPtr) /* Array of pids to detach. */ { Detached *detPtr; - int i; + Tcl_Size i; Tcl_MutexLock(&pipeMutex); for (i = 0; i < numPids; i++) { detPtr = (Detached *)Tcl_Alloc(sizeof(Detached)); detPtr->pid = pidPtr[i]; @@ -267,20 +267,20 @@ */ int TclCleanupChildren( Tcl_Interp *interp, /* Used for error messages. */ - int numPids, /* Number of entries in pidPtr array. */ + Tcl_Size numPids, /* Number of entries in pidPtr array. */ Tcl_Pid *pidPtr, /* Array of process ids of children. */ Tcl_Channel errorChan) /* Channel for file containing stderr output * from pipeline. NULL means there isn't any * stderr output. */ { int result = TCL_OK; - int i, abnormalExit, anyErrorInfo; + int code, abnormalExit, anyErrorInfo; TclProcessWaitStatus waitStatus; - int code; + Tcl_Size i; Tcl_Obj *msg, *error; abnormalExit = 0; for (i = 0; i < numPids; i++) { waitStatus = TclProcessWait(pidPtr[i], 0, &code, &msg, &error); @@ -333,11 +333,11 @@ int count; Tcl_Obj *objPtr; Tcl_Seek(errorChan, 0, SEEK_SET); TclNewObj(objPtr); - count = Tcl_ReadChars(errorChan, objPtr, -1, 0); + count = Tcl_ReadChars(errorChan, objPtr, TCL_INDEX_NONE, 0); if (count == -1) { result = TCL_ERROR; Tcl_DecrRefCount(objPtr); Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -376,11 +376,11 @@ * * This function is unofficially exported for use by BLT. * * Results: * The return value is a count of the number of new processes created, or - * -1 if an error occurred while creating the pipeline. *pidArrayPtr is + * TCL_INDEX_NONE if an error occurred while creating the pipeline. *pidArrayPtr is * filled in with the address of a dynamically allocated array giving the * ids of all of the processes. It is up to the caller to free this array * when it isn't needed anymore. If inPipePtr is non-NULL, *inPipePtr is * filled in with the file id for the input pipe for the pipeline (if * any): the caller must eventually close this file. If outPipePtr isn't @@ -393,14 +393,14 @@ * Processes and pipes are created. * *---------------------------------------------------------------------- */ -int +Tcl_Size TclCreatePipeline( Tcl_Interp *interp, /* Interpreter to use for error reporting. */ - int argc, /* Number of entries in argv. */ + Tcl_Size argc, /* Number of entries in argv. */ const char **argv, /* Array of strings describing commands in * pipeline plus I/O redirection with <, <<, * >, etc. Argv[argc] must be NULL. */ Tcl_Pid **pidArrayPtr, /* Word at *pidArrayPtr gets filled in with * address of array of pids for processes in @@ -413,11 +413,11 @@ * at *inPipePtr. NULL means command specified * its own input source. */ TclFile *outPipePtr, /* If non-NULL, output to the pipeline goes to * a pipe, unless overridden by redirection in * the command. The file id with which to read - * frome this pipe is stored at *outPipePtr. + * from this pipe is stored at *outPipePtr. * NULL means command specified its own output * sink. */ TclFile *errFilePtr) /* If non-NULL, all stderr output from the * pipeline will go to a temporary file * created here, and a descriptor to read the @@ -429,13 +429,13 @@ * redirection then the file will still be * created but it will never get any data. */ { Tcl_Pid *pidPtr = NULL; /* Points to malloc-ed array holding all the * pids of child processes. */ - int numPids; /* Actual number of processes that exist at + Tcl_Size numPids; /* Actual number of processes that exist at * *pidPtr right now. */ - int cmdCount; /* Count of number of distinct commands found + Tcl_Size cmdCount; /* Count of number of distinct commands found * in argc/argv. */ const char *inputLiteral = NULL; /* If non-null, then this points to a string * containing input data (specified via <<) to * be piped to the first process in the @@ -458,11 +458,12 @@ int errorClose = 0; /* If non-zero, then errorFile should be * closed when cleaning up. */ int errorRelease = 0; const char *p; const char *nextArg; - int skip, lastBar, lastArg, i, j, atOK, flags, needCmd, errorToOutput = 0; + int skip, atOK, flags, needCmd, errorToOutput = 0; + Tcl_Size i, j, lastArg, lastBar; Tcl_DString execBuffer; TclFile pipeIn; TclFile curInFile, curOutFile, curErrFile; Tcl_Channel channel; @@ -487,11 +488,11 @@ * First, scan through all the arguments to figure out the structure of * the pipeline. Process all of the input and output redirection arguments * and remove them from the argument list in the pipeline. Count the * number of distinct processes (it's the number of "|" arguments plus * one) but don't remove the "|" arguments because they'll be used in the - * second pass to seperate the individual child processes. Cannot start + * second pass to separate the individual child processes. Cannot start * the child processes in this pass because the redirection symbols may * appear anywhere in the command line - e.g., the '<' that specifies the * input to the entire pipe may appear at the very end of the argument * list. */ @@ -511,11 +512,11 @@ if (*p == '\0') { if ((i == (lastBar + 1)) || (i == (argc - 1))) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal use of | or |& in command", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", - "PIPESYNTAX", NULL); + "PIPESYNTAX", (void *)NULL); goto error; } } lastBar = i; cmdCount++; @@ -540,11 +541,11 @@ if (inputLiteral == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't specify \"%s\" as last word in command", argv[i])); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", - "PIPESYNTAX", NULL); + "PIPESYNTAX", (void *)NULL); goto error; } skip = 2; } } else { @@ -657,11 +658,11 @@ if (i != argc-1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "must specify \"%s\" as last word in command", argv[i])); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", - "PIPESYNTAX", NULL); + "PIPESYNTAX", (void *)NULL); goto error; } errorFile = outputFile; errorToOutput = 2; skip = 1; @@ -699,11 +700,11 @@ */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal use of | or |& in command", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "PIPESYNTAX", - NULL); + (void *)NULL); goto error; } if (inputFile == NULL) { if (inputLiteral != NULL) { @@ -1018,19 +1019,19 @@ Tcl_Channel Tcl_OpenCommandChannel( Tcl_Interp *interp, /* Interpreter for error reporting. Can NOT be * NULL. */ - int argc, /* How many arguments. */ + Tcl_Size argc, /* How many arguments. */ const char **argv, /* Array of arguments for command pipe. */ int flags) /* Or'ed combination of TCL_STDIN, TCL_STDOUT, * TCL_STDERR, and TCL_ENFORCE_MODE. */ { TclFile *inPipePtr, *outPipePtr, *errFilePtr; TclFile inPipe, outPipe, errFile; - int numPids; - Tcl_Pid *pidPtr; + Tcl_Size numPids; + Tcl_Pid *pidPtr = NULL; Tcl_Channel channel; inPipe = outPipe = errFile = NULL; inPipePtr = (flags & TCL_STDIN) ? &inPipe : NULL; @@ -1053,19 +1054,19 @@ if ((flags & TCL_STDOUT) && (outPipe == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't read output from command:" " standard output was redirected", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", - "BADREDIRECT", NULL); + "BADREDIRECT", (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", NULL); + "BADREDIRECT", (void *)NULL); goto error; } } channel = TclpCreateCommandChannel(outPipe, inPipe, errFile, @@ -1072,17 +1073,17 @@ numPids, pidPtr); if (channel == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "pipe for command could not be created", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "NOPIPE", NULL); + Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "NOPIPE", (void *)NULL); goto error; } return channel; error: - if (numPids > 0) { + if (pidPtr) { Tcl_DetachPids(numPids, pidPtr); Tcl_Free(pidPtr); } if (inPipe != NULL) { TclpCloseFile(inPipe); Index: generic/tclPkg.c ================================================================== --- generic/tclPkg.c +++ generic/tclPkg.c @@ -2,12 +2,12 @@ * 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 + * Copyright © 1996 Sun Microsystems, Inc. + * Copyright © 2006 Andreas Kupries * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * TIP #268. @@ -38,11 +38,11 @@ } PkgAvail; typedef struct PkgName { struct PkgName *nextPtr; /* Next in list of package names being * initialized. */ - char name[1]; + char name[TCLFLEXARRAY]; } PkgName; typedef struct PkgFiles { PkgName *names; /* Package names being initialized. Must be * first field. */ @@ -94,19 +94,19 @@ static void AddRequirementsToResult(Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]); static void AddRequirementsToDString(Tcl_DString *dstring, int reqc, Tcl_Obj *const reqv[]); static Package * FindPackage(Tcl_Interp *interp, const char *name); -static int PkgRequireCore(ClientData data[], Tcl_Interp *interp, int result); -static int PkgRequireCoreFinal(ClientData data[], Tcl_Interp *interp, int result); -static int PkgRequireCoreCleanup(ClientData data[], Tcl_Interp *interp, int result); -static int PkgRequireCoreStep1(ClientData data[], Tcl_Interp *interp, int result); -static int PkgRequireCoreStep2(ClientData data[], Tcl_Interp *interp, int result); -static int TclNRPkgRequireProc(ClientData clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]); -static int SelectPackage(ClientData data[], Tcl_Interp *interp, int result); -static int SelectPackageFinal(ClientData data[], Tcl_Interp *interp, int result); -static int TclNRPackageObjCmdCleanup(ClientData data[], Tcl_Interp *interp, int result); +static int PkgRequireCore(void *data[], Tcl_Interp *interp, int result); +static int PkgRequireCoreFinal(void *data[], Tcl_Interp *interp, int result); +static int PkgRequireCoreCleanup(void *data[], Tcl_Interp *interp, int result); +static int PkgRequireCoreStep1(void *data[], Tcl_Interp *interp, int result); +static int PkgRequireCoreStep2(void *data[], Tcl_Interp *interp, int result); +static int TclNRPkgRequireProc(void *clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]); +static int SelectPackage(void *data[], Tcl_Interp *interp, int result); +static int SelectPackageFinal(void *data[], Tcl_Interp *interp, int result); +static int TclNRPackageObjCmdCleanup(void *data[], Tcl_Interp *interp, int result); /* * Helper macros. */ @@ -190,11 +190,11 @@ return TCL_OK; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "conflicting versions provided for package \"%s\": %s, then %s", name, Tcl_GetString(pkgPtr->version), version)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT", NULL); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -223,11 +223,11 @@ *---------------------------------------------------------------------- */ static void PkgFilesCleanupProc( - ClientData clientData, + void *clientData, TCL_UNUSED(Tcl_Interp *)) { PkgFiles *pkgFiles = (PkgFiles *) clientData; Tcl_HashSearch search; Tcl_HashEntry *entry; @@ -387,35 +387,35 @@ */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "Cannot load package \"%s\" in standalone executable:" " This package is not compiled with stub support", name)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNSTUBBED", NULL); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNSTUBBED", (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_GetString(Tcl_GetObjResult(interp)); + result = Tcl_GetStringResult(interp); Tcl_ResetResult(interp); } } else { if (exact && TCL_OK != CheckVersionAndConvert(interp, version, NULL, NULL)) { return NULL; } ov = Tcl_NewStringObj(version, -1); if (exact) { - Tcl_AppendStringsToObj(ov, "-", version, NULL); + Tcl_AppendStringsToObj(ov, "-", version, (void *)NULL); } Tcl_IncrRefCount(ov); if (Tcl_PkgRequireProc(interp, name, 1, &ov, clientDataPtr) == TCL_OK) { - result = Tcl_GetString(Tcl_GetObjResult(interp)); + result = Tcl_GetStringResult(interp); Tcl_ResetResult(interp); } TclDecrRefCount(ov); } return result; @@ -424,11 +424,11 @@ int Tcl_PkgRequireProc( Tcl_Interp *interp, /* Interpreter in which package is now * available. */ const char *name, /* Name of desired package. */ - int reqc, /* Requirements constraining the desired + Tcl_Size reqc, /* Requirements constraining the desired * version. */ Tcl_Obj *const reqv[], /* 0 means to use the latest version * available. */ void *clientDataPtr) { @@ -440,11 +440,11 @@ TclNRPkgRequireProc, (void *) &args, reqc, reqv); } static int TclNRPkgRequireProc( - ClientData clientData, + void *clientData, Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]) { RequireProcArgs *args = (RequireProcArgs *)clientData; @@ -455,16 +455,16 @@ return TCL_OK; } static int PkgRequireCore( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int)) { const char *name = (const char *)data[0]; - int reqc = PTR2INT(data[1]); + int reqc = (int)PTR2INT(data[1]); Tcl_Obj **reqv = (Tcl_Obj **)data[2]; int code = CheckAllRequirements(interp, reqc, reqv); Require *reqPtr; if (code != TCL_OK) { @@ -486,18 +486,18 @@ return TCL_OK; } static int PkgRequireCoreStep1( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int)) { Tcl_DString command; char *script; Require *reqPtr = (Require *)data[0]; - int reqc = PTR2INT(data[1]); + int reqc = (int)PTR2INT(data[1]); Tcl_Obj **const reqv = (Tcl_Obj **)data[2]; const char *name = reqPtr->name /* Name of desired package. */; /* * If we've got the package in the DB already, go on to actually loading @@ -545,23 +545,23 @@ return TCL_OK; } static int PkgRequireCoreStep2( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Require *reqPtr = (Require *)data[0]; - int reqc = PTR2INT(data[1]); + int reqc = (int)PTR2INT(data[1]); Tcl_Obj **const reqv = (Tcl_Obj **)data[2]; const char *name = reqPtr->name; /* Name of desired package. */ if ((result != TCL_OK) && (result != TCL_ERROR)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad return code: %d", result)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", (void *)NULL); result = TCL_ERROR; } if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"package unknown\" script)"); @@ -580,25 +580,25 @@ return TCL_OK; } static int PkgRequireCoreFinal( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int)) { Require *reqPtr = (Require *)data[0]; - int reqc = PTR2INT(data[1]), satisfies; + int reqc = (int)PTR2INT(data[1]), satisfies; Tcl_Obj **const reqv = (Tcl_Obj **)data[2]; char *pkgVersionI; void *clientDataPtr = reqPtr->clientDataPtr; const char *name = reqPtr->name; /* Name of desired package. */ if (reqPtr->pkgPtr->version == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't find package %s", name)); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", NULL); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", (void *)NULL); AddRequirementsToResult(interp, reqc, reqv); return TCL_ERROR; } /* @@ -615,11 +615,11 @@ 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); + (void *)NULL); AddRequirementsToResult(interp, reqc, reqv); return TCL_ERROR; } } @@ -632,30 +632,30 @@ return TCL_OK; } static int PkgRequireCoreCleanup( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { Tcl_Free(data[0]); return result; } static int SelectPackage( - ClientData data[], + void *data[], Tcl_Interp *interp, TCL_UNUSED(int)) { PkgAvail *availPtr, *bestPtr, *bestStablePtr; char *availVersion, *bestVersion, *bestStableVersion; /* Internal rep. of versions */ int availStable, satisfies; Require *reqPtr = (Require *)data[0]; - int reqc = PTR2INT(data[1]); + int reqc = (int)PTR2INT(data[1]); Tcl_Obj **const reqv = (Tcl_Obj **)data[2]; const char *name = reqPtr->name; Package *pkgPtr = reqPtr->pkgPtr; Interp *iPtr = (Interp *) interp; @@ -668,11 +668,11 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "circular package dependency:" " attempt to provide %s %s requires %s", name, (char *) pkgPtr->clientData, name)); AddRequirementsToResult(interp, reqc, reqv); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", NULL); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", (void *)NULL); return TCL_ERROR; } /* * The package isn't yet present. Search the list of available versions @@ -826,11 +826,11 @@ /* * Push "ifneeded" package name in "tclPkgFiles" assocdata. */ - pkgName = (PkgName *)Tcl_Alloc(sizeof(PkgName) + strlen(name)); + pkgName = (PkgName *)Tcl_Alloc(offsetof(PkgName, name) + 1 + strlen(name)); pkgName->nextPtr = pkgFiles->names; strcpy(pkgName->name, name); pkgFiles->names = pkgName; if (bestPtr->pkgIndex) { TclPkgFileSeen(interp, bestPtr->pkgIndex); @@ -845,16 +845,16 @@ return TCL_OK; } static int SelectPackageFinal( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Require *reqPtr = (Require *)data[0]; - int reqc = PTR2INT(data[1]); + int reqc = (int)PTR2INT(data[1]); Tcl_Obj **const reqv = (Tcl_Obj **)data[2]; const char *name = reqPtr->name; char *versionToProvide = reqPtr->versionToProvide; /* @@ -874,11 +874,11 @@ 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); + (void *)NULL); } else { char *pvi, *vi; if (TCL_OK != CheckVersionAndConvert(interp, Tcl_GetString(reqPtr->pkgPtr->version), &pvi, NULL)) { @@ -898,11 +898,11 @@ "attempt to provide package %s %s failed:" " package %s %s provided instead", name, versionToProvide, name, Tcl_GetString(reqPtr->pkgPtr->version))); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", - "WRONGPROVIDE", NULL); + "WRONGPROVIDE", (void *)NULL); } } } } else if (result != TCL_ERROR) { Tcl_Obj *codePtr; @@ -910,11 +910,11 @@ TclNewIntObj(codePtr, result); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "attempt to provide package %s %s failed:" " bad return code: %s", name, versionToProvide, TclGetString(codePtr))); - Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); + Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", (void *)NULL); TclDecrRefCount(codePtr); result = TCL_ERROR; } if (result == TCL_ERROR) { @@ -1016,11 +1016,11 @@ const char *foundVersion = Tcl_PkgRequireEx(interp, name, version, exact, clientDataPtr); if (foundVersion == NULL) { Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, - NULL); + (void *)NULL); } return foundVersion; } } @@ -1029,11 +1029,11 @@ "package %s %s is not present", name, version)); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "package %s is not present", name)); } - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, (void *)NULL); return NULL; } /* *---------------------------------------------------------------------- @@ -1051,21 +1051,21 @@ * *---------------------------------------------------------------------- */ int Tcl_PackageObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRPackageObjCmd, clientData, objc, objv); } int TclNRPackageObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const pkgOptions[] = { @@ -1075,13 +1075,14 @@ }; enum pkgOptionsEnum { PKG_FILES, PKG_FORGET, PKG_IFNEEDED, PKG_NAMES, PKG_PREFER, PKG_PRESENT, PKG_PROVIDE, PKG_REQUIRE, PKG_UNKNOWN, PKG_VCOMPARE, PKG_VERSIONS, PKG_VSATISFIES - }; + } optionIndex; Interp *iPtr = (Interp *) interp; - int optionIndex, exact, i, newobjc, satisfies; + int exact, satisfies; + Tcl_Size i, newobjc; PkgAvail *availPtr, *prevPtr; Package *pkgPtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_HashTable *tablePtr; @@ -1097,11 +1098,11 @@ if (Tcl_GetIndexFromObj(interp, objv[1], pkgOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } - switch ((enum pkgOptionsEnum) optionIndex) { + switch (optionIndex) { case PKG_FILES: { PkgFiles *pkgFiles; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "package"); @@ -1157,11 +1158,11 @@ Tcl_Free(pkgPtr); } break; } case PKG_IFNEEDED: { - size_t length; + Tcl_Size length; int res; char *argv3i, *avi; if ((objc != 4) && (objc != 5)) { Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?"); @@ -1180,11 +1181,11 @@ } pkgPtr = (Package *)Tcl_GetHashValue(hPtr); } else { pkgPtr = FindPackage(interp, argv2); } - argv3 = TclGetStringFromObj(objv[3], &length); + argv3 = Tcl_GetStringFromObj(objv[3], &length); for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL; prevPtr = availPtr, availPtr = availPtr->nextPtr) { if (CheckVersionAndConvert(interp, availPtr->version, &avi, NULL) != TCL_OK) { @@ -1227,14 +1228,14 @@ availPtr->nextPtr = prevPtr->nextPtr; prevPtr->nextPtr = availPtr; } } if (iPtr->scriptFile) { - argv4 = TclGetStringFromObj(iPtr->scriptFile, &length); + argv4 = Tcl_GetStringFromObj(iPtr->scriptFile, &length); DupBlock(availPtr->pkgIndex, argv4, length + 1); } - argv4 = TclGetStringFromObj(objv[4], &length); + argv4 = Tcl_GetStringFromObj(objv[4], &length); DupBlock(availPtr->script, argv4, length + 1); break; } case PKG_NAMES: if (objc != 2) { @@ -1351,19 +1352,19 @@ /* * Create a new-style requirement for the exact version. */ ov = Tcl_NewStringObj(version, -1); - Tcl_AppendStringsToObj(ov, "-", version, NULL); + 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); - Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr); + TclListObjGetElementsM(interp, objvListPtr, &newobjc, &newObjvPtr); Tcl_NRAddCallback(interp, TclNRPackageObjCmdCleanup, objv[3], objvListPtr, NULL,NULL); Tcl_NRAddCallback(interp, PkgRequireCore, (void *) argv3, INT2PTR(newobjc), @@ -1386,21 +1387,21 @@ */ Tcl_ListObjAppendElement(interp, objvListPtr, Tcl_DuplicateObj(newobjv[i])); } - Tcl_ListObjGetElements(interp, objvListPtr, &newobjc, &newObjvPtr); + TclListObjGetElementsM(interp, objvListPtr, &newobjc, &newObjvPtr); Tcl_NRAddCallback(interp, TclNRPackageObjCmdCleanup, objv[2], objvListPtr, NULL,NULL); Tcl_NRAddCallback(interp, PkgRequireCore, (void *) argv2, INT2PTR(newobjc), newObjvPtr, NULL); return TCL_OK; } break; case PKG_UNKNOWN: { - size_t length; + Tcl_Size length; if (objc == 2) { if (iPtr->packageUnknown != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(iPtr->packageUnknown, -1)); @@ -1407,11 +1408,11 @@ } } else if (objc == 3) { if (iPtr->packageUnknown != NULL) { Tcl_Free(iPtr->packageUnknown); } - argv2 = TclGetStringFromObj(objv[2], &length); + argv2 = Tcl_GetStringFromObj(objv[2], &length); if (argv2[0] == 0) { iPtr->packageUnknown = NULL; } else { DupBlock(iPtr->packageUnknown, argv2, length+1); } @@ -1536,11 +1537,11 @@ return TCL_OK; } static int TclNRPackageObjCmdCleanup( - ClientData data[], + void *data[], TCL_UNUSED(Tcl_Interp *), int result) { TclDecrRefCount((Tcl_Obj *) data[0]); TclDecrRefCount((Tcl_Obj *) data[1]); @@ -1696,11 +1697,11 @@ goto error; } *ip++ = *p; - for (prevChar = *p, p++; *p != 0; p++) { + for (prevChar = *p, p++; (*p != 0) && (*p != '+'); p++) { if (!isdigit(UCHAR(*p)) && /* INTL: digit */ ((*p!='.' && *p!='a' && *p!='b') || ((hasunstable && (*p=='a' || *p=='b')) || ((prevChar=='a' || prevChar=='b' || prevChar=='.') && (*p=='.')) || @@ -1753,11 +1754,11 @@ error: Tcl_Free(ibuf); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected version number but got \"%s\"", string)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSION", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSION", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -1782,11 +1783,11 @@ CompareVersions( char *v1, char *v2, /* Versions strings, of form 2.1.3 (any number * of version numbers). */ int *isMajorPtr) /* If non-null, the word pointed to is filled * in with a 0/1 value. 1 means that the - * difference occured in the first element. */ + * difference occurred in the first element. */ { int thisIsMajor, res, flip; char *s1, *e1, *s2, *e2, o1, o2; /* @@ -2000,14 +2001,14 @@ * = version- */ char *dash = NULL, *buf; - dash = (char *)strchr(string, '-'); + dash = strchr(string, '+') ? NULL : (char *)strchr(string, '-'); if (dash == NULL) { /* - * No dash found, has to be a simple version. + * '+' found or no dash found: has to be a simple version. */ return CheckVersionAndConvert(interp, string, NULL, NULL); } @@ -2016,11 +2017,11 @@ * More dashes found after the first. This is wrong. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected versionMin-versionMax but got \"%s\"", string)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSIONRANGE", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSIONRANGE", (void *)NULL); return TCL_ERROR; } /* * Exactly one dash is present. Copy the string, split at the location of @@ -2069,14 +2070,14 @@ Tcl_Obj *const reqv[]) /* 0 means to use the latest version * available. */ { Tcl_Obj *result = Tcl_GetObjResult(interp); int i; - size_t length; + Tcl_Size length; for (i = 0; i < reqc; i++) { - const char *v = TclGetStringFromObj(reqv[i], &length); + const char *v = Tcl_GetStringFromObj(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)); } else { @@ -2236,11 +2237,11 @@ return satisfied; } /* * We have both min and max, and generate their internal reps. When - * identical we compare as is, otherwise we pad with 'a0' to ove the range + * identical we compare as is, otherwise we pad with 'a0' to over the range * a bit. */ CheckVersionAndConvert(NULL, buf, &min, NULL); CheckVersionAndConvert(NULL, dash, &max, NULL); Index: generic/tclPkgConfig.c ================================================================== --- generic/tclPkgConfig.c +++ generic/tclPkgConfig.c @@ -1,12 +1,12 @@ /* * tclPkgConfig.c -- * * This file contains the configuration information to embed into the tcl - * binary library. + * library. * - * Copyright (c) 2002 Andreas Kupries + * Copyright © 2002 Andreas Kupries * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -107,12 +107,13 @@ {"libdir,runtime", CFG_RUNTIME_LIBDIR}, {"bindir,runtime", CFG_RUNTIME_BINDIR}, {"scriptdir,runtime", CFG_RUNTIME_SCRDIR}, {"includedir,runtime", CFG_RUNTIME_INCDIR}, {"docdir,runtime", CFG_RUNTIME_DOCDIR}, +#if !defined(STATIC_BUILD) {"dllfile,runtime", CFG_RUNTIME_DLLFILE}, - {"zipfile,runtime", CFG_RUNTIME_ZIPFILE}, +#endif /* Installation paths to various stuff */ {"libdir,install", CFG_INSTALL_LIBDIR}, {"bindir,install", CFG_INSTALL_BINDIR}, Index: generic/tclPlatDecls.h ================================================================== --- generic/tclPlatDecls.h +++ generic/tclPlatDecls.h @@ -38,10 +38,106 @@ 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 @@ -48,28 +144,31 @@ /* * 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, + int hasResourceFile, Tcl_Size maxPathLen, char *libraryPath); -#endif /* MACOSX */ +/* 2 */ +EXTERN void Tcl_MacOSXNotifierAddRunLoopMode( + const void *runLoopMode); +/* 3 */ +EXTERN void Tcl_WinConvertError(unsigned errCode); typedef struct TclPlatStubs { int magic; void *hooks; -#ifdef MAC_OSX_TCL /* MACOSX */ void (*reserved0)(void); - int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, size_t maxPathLen, char *libraryPath); /* 1 */ -#endif /* MACOSX */ + int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, Tcl_Size maxPathLen, char *libraryPath); /* 1 */ + void (*tcl_MacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 2 */ + void (*tcl_WinConvertError) (unsigned errCode); /* 3 */ } TclPlatStubs; extern const TclPlatStubs *tclPlatStubsPtr; #ifdef __cplusplus @@ -80,31 +179,50 @@ /* * Inline function declarations: */ -#ifdef MAC_OSX_TCL /* MACOSX */ /* Slot 0 is reserved */ #define Tcl_MacOSXOpenVersionedBundleResources \ (tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */ -#endif /* MACOSX */ +#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 -#if defined(USE_TCL_STUBS) && defined(_WIN32) && !defined(TCL_NO_DEPRECATED) +#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 */ Index: generic/tclPosixStr.c ================================================================== --- generic/tclPosixStr.c +++ generic/tclPosixStr.c @@ -2,12 +2,12 @@ * tclPosixStr.c -- * * This file contains procedures that generate strings corresponding to * various POSIX-related codes, such as errno and signals. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -60,10 +60,13 @@ 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"; @@ -72,13 +75,10 @@ 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"; @@ -93,10 +93,16 @@ 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"; @@ -138,16 +144,22 @@ 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"; @@ -156,10 +168,16 @@ 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"; @@ -174,16 +192,13 @@ case EISCONN: return "EISCONN"; #endif #ifdef EISDIR case EISDIR: return "EISDIR"; #endif -#ifdef EISNAME +#ifdef EISNAM case EISNAM: return "EISNAM"; #endif -#ifdef ELBIN - case ELBIN: return "ELBIN"; -#endif #ifdef EL2HLT case EL2HLT: return "EL2HLT"; #endif #ifdef EL2NSYNC case EL2NSYNC: return "EL2NSYNC"; @@ -192,10 +207,13 @@ 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"; @@ -213,10 +231,13 @@ 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"; @@ -231,13 +252,10 @@ 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"; @@ -246,10 +264,13 @@ 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"; @@ -276,10 +297,13 @@ 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"; @@ -288,10 +312,13 @@ 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"; @@ -333,10 +360,13 @@ 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"; @@ -399,10 +429,13 @@ 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"; @@ -514,50 +547,56 @@ #endif #ifdef EAGAIN case EAGAIN: return "resource temporarily unavailable"; #endif #ifdef EALIGN - case EALIGN: return "EALIGN"; + case EALIGN: return "alignment error"; #endif #if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY)) case EALREADY: return "operation already in progress"; #endif +#ifdef EBADCAT + case EBADCAT: return "bad message catalogue format"; +#endif #ifdef EBADE - case EBADE: return "bad exchange descriptor"; + case EBADE: return "invalid exchange"; #endif #ifdef EBADF - case EBADF: return "bad file number"; + case EBADF: return "bad file descriptor"; #endif #ifdef EBADFD case EBADFD: return "file descriptor in bad state"; #endif #ifdef EBADMSG - case EBADMSG: return "not a data message"; -#endif -#ifdef ECANCELED - case ECANCELED: return "operation canceled"; + case EBADMSG: return "bad message"; #endif #ifdef EBADR - case EBADR: return "bad request descriptor"; + case EBADR: return "invalid request descriptor"; #endif #ifdef EBADRPC case EBADRPC: return "RPC structure is bad"; #endif #ifdef EBADRQC - case EBADRQC: return "bad request code"; + case EBADRQC: return "invalid request code"; #endif #ifdef EBADSLT case EBADSLT: return "invalid slot"; #endif #ifdef EBFONT case EBFONT: return "bad font file format"; #endif #ifdef EBUSY - case EBUSY: return "file busy"; + case EBUSY: return "device or resource busy"; +#endif +#ifdef ECANCELED + case ECANCELED: return "operation canceled"; +#endif +#ifdef ECASECLASH + case ECASECLASH: return "filename exists with different case"; #endif #ifdef ECHILD - case ECHILD: return "no children"; + case ECHILD: return "no child processes"; #endif #ifdef ECHRNG case ECHRNG: return "channel number out of range"; #endif #ifdef ECOMM @@ -583,11 +622,11 @@ #endif #ifdef EDIRTY case EDIRTY: return "mounting a dirty fs w/o force"; #endif #ifdef EDOM - case EDOM: return "math argument out of range"; + case EDOM: return "numerical argument out of domain"; #endif #ifdef EDOTDOT case EDOTDOT: return "cross mount point"; #endif #ifdef EDQUOT @@ -595,30 +634,42 @@ #endif #ifdef EDUPPKG case EDUPPKG: return "duplicate package name"; #endif #ifdef EEXIST - case EEXIST: return "file already exists"; + case EEXIST: return "file exists"; +#endif +#ifdef EFAIL + case EFAIL: return "cannot start operation"; #endif #ifdef EFAULT - case EFAULT: return "bad address in system call argument"; + case EFAULT: return "bad address"; #endif #ifdef EFBIG case EFBIG: return "file too large"; #endif +#ifdef EFTYPE + case EFTYPE: return "inappropriate file type or format"; +#endif #ifdef EHOSTDOWN case EHOSTDOWN: return "host is down"; #endif #ifdef EHOSTUNREACH - case EHOSTUNREACH: return "host is unreachable"; + case EHOSTUNREACH: return "no route to host"; #endif #if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS)) case EIDRM: return "identifier removed"; #endif #ifdef EINIT case EINIT: return "initialization error"; #endif +#ifdef EILSEQ + case EILSEQ: return "invalid or incomplete multibyte or wide character"; +#endif +#ifdef EINPROG + case EINPROG: return "asynchronous operation in progress"; +#endif #ifdef EINPROGRESS case EINPROGRESS: return "operation now in progress"; #endif #ifdef EINTR case EINTR: return "interrupted system call"; @@ -625,23 +676,20 @@ #endif #ifdef EINVAL case EINVAL: return "invalid argument"; #endif #ifdef EIO - case EIO: return "I/O error"; + case EIO: return "input/output error"; #endif #ifdef EISCONN - case EISCONN: return "socket is already connected"; + case EISCONN: return "transport endpoint is already connected"; #endif #ifdef EISDIR - case EISDIR: return "illegal operation on a directory"; + case EISDIR: return "is a directory"; #endif -#ifdef EISNAME - case EISNAM: return "is a name file"; -#endif -#ifdef ELBIN - case ELBIN: return "ELBIN"; +#ifdef EISNAM + case EISNAM: return "is a named type file"; #endif #ifdef EL2HLT case EL2HLT: return "level 2 halted"; #endif #ifdef EL2NSYNC @@ -651,22 +699,25 @@ case EL3HLT: return "level 3 halted"; #endif #ifdef EL3RST case EL3RST: return "level 3 reset"; #endif +#ifdef ELBIN + case ELBIN: return "inode is remote"; +#endif #ifdef ELIBACC - case ELIBACC: return "cannot access a needed shared library"; + case ELIBACC: return "can not access a needed shared library"; #endif #ifdef ELIBBAD case ELIBBAD: return "accessing a corrupted shared library"; #endif #ifdef ELIBEXEC case ELIBEXEC: return "cannot exec a shared library directly"; #endif #if defined(ELIBMAX) && (!defined(ECANCELED) || (ELIBMAX != ECANCELED)) case ELIBMAX: return - "attempting to link in more shared libraries than system limit"; + "attempting to link in too many shared libraries"; #endif #ifdef ELIBSCN case ELIBSCN: return ".lib section in a.out corrupted"; #endif #ifdef ELNRNG @@ -673,10 +724,13 @@ 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"; @@ -691,13 +745,10 @@ 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"; @@ -704,14 +755,17 @@ #endif #ifdef ENETUNREACH case ENETUNREACH: return "network is unreachable"; #endif #ifdef ENFILE - case ENFILE: return "file table overflow"; + case ENFILE: return "too many open files in system"; +#endif +#ifdef ENMFILE + case ENMFILE: return "no more files"; #endif #ifdef ENOANO - case ENOANO: return "anode table overflow"; + case ENOANO: return "no anode"; #endif #if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR)) case ENOBUFS: return "no buffer space available"; #endif #ifdef ENOCSI @@ -734,11 +788,14 @@ #endif #ifdef ENOLINK case ENOLINK: return "link has been severed"; #endif #ifdef ENOMEM - case ENOMEM: return "not enough memory"; + case ENOMEM: return "cannot allocate memory"; +#endif +#ifdef ENOMEDIUM + case ENOMEDIUM: return "no medium found"; #endif #ifdef ENOMSG case ENOMSG: return "no message of desired type"; #endif #ifdef ENONET @@ -746,20 +803,23 @@ #endif #ifdef ENOPKG case ENOPKG: return "package not installed"; #endif #ifdef ENOPROTOOPT - case ENOPROTOOPT: return "bad protocol option"; + case ENOPROTOOPT: return "protocol not available"; +#endif +#ifdef ENOSHARE + case ENOSHARE: return "no such host or network path"; #endif #ifdef ENOSPC case ENOSPC: return "no space left on device"; #endif #if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR)) - case ENOSR: return "out of stream resources"; + case ENOSR: return "out of streams resources"; #endif #if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR)) - case ENOSTR: return "not a stream device"; + case ENOSTR: return "device not a stream"; #endif #ifdef ENOSYM case ENOSYM: return "unresolved symbol name"; #endif #ifdef ENOSYS @@ -767,14 +827,11 @@ #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"; + 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)) @@ -781,22 +838,28 @@ case ENOTEMPTY: return "directory not empty"; #endif #ifdef ENOTNAM case ENOTNAM: return "not a name file"; #endif +#ifdef ENOTRECOVERABLE + case ENOTRECOVERABLE: return "state not recoverable"; +#endif #ifdef ENOTSOCK case ENOTSOCK: return "socket operation on non-socket"; #endif #ifdef ENOTSUP case ENOTSUP: return "operation not supported"; #endif #ifdef ENOTTY - case ENOTTY: return "inappropriate device for ioctl"; + case ENOTTY: return "inappropriate ioctl for device"; #endif #ifdef ENOTUNIQ case ENOTUNIQ: return "name not unique on network"; #endif +#ifdef ENWAIT + case ENWAIT: return "No waiting processes"; +#endif #ifdef ENXIO case ENXIO: return "no such device or address"; #endif #if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) case EOPNOTSUPP: return "operation not supported on socket"; @@ -803,17 +866,17 @@ #endif #ifdef EOTHER case EOTHER: return "other error"; #endif #if defined(EOVERFLOW) && (!defined(EFBIG) || (EOVERFLOW != EFBIG)) && (!defined(EINVAL) || (EOVERFLOW != EINVAL)) - case EOVERFLOW: return "file too big"; + case EOVERFLOW: return "value too large for defined data type"; #endif #ifdef EOWNERDEAD case EOWNERDEAD: return "owner died"; #endif #ifdef EPERM - case EPERM: return "not owner"; + case EPERM: return "operation not permitted"; #endif #if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT)) case EPFNOSUPPORT: return "protocol family not supported"; #endif #ifdef EPIPE @@ -839,29 +902,32 @@ #endif #ifdef EPROTOTYPE case EPROTOTYPE: return "protocol wrong type for socket"; #endif #ifdef ERANGE - case ERANGE: return "math result unrepresentable"; + case ERANGE: return "numerical result out of range"; #endif #if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED)) - case EREFUSED: return "EREFUSED"; + case EREFUSED: return "connection refused"; #endif #ifdef EREMCHG case EREMCHG: return "remote address changed"; #endif #ifdef EREMDEV case EREMDEV: return "remote device"; #endif #ifdef EREMOTE - case EREMOTE: return "pathname hit remote file system"; + case EREMOTE: return "object is remote"; #endif #ifdef EREMOTEIO - case EREMOTEIO: return "remote i/o error"; + case EREMOTEIO: return "remote I/O error"; #endif #ifdef EREMOTERELEASE - case EREMOTERELEASE: return "EREMOTERELEASE"; + case EREMOTERELEASE: return "remote peer released connection"; +#endif +#ifdef ERESTART + case ERESTART: return "interrupted system call should be restarted"; #endif #ifdef EROFS case EROFS: return "read-only file system"; #endif #ifdef ERPCMISMATCH @@ -869,29 +935,32 @@ #endif #ifdef ERREMOTE case ERREMOTE: return "object is remote"; #endif #ifdef ESHUTDOWN - case ESHUTDOWN: return "cannot send after socket shutdown"; + case ESHUTDOWN: return "cannot send after transport endpoint shutdown"; #endif #ifdef ESOCKTNOSUPPORT case ESOCKTNOSUPPORT: return "socket type not supported"; #endif #ifdef ESPIPE - case ESPIPE: return "invalid seek"; + case ESPIPE: return "illegal seek"; #endif #ifdef ESRCH case ESRCH: return "no such process"; #endif #ifdef ESRMNT case ESRMNT: return "srmount error"; #endif #ifdef ESTALE - case ESTALE: return "stale remote file handle"; + case ESTALE: return "stale file handle"; +#endif +#ifdef ESTRPIPE + case ESTRPIPE: return "streams pipe error"; #endif #ifdef ESUCCESS - case ESUCCESS: return "Error 0"; + case ESUCCESS: return "success"; #endif #if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP)) case ETIME: return "timer expired"; #endif #if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR)) @@ -899,11 +968,11 @@ #endif #ifdef ETOOMANYREFS case ETOOMANYREFS: return "too many references: cannot splice"; #endif #ifdef ETXTBSY - case ETXTBSY: return "text file or pseudo-device busy"; + case ETXTBSY: return "text file busy"; #endif #ifdef EUCLEAN case EUCLEAN: return "structure needs cleaning"; #endif #ifdef EUNATCH @@ -917,14 +986,14 @@ #endif #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) case EWOULDBLOCK: return "operation would block"; #endif #ifdef EXDEV - case EXDEV: return "cross-domain link"; + case EXDEV: return "invalid cross-device link"; #endif #ifdef EXFULL - case EXFULL: return "message tables full"; + case EXFULL: return "exchange full"; #endif default: #ifdef NO_STRERROR return "unknown POSIX error"; #else Index: generic/tclPreserve.c ================================================================== --- generic/tclPreserve.c +++ generic/tclPreserve.c @@ -3,49 +3,42 @@ * * This file contains a collection of functions that are used to make * sure that widget records and other data structures aren't reallocated * when there are nested functions that depend on their existence. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" +#include "tclBrodnik.h" /* * The following data structure is used to keep track of all the Tcl_Preserve * calls that are still in effect. It grows as needed to accommodate any * number of calls in effect. */ typedef struct { - ClientData clientData; /* Address of preserved block. */ + void *clientData; /* Address of preserved block. */ size_t refCount; /* Number of Tcl_Preserve calls in effect for * block. */ - int mustFree; /* Non-zero means Tcl_EventuallyFree was - * called while a Tcl_Preserve call was in - * effect, so the structure must be freed when - * refCount becomes zero. */ Tcl_FreeProc *freeProc; /* Function to call to free. */ } Reference; /* * Global data structures used to hold the list of preserved data references. * These variables are protected by "preserveMutex". */ -static Reference *refArray = NULL; /* First in array of references. */ -static size_t spaceAvl = 0; /* Total number of structures available at - * *firstRefPtr. */ -static size_t inUse = 0; /* Count of structures currently in use in - * refArray. */ -TCL_DECLARE_MUTEX(preserveMutex)/* To protect the above statics */ - -#define INITIAL_SIZE 2 /* Initial number of reference slots to make */ +TclBrodnikArray(Reference); + +static BA_Reference *refArray = NULL; +TCL_DECLARE_MUTEX(preserveMutex) /* To protect the refArray */ /* * The following data structure is used to keep track of whether an arbitrary * block of memory has been deleted. This is used by the TclHandle code to * avoid the more time-expensive algorithm of Tcl_Preserve(). This mechanism @@ -85,15 +78,12 @@ void TclFinalizePreserve(void) { Tcl_MutexLock(&preserveMutex); - if (spaceAvl != 0) { - Tcl_Free(refArray); - refArray = NULL; - inUse = 0; - spaceAvl = 0; + if (refArray) { + BA_Reference_Destroy(refArray); } Tcl_MutexUnlock(&preserveMutex); } /* @@ -115,49 +105,44 @@ *---------------------------------------------------------------------- */ void Tcl_Preserve( - ClientData clientData) /* Pointer to malloc'ed block of memory. */ + void *clientData) /* Pointer to malloc'ed block of memory. */ { Reference *refPtr; - size_t i; /* * See if there is already a reference for this pointer. If so, just * increment its reference count. */ Tcl_MutexLock(&preserveMutex); - for (i=0, refPtr=refArray ; iclientData == clientData) { - refPtr->refCount++; - Tcl_MutexUnlock(&preserveMutex); - return; - } - } - - /* - * Make a reference array if it doesn't already exist, or make it bigger - * if it is full. - */ - - if (inUse == spaceAvl) { - spaceAvl = spaceAvl ? 2*spaceAvl : INITIAL_SIZE; - refArray = (Reference *)Tcl_Realloc(refArray, spaceAvl * sizeof(Reference)); + if (refArray == NULL) { + refArray = BA_Reference_Create(); + } else { + BP_Reference ptr; + + refPtr = BA_Reference_First(refArray, &ptr); + while (refPtr) { + if (refPtr->clientData == clientData) { + refPtr->refCount++; + Tcl_MutexUnlock(&preserveMutex); + return; + } + refPtr = BP_Reference_Next(&ptr); + } } /* * Make a new entry for the new reference. */ - refPtr = &refArray[inUse]; + refPtr = BA_Reference_Append(refArray); refPtr->clientData = clientData; refPtr->refCount = 1; - refPtr->mustFree = 0; - refPtr->freeProc = 0; - inUse += 1; + refPtr->freeProc = NULL; Tcl_MutexUnlock(&preserveMutex); } /* *---------------------------------------------------------------------- @@ -178,19 +163,24 @@ *---------------------------------------------------------------------- */ void Tcl_Release( - ClientData clientData) /* Pointer to malloc'ed block of memory. */ + void *clientData) /* Pointer to malloc'ed block of memory. */ { Reference *refPtr; - size_t i; + BP_Reference ptr; Tcl_MutexLock(&preserveMutex); - for (i=0, refPtr=refArray ; iclientData != clientData) { continue; } @@ -205,14 +195,13 @@ * same clientData. Copy down the last reference in the array to * overwrite the current slot. */ freeProc = refPtr->freeProc; - mustFree = refPtr->mustFree; - inUse--; - if (i < inUse) { - refArray[i] = refArray[inUse]; + lastRefPtr = BA_Reference_Detach(refArray); + if (refPtr != lastRefPtr) { + *refPtr = *lastRefPtr; } /* * Now committed to disposing the data. But first, we've patched up * all the global data structures so we should release the mutex now. @@ -219,16 +208,12 @@ * Only then should we dabble around with potentially-slow memory * managers... */ Tcl_MutexUnlock(&preserveMutex); - if (mustFree) { - if (freeProc == TCL_DYNAMIC) { - Tcl_Free(clientData); - } else { - freeProc((char *)clientData); - } + if (freeProc) { + freeProc((char *)clientData); } return; } Tcl_MutexUnlock(&preserveMutex); @@ -255,32 +240,46 @@ * Ptr may be released by calling free(). * *---------------------------------------------------------------------- */ +#ifdef TCL_MEM_DEBUG +# undef Tcl_Free +# define Tcl_Free freeproc +static void Tcl_Free(void *x) { + Tcl_DbCkfree((x), __FILE__, __LINE__); +} +#endif + void Tcl_EventuallyFree( - ClientData clientData, /* Pointer to malloc'ed block of memory. */ + void *clientData, /* Pointer to malloc'ed block of memory. */ Tcl_FreeProc *freeProc) /* Function to actually do free. */ { Reference *refPtr; - size_t i; + BP_Reference ptr; + if (freeProc == TCL_DYNAMIC) { + freeProc = Tcl_Free; + } /* - * See if there is a reference for this pointer. If so, set its "mustFree" - * flag (the flag had better not be set already!). + * See if there is a reference for this pointer. If so, set the freeProc + * to call (it should not be set already!). */ - Tcl_MutexLock(&preserveMutex); - for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) { + if (refArray == NULL) { + refArray = BA_Reference_Create(); + } + + for (refPtr = BA_Reference_First(refArray, &ptr); refPtr; + refPtr = BP_Reference_Next(&ptr)) { if (refPtr->clientData != clientData) { continue; } - if (refPtr->mustFree) { + if (refPtr->freeProc) { Tcl_Panic("Tcl_EventuallyFree called twice for %p", clientData); } - refPtr->mustFree = 1; refPtr->freeProc = freeProc; Tcl_MutexUnlock(&preserveMutex); return; } Tcl_MutexUnlock(&preserveMutex); @@ -287,15 +286,11 @@ /* * No reference for this block. Free it now. */ - if (freeProc == TCL_DYNAMIC) { - Tcl_Free(clientData); - } else { - freeProc((char *)clientData); - } + freeProc(clientData); } /* *--------------------------------------------------------------------------- * Index: generic/tclProc.c ================================================================== --- generic/tclProc.c +++ generic/tclProc.c @@ -2,14 +2,14 @@ * 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 + * 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 * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -49,10 +49,11 @@ 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 */ @@ -61,41 +62,42 @@ ProcBodyFree, /* FreeInternalRep function */ ProcBodyDup, /* DupInternalRep function */ NULL, /* UpdateString function; Tcl_GetString and * Tcl_GetStringFromObj should panic * instead. */ - NULL /* SetFromAny function; Tcl_ConvertToType + NULL, /* SetFromAny function; Tcl_ConvertToType * should panic instead. */ + TCL_OBJTYPE_V0 }; -#define ProcSetIntRep(objPtr, procPtr) \ +#define ProcSetInternalRep(objPtr, procPtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ (procPtr)->refCount++; \ ir.twoPtrValue.ptr1 = (procPtr); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreIntRep((objPtr), &tclProcBodyType, &ir); \ + Tcl_StoreInternalRep((objPtr), &tclProcBodyType, &ir); \ } while (0) -#define ProcGetIntRep(objPtr, procPtr) \ +#define ProcGetInternalRep(objPtr, procPtr) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), &tclProcBodyType); \ + const Tcl_ObjInternalRep *irPtr; \ + irPtr = TclFetchInternalRep((objPtr), &tclProcBodyType); \ (procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* - * The [upvar]/[uplevel] level reference type. Uses the longValue field + * The [upvar]/[uplevel] level reference type. Uses the wideValue field * to remember the integer value of a parsed # format. * * Uses the default behaviour throughout, and never disposes of the string * rep; it's just a cache type. */ static const Tcl_ObjType levelReferenceType = { "levelReference", - NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, TCL_OBJTYPE_V0 }; /* * The type of lambdas. Note that every lambda will *always* have a string * representation. @@ -108,26 +110,27 @@ static const Tcl_ObjType lambdaType = { "lambdaExpr", /* name */ FreeLambdaInternalRep, /* freeIntRepProc */ DupLambdaInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetLambdaFromAny /* setFromAnyProc */ + SetLambdaFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; -#define LambdaSetIntRep(objPtr, procPtr, nsObjPtr) \ +#define LambdaSetInternalRep(objPtr, procPtr, nsObjPtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (procPtr); \ ir.twoPtrValue.ptr2 = (nsObjPtr); \ Tcl_IncrRefCount((nsObjPtr)); \ - Tcl_StoreIntRep((objPtr), &lambdaType, &ir); \ + Tcl_StoreInternalRep((objPtr), &lambdaType, &ir); \ } while (0) -#define LambdaGetIntRep(objPtr, procPtr, nsObjPtr) \ +#define LambdaGetInternalRep(objPtr, procPtr, nsObjPtr) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), &lambdaType); \ + 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) @@ -146,15 +149,16 @@ * A new procedure gets created. * *---------------------------------------------------------------------- */ +#undef TclObjInterpProc int Tcl_ProcObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; Proc *procPtr; const char *procName; @@ -179,18 +183,18 @@ if (nsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\": unknown namespace", procName)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", (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", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", (void *)NULL); return TCL_ERROR; } /* * Create the data structure to represent the procedure. @@ -203,11 +207,11 @@ Tcl_AddErrorInfo(interp, "\")"); return TCL_ERROR; } cmd = TclNRCreateCommandInNs(interp, simpleName, (Tcl_Namespace *) nsPtr, - TclObjInterpProc, TclNRInterpProc, procPtr, TclProcDeleteProc); + TclObjInterpProc, NRInterpProc, procPtr, TclProcDeleteProc); /* * Now initialize the new procedure's cmdPtr field. This will be used * later when the procedure is called to determine what namespace the * procedure will run in. This will be different than the current @@ -263,11 +267,11 @@ Tcl_HashEntry *hePtr; CmdFrame *cfPtr = (CmdFrame *)Tcl_Alloc(sizeof(CmdFrame)); cfPtr->level = -1; cfPtr->type = contextPtr->type; - cfPtr->line = (int *)Tcl_Alloc(sizeof(int)); + cfPtr->line = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size)); cfPtr->line[0] = contextPtr->line[3]; cfPtr->nline = 1; cfPtr->framePtr = NULL; cfPtr->nextPtr = NULL; @@ -325,11 +329,11 @@ * - could be enhanced to handle also non-empty bodies that contain only * comments; however, parsing the body will slow down the compilation * of all procs whose argument list is just _args_ */ - if (objv[3]->typePtr == &tclProcBodyType) { + if (TclHasInternalRep(objv[3], &tclProcBodyType)) { goto done; } procArgs = TclGetString(objv[2]); @@ -336,11 +340,11 @@ while (*procArgs == ' ') { procArgs++; } if ((procArgs[0] == 'a') && (strncmp(procArgs, "args", 4) == 0)) { - size_t numBytes; + Tcl_Size numBytes; procArgs +=4; while (*procArgs != '\0') { if (*procArgs != ' ') { goto done; @@ -350,11 +354,11 @@ /* * The argument list is just "args"; check the body */ - procBody = TclGetStringFromObj(objv[3], &numBytes); + procBody = Tcl_GetStringFromObj(objv[3], &numBytes); if (TclParseAllWhiteSpace(procBody, numBytes) < numBytes) { goto done; } /* @@ -402,16 +406,16 @@ Proc **procPtrPtr) /* Returns: pointer to proc data. */ { Interp *iPtr = (Interp *) interp; Proc *procPtr = NULL; - int i, result, numArgs; + Tcl_Size i, numArgs; CompiledLocal *localPtr = NULL; Tcl_Obj **argArray; - int precompiled = 0; + int precompiled = 0, result; - ProcGetIntRep(bodyPtr, procPtr); + ProcGetInternalRep(bodyPtr, procPtr); if (procPtr != NULL) { /* * Because the body is a TclProProcBody, the actual body is already * compiled, and it is not shared with anyone else, so it's OK not to * unshare it (as a matter of fact, it is bad to unshare it, because @@ -442,14 +446,14 @@ * not want any bytecode internal representation. */ if (Tcl_IsShared(bodyPtr)) { const char *bytes; - size_t length; + Tcl_Size length; Tcl_Obj *sharedBodyPtr = bodyPtr; - bytes = TclGetStringFromObj(bodyPtr, &length); + bytes = Tcl_GetStringFromObj(bodyPtr, &length); bodyPtr = Tcl_NewStringObj(bytes, length); /* * TIP #280. * Ensure that the continuation line data for the original body is @@ -482,23 +486,23 @@ * argument specifier. If the body is precompiled, processing is limited * to checking that the parsed argument is consistent with the one stored * in the Proc. */ - result = Tcl_ListObjGetElements(interp , argsPtr ,&numArgs ,&argArray); + result = TclListObjGetElementsM(interp, argsPtr, &numArgs, &argArray); if (result != TCL_OK) { goto procError; } if (precompiled) { if (numArgs > procPtr->numArgs) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "procedure \"%s\": arg list contains %d entries, " - "precompiled header expects %d", procName, numArgs, + "procedure \"%s\": arg list contains %" TCL_SIZE_MODIFIER "u entries, " + "precompiled header expects %" TCL_SIZE_MODIFIER "u", procName, numArgs, procPtr->numArgs)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", - "BYTECODELIES", NULL); + "BYTECODELIES", (void *)NULL); goto procError; } localPtr = procPtr->firstLocalPtr; } else { procPtr->numArgs = numArgs; @@ -505,19 +509,18 @@ procPtr->numCompiledLocals = numArgs; } for (i = 0; i < numArgs; i++) { const char *argname, *argnamei, *argnamelast; - int fieldCount; - size_t nameLength; + Tcl_Size fieldCount, nameLength; Tcl_Obj **fieldValues; /* * Now divide the specifier up into name and default. */ - result = Tcl_ListObjGetElements(interp, argArray[i], &fieldCount, + result = TclListObjGetElementsM(interp, argArray[i], &fieldCount, &fieldValues); if (result != TCL_OK) { goto procError; } if (fieldCount > 2) { @@ -525,22 +528,22 @@ "too many fields in argument specifier \"", -1); Tcl_AppendObjToObj(errorObj, argArray[i]); Tcl_AppendToObj(errorObj, "\"", -1); Tcl_SetObjResult(interp, errorObj); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", - "FORMALARGUMENTFORMAT", NULL); + "FORMALARGUMENTFORMAT", (void *)NULL); goto procError; } - if ((fieldCount == 0) || (fieldValues[0]->length == 0)) { + if ((fieldCount == 0) || (Tcl_GetCharLength(fieldValues[0]) == 0)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "argument with no name", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", - "FORMALARGUMENTFORMAT", NULL); + "FORMALARGUMENTFORMAT", (void *)NULL); goto procError; } - argname = TclGetStringFromObj(fieldValues[0], &nameLength); + argname = Tcl_GetStringFromObj(fieldValues[0], &nameLength); /* * Check that the formal parameter name is a scalar. */ @@ -551,21 +554,21 @@ if (*argnamelast == ')') { /* We have an array element. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "formal parameter \"%s\" is an array element", TclGetString(fieldValues[0]))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", - "FORMALARGUMENTFORMAT", NULL); + "FORMALARGUMENTFORMAT", (void *)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); + "FORMALARGUMENTFORMAT", (void *)NULL); goto procError; } argnamei++; } @@ -574,11 +577,11 @@ * Compare the parsed argument with the stored one. Note that the * only flag value that makes sense at this point is VAR_ARGUMENT * (its value was kept the same as pre VarReform to simplify * tbcload's processing of older byetcodes). * - * The only other flag vlaue that is important to retrieve from + * The only other flag value that is important to retrieve from * precompiled procs is VAR_TEMPORARY (also unchanged). It is * needed later when retrieving the variable names. */ if ((localPtr->nameLength != nameLength) @@ -586,25 +589,25 @@ || (localPtr->frameIndex != i) || !(localPtr->flags & VAR_ARGUMENT) || (localPtr->defValuePtr == NULL && fieldCount == 2) || (localPtr->defValuePtr != NULL && fieldCount != 2)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "procedure \"%s\": formal parameter %d is " + "procedure \"%s\": formal parameter %" TCL_SIZE_MODIFIER "u is " "inconsistent with precompiled body", procName, i)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", - "BYTECODELIES", NULL); + "BYTECODELIES", (void *)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); + Tcl_Size tmpLength, valueLength; + const char *tmpPtr = Tcl_GetStringFromObj(localPtr->defValuePtr, &tmpLength); + const char *value = Tcl_GetStringFromObj(fieldValues[1], &valueLength); if ((valueLength != tmpLength) || memcmp(value, tmpPtr, tmpLength) != 0 ) { Tcl_Obj *errorObj = Tcl_ObjPrintf( @@ -612,11 +615,11 @@ Tcl_AppendObjToObj(errorObj, fieldValues[0]); Tcl_AppendToObj(errorObj, "\" has " "default value inconsistent with precompiled body", -1); Tcl_SetObjResult(interp, errorObj); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", - "BYTECODELIES", NULL); + "BYTECODELIES", (void *)NULL); goto procError; } } if ((i == numArgs - 1) && (localPtr->nameLength == 4) @@ -631,11 +634,11 @@ * Allocate an entry in the runtime procedure frame's array of * local variables for the argument. */ localPtr = (CompiledLocal *)Tcl_Alloc( - offsetof(CompiledLocal, name) + fieldValues[0]->length + 1); + offsetof(CompiledLocal, name) + 1U + fieldValues[0]->length); if (procPtr->firstLocalPtr == NULL) { procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr; } else { procPtr->lastLocalPtr->nextPtr = localPtr; procPtr->lastLocalPtr = localPtr; @@ -722,11 +725,11 @@ obj.bytes = (char *) name; obj.length = strlen(name); obj.typePtr = NULL; result = TclObjGetFrame(interp, &obj, framePtrPtr); - TclFreeIntRep(&obj); + TclFreeInternalRep(&obj); return result; } /* *---------------------------------------------------------------------- @@ -760,11 +763,11 @@ CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if * global frame indicated). */ { Interp *iPtr = (Interp *) interp; int curLevel, level, result; - const Tcl_ObjIntRep *irPtr; + const Tcl_ObjInternalRep *irPtr; const char *name = NULL; Tcl_WideInt w; /* * Parse object to figure out which level number to go to. @@ -786,24 +789,24 @@ result = -1; } else { level = curLevel - level; result = 1; } - } else if ((irPtr = TclFetchIntRep(objPtr, &levelReferenceType))) { + } else if ((irPtr = TclFetchInternalRep(objPtr, &levelReferenceType))) { level = irPtr->wideValue; result = 1; } else { name = TclGetString(objPtr); if (name[0] == '#') { if (TCL_OK == Tcl_GetInt(NULL, name+1, &level)) { if (level < 0 || (level > 0 && name[1] == '-')) { result = -1; } else { - Tcl_ObjIntRep ir; + Tcl_ObjInternalRep ir; ir.wideValue = level; - Tcl_StoreIntRep(objPtr, &levelReferenceType, &ir); + Tcl_StoreInternalRep(objPtr, &levelReferenceType, &ir); result = 1; } } else { result = -1; } @@ -828,11 +831,11 @@ } if (level >= 0) { CallFrame *framePtr; for (framePtr = iPtr->varFramePtr; framePtr != NULL; framePtr = framePtr->callerVarPtr) { - if (framePtr->level == level) { + if ((int)framePtr->level == level) { *framePtrPtr = framePtr; return result; } } } @@ -840,11 +843,11 @@ badLevel: if (name == NULL) { name = objPtr ? TclGetString(objPtr) : "1" ; } Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad level \"%s\"", name)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", name, (void *)NULL); return -1; } /* *---------------------------------------------------------------------- @@ -863,11 +866,11 @@ *---------------------------------------------------------------------- */ static int Uplevel_Callback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { CallFrame *savedVarFramePtr = (CallFrame *)data[0]; @@ -884,21 +887,21 @@ return result; } int Tcl_UplevelObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRUplevelObjCmd, clientData, objc, objv); } int TclNRUplevelObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { @@ -917,12 +920,13 @@ */ uplevelSyntax: Tcl_WrongNumArgs(interp, 1, objv, "?level? command ?arg ...?"); return TCL_ERROR; } else if (!TclHasStringRep(objv[1]) && objc == 2) { - int status ,llength; - status = Tcl_ListObjLength(interp, objv[1], &llength); + int status; + Tcl_Size llength; + status = TclListObjLengthM(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) { @@ -1062,11 +1066,11 @@ Tcl_Interp *interp, int skip) { CallFrame *framePtr = ((Interp *)interp)->varFramePtr; Proc *procPtr = framePtr->procPtr; - int localCt = procPtr->numCompiledLocals, numArgs, i; + Tcl_Size localCt = procPtr->numCompiledLocals, numArgs, i; Tcl_Obj **desiredObjs; const char *final = NULL; /* * Build up desired argument list for Tcl_WrongNumArgs @@ -1082,19 +1086,19 @@ desiredObjs[0] = framePtr->objv[skip-1]; } Tcl_IncrRefCount(desiredObjs[0]); if (localCt > 0) { - Var *defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt); + Var *defPtr = (Var *)(&framePtr->localCachePtr->varName0 + localCt); for (i=1 ; i<=numArgs ; i++, defPtr++) { Tcl_Obj *argObj; Tcl_Obj *namePtr = localName(framePtr, i-1); if (defPtr->value.objPtr != NULL) { TclNewObj(argObj); - Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?", NULL); + Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?", (void *)NULL); } else if (defPtr->flags & VAR_IS_ARGS) { numArgs--; final = "?arg ...?"; break; } else { @@ -1244,11 +1248,11 @@ void TclFreeLocalCache( Tcl_Interp *interp, LocalCache *localCachePtr) { - int i; + Tcl_Size i; Tcl_Obj **namePtrPtr = &localCachePtr->varName0; for (i = 0; i < localCachePtr->numVars; i++, namePtrPtr++) { Tcl_Obj *objPtr = *namePtrPtr; @@ -1264,20 +1268,19 @@ InitLocalCache( Proc *procPtr) { Interp *iPtr = procPtr->iPtr; ByteCode *codePtr; - int localCt = procPtr->numCompiledLocals; - int numArgs = procPtr->numArgs, i = 0; + Tcl_Size localCt = procPtr->numCompiledLocals; + Tcl_Size numArgs = procPtr->numArgs, i = 0; Tcl_Obj **namePtr; Var *varPtr; LocalCache *localCachePtr; CompiledLocal *localPtr; - int isNew; - ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr); /* * Cache the names and initial values of local variables; store the * cache in both the framePtr for this execution and in the codePtr * for future calls. @@ -1292,13 +1295,12 @@ 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); + *namePtr = TclCreateLiteral(iPtr, + localPtr->name, localPtr->nameLength); Tcl_IncrRefCount(*namePtr); } if (i < numArgs) { varPtr->flags = (localPtr->flags & VAR_IS_ARGS); @@ -1343,14 +1345,14 @@ { CallFrame *framePtr = ((Interp *)interp)->varFramePtr; Proc *procPtr = framePtr->procPtr; ByteCode *codePtr; Var *varPtr, *defPtr; - int localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax; + Tcl_Size localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax; Tcl_Obj *const *argObjs; - ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr); /* * Make sure that the local cache of variable names and initial values has * been initialised properly . */ @@ -1384,18 +1386,18 @@ */ numArgs = procPtr->numArgs; argCt = framePtr->objc - skip; /* Set it to the number of args to the * procedure. */ - argObjs = framePtr->objv + skip; if (numArgs == 0) { if (argCt) { goto incorrectArgs; } else { goto correctArgs; } } + argObjs = framePtr->objv + skip; imax = ((argCt < numArgs-1) ? argCt : numArgs-1); for (i = 0; i < imax; i++, varPtr++, defPtr ? defPtr++ : defPtr) { /* * "Normal" arguments; last formal is special, depends on it being * 'args'. @@ -1428,11 +1430,11 @@ * defPtr and varPtr point to the last argument to be initialized. */ varPtr->flags = 0; if (defPtr && defPtr->flags & VAR_IS_ARGS) { - Tcl_Obj *listPtr = Tcl_NewListObj(argCt-i, argObjs+i); + Tcl_Obj *listPtr = Tcl_NewListObj((argCt>i)? argCt-i : 0, argObjs+i); varPtr->value.objPtr = listPtr; Tcl_IncrRefCount(listPtr); /* Local var is a reference. */ } else if (argCt == numArgs) { Tcl_Obj *objPtr = argObjs[i]; @@ -1498,15 +1500,15 @@ *---------------------------------------------------------------------- */ int TclPushProcCallFrame( - ClientData clientData, /* Record describing procedure to be + void *clientData, /* Record describing procedure to be * interpreted. */ Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ - int objc, /* Count of number of arguments to this + Tcl_Size objc, /* Count of number of arguments to this * procedure. */ Tcl_Obj *const objv[], /* Argument value objects. */ int isLambda) /* 1 if this is a call by ApplyObjCmd: it * needs special rules for error msg */ { @@ -1522,11 +1524,11 @@ * slots for the procedure's non-argument local variables. Note that * compiling the body might increase procPtr->numCompiledLocals if new * local variables are found while compiling. */ - ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr); if (codePtr != NULL) { Interp *iPtr = (Interp *) interp; /* * When we've got bytecode, this is the check for validity. That is, @@ -1533,16 +1535,19 @@ * the bytecode must be for the right interpreter (no cross-leaks!), * the code must be from the current epoch (so subcommand compilation * is up-to-date), the namespace must match (so variable handling * is right) and the resolverEpoch must match (so that new shadowed * commands and/or resolver changes are considered). + * Ensure the ByteCode's procPtr is the same (or it's precompiled). */ if (((Interp *) *codePtr->interpHandle != iPtr) || (codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsPtr != nsPtr) - || (codePtr->nsEpoch != nsPtr->resolverEpoch)) { + || (codePtr->nsEpoch != nsPtr->resolverEpoch) + || ((codePtr->procPtr != procPtr) && procPtr->bodyPtr->bytes) + ) { goto doCompilation; } } else { doCompilation: result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr, @@ -1590,11 +1595,11 @@ *---------------------------------------------------------------------- */ int TclObjInterpProc( - ClientData clientData, /* Record describing procedure to be + void *clientData, /* Record describing procedure to be * interpreted. */ Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ int objc, /* Count of number of arguments to this * procedure. */ @@ -1602,20 +1607,39 @@ { /* * Not used much in the core; external interface for iTcl */ - return Tcl_NRCallObjProc(interp, TclNRInterpProc, clientData, objc, objv); + return Tcl_NRCallObjProc(interp, NRInterpProc, clientData, objc, objv); } int TclNRInterpProc( - ClientData clientData, /* Record describing procedure to be + void *clientData, /* Record describing procedure to be * interpreted. */ Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ - int objc, /* Count of number of arguments to this + Tcl_Size objc, /* Count of number of arguments to this + * procedure. */ + Tcl_Obj *const objv[]) /* Argument value objects. */ +{ + int 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); @@ -1623,10 +1647,28 @@ 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 -- @@ -1647,11 +1689,11 @@ 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, + 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; @@ -1671,11 +1713,11 @@ } #if defined(TCL_COMPILE_DEBUG) if (tclTraceExec >= 1) { CallFrame *framePtr = iPtr->varFramePtr; - int i; + Tcl_Size i; if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) { fprintf(stdout, "Calling lambda "); } else { fprintf(stdout, "Calling proc "); @@ -1689,13 +1731,13 @@ } #endif /*TCL_COMPILE_DEBUG*/ #ifdef USE_DTRACE if (TCL_DTRACE_PROC_ARGS_ENABLED()) { - int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; + Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; const char *a[10]; - int i; + Tcl_Size i; for (i = 0 ; i < 10 ; i++) { a[i] = (l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL); l++; @@ -1710,19 +1752,19 @@ TclDTraceInfo(info, a, i); TCL_DTRACE_PROC_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]); TclDecrRefCount(info); } if (TCL_DTRACE_PROC_ENTRY_ENABLED()) { - int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; + Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; TCL_DTRACE_PROC_ENTRY(l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL, iPtr->varFramePtr->objc - l - 1, (Tcl_Obj **)(iPtr->varFramePtr->objv + l + 1)); } if (TCL_DTRACE_PROC_ENTRY_ENABLED()) { - int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; + Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; TCL_DTRACE_PROC_ENTRY(l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL, iPtr->varFramePtr->objc - l - 1, (Tcl_Obj **)(iPtr->varFramePtr->objv + l + 1)); @@ -1732,20 +1774,20 @@ /* * Invoke the commands in the procedure's body. */ procPtr->refCount++; - ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr); TclNRAddCallback(interp, InterpProcNR2, procNameObj, errorProc, NULL, NULL); return TclNRExecuteByteCode(interp, codePtr); } static int InterpProcNR2( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Proc *procPtr = iPtr->varFramePtr->procPtr; @@ -1752,11 +1794,11 @@ CallFrame *freePtr; Tcl_Obj *procNameObj = (Tcl_Obj *)data[0]; ProcErrorProc *errorProc = (ProcErrorProc *)data[1]; if (TCL_DTRACE_PROC_RETURN_ENABLED()) { - int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; + Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; TCL_DTRACE_PROC_RETURN(l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result); } if (procPtr->refCount-- <= 1) { @@ -1775,11 +1817,11 @@ goto process; } done: if (TCL_DTRACE_PROC_RESULT_ENABLED()) { - int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; + Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; Tcl_Obj *r = Tcl_GetObjResult(interp); TCL_DTRACE_PROC_RESULT(l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result, TclGetString(r), r); @@ -1814,11 +1856,11 @@ */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invoked \"%s\" outside of a loop", ((result == TCL_BREAK) ? "break" : "continue"))); - Tcl_SetErrorCode(interp, "TCL", "RESULT", "UNEXPECTED", NULL); + Tcl_SetErrorCode(interp, "TCL", "RESULT", "UNEXPECTED", (void *)NULL); result = TCL_ERROR; /* FALLTHRU */ case TCL_ERROR: @@ -1866,11 +1908,11 @@ { Interp *iPtr = (Interp *) interp; Tcl_CallFrame *framePtr; ByteCode *codePtr; - ByteCodeGetIntRep(bodyPtr, &tclByteCodeType, codePtr); + ByteCodeGetInternalRep(bodyPtr, &tclByteCodeType, codePtr); /* * If necessary, compile the procedure's body. The compiler will allocate * frame slots for the procedure's non-argument local variables. If the * ByteCode already exists, make sure it hasn't been invalidated by @@ -1878,34 +1920,37 @@ * wrong). Also, if the code was compiled in/for a different interpreter, * we recompile it. Note that compiling the body might increase * procPtr->numCompiledLocals if new local variables are found while * compiling. * + * Ensure the ByteCode's procPtr is the same (or it is pure precompiled). * Precompiled procedure bodies, however, are immutable and therefore they * are not recompiled, even if things have changed. */ if (codePtr != NULL) { if (((Interp *) *codePtr->interpHandle == iPtr) && (codePtr->compileEpoch == iPtr->compileEpoch) && (codePtr->nsPtr == nsPtr) - && (codePtr->nsEpoch == nsPtr->resolverEpoch)) { + && (codePtr->nsEpoch == nsPtr->resolverEpoch) + && ((codePtr->procPtr == procPtr) || !bodyPtr->bytes) + ) { return TCL_OK; } if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) { if ((Interp *) *codePtr->interpHandle != iPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "a precompiled script jumped interps", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", - "CROSSINTERPBYTECODE", NULL); + "CROSSINTERPBYTECODE", (void *)NULL); return TCL_ERROR; } codePtr->compileEpoch = iPtr->compileEpoch; codePtr->nsPtr = nsPtr; } else { - Tcl_StoreIntRep(bodyPtr, &tclByteCodeType, NULL); + Tcl_StoreInternalRep(bodyPtr, &tclByteCodeType, NULL); codePtr = NULL; } } if (codePtr == NULL) { @@ -1920,12 +1965,12 @@ Tcl_Obj *message; TclNewLiteralStringObj(message, "Compiling "); Tcl_IncrRefCount(message); - Tcl_AppendStringsToObj(message, description, " \"", NULL); - Tcl_AppendLimitedToObj(message, procName, -1, 50, NULL); + Tcl_AppendStringsToObj(message, description, " \"", (void *)NULL); + Tcl_AppendLimitedToObj(message, procName, TCL_INDEX_NONE, 50, NULL); fprintf(stdout, "%s\"\n", TclGetString(message)); Tcl_DecrRefCount(message); } #else (void)description; @@ -2030,18 +2075,18 @@ 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); + int overflow, limit = 60; + Tcl_Size nameLen; + const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen); - overflow = (nameLen > limit); + overflow = (nameLen > (Tcl_Size)limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (procedure \"%.*s%s\" line %d)", - (int)(overflow ? limit :nameLen), procName, + (overflow ? limit : (int)nameLen), procName, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } /* *---------------------------------------------------------------------- @@ -2063,11 +2108,11 @@ *---------------------------------------------------------------------- */ void TclProcDeleteProc( - ClientData clientData) /* Procedure to be deleted. */ + void *clientData) /* Procedure to be deleted. */ { Proc *procPtr = (Proc *)clientData; if (procPtr->refCount-- <= 1) { TclProcCleanupProc(procPtr); @@ -2102,10 +2147,17 @@ 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; @@ -2205,30 +2257,37 @@ } /* *---------------------------------------------------------------------- * - * TclGetObjInterpProc -- + * TclGetObjInterpProc/TclGetObjInterpProc2 -- * - * Returns a pointer to the TclObjInterpProc function; this is different - * from the value obtained from the TclObjInterpProc reference on systems - * like Windows where import and export versions of a function exported - * by a DLL exist. + * Returns a pointer to the TclObjInterpProc/ObjInterpProc2 functions; + * this is different from the value obtained from the TclObjInterpProc + * reference on systems like Windows where import and export versions + * of a function exported by a DLL exist. * * Results: - * Returns the internal address of the TclObjInterpProc function. + * Returns the internal address of the TclObjInterpProc/ObjInterpProc2 + * functions. * * Side effects: * None. * *---------------------------------------------------------------------- */ -TclObjCmdProcType +Tcl_ObjCmdProc * TclGetObjInterpProc(void) { - return (TclObjCmdProcType) TclObjInterpProc; + return TclObjInterpProc; +} + +Tcl_ObjCmdProc2 * +TclGetObjInterpProc2(void) +{ + return ObjInterpProc2; } /* *---------------------------------------------------------------------- * @@ -2259,11 +2318,11 @@ return NULL; } TclNewObj(objPtr); if (objPtr) { - ProcSetIntRep(objPtr, procPtr); + ProcSetInternalRep(objPtr, procPtr); } return objPtr; } @@ -2288,13 +2347,13 @@ ProcBodyDup( Tcl_Obj *srcPtr, /* Object to copy. */ Tcl_Obj *dupPtr) /* Target object for the duplication. */ { Proc *procPtr; - ProcGetIntRep(srcPtr, procPtr); + ProcGetInternalRep(srcPtr, procPtr); - ProcSetIntRep(dupPtr, procPtr); + ProcSetInternalRep(dupPtr, procPtr); } /* *---------------------------------------------------------------------- * @@ -2318,11 +2377,11 @@ ProcBodyFree( Tcl_Obj *objPtr) /* The object to clean up. */ { Proc *procPtr; - ProcGetIntRep(objPtr, procPtr); + ProcGetInternalRep(objPtr, procPtr); if (procPtr->refCount-- <= 1) { TclProcCleanupProc(procPtr); } } @@ -2347,16 +2406,16 @@ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { Proc *procPtr; Tcl_Obj *nsObjPtr; - LambdaGetIntRep(srcPtr, procPtr, nsObjPtr); + LambdaGetInternalRep(srcPtr, procPtr, nsObjPtr); assert(procPtr != NULL); procPtr->refCount++; - LambdaSetIntRep(copyPtr, procPtr, nsObjPtr); + LambdaSetInternalRep(copyPtr, procPtr, nsObjPtr); } static void FreeLambdaInternalRep( Tcl_Obj *objPtr) /* CmdName object with internal representation @@ -2363,11 +2422,11 @@ * to free. */ { Proc *procPtr; Tcl_Obj *nsObjPtr; - LambdaGetIntRep(objPtr, procPtr, nsObjPtr); + LambdaGetInternalRep(objPtr, procPtr, nsObjPtr); assert(procPtr != NULL); if (procPtr->refCount-- <= 1) { TclProcCleanupProc(procPtr); } @@ -2380,11 +2439,12 @@ Tcl_Obj *objPtr) /* The object to convert. */ { Interp *iPtr = (Interp *) interp; const char *name; Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv; - int isNew, objc, result; + int isNew, result; + Tcl_Size objc; CmdFrame *cfPtr = NULL; Proc *procPtr; if (interp == NULL) { return TCL_ERROR; @@ -2393,16 +2453,24 @@ /* * 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); + result = TclListObjLengthM(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 = TclListObjGetElementsM(NULL, objPtr, &objc, &objv); if ((result != TCL_OK) || ((objc != 2) && (objc != 3))) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't interpret \"%s\" as a lambda expression", TclGetString(objPtr))); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "LAMBDA", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "LAMBDA", (void *)NULL); return TCL_ERROR; } argsPtr = objv[0]; bodyPtr = objv[1]; @@ -2476,11 +2544,11 @@ * was not created by substitution. */ if (contextPtr->line && (contextPtr->nline >= 2) && (contextPtr->line[1] >= 0)) { - int buf[2]; + Tcl_Size buf[2]; /* * Move from approximation (line of list cmd word) to actual * location (line of 2nd list element). */ @@ -2488,11 +2556,11 @@ cfPtr = (CmdFrame *)Tcl_Alloc(sizeof(CmdFrame)); TclListLines(objPtr, contextPtr->line[1], 2, buf, NULL); cfPtr->level = -1; cfPtr->type = contextPtr->type; - cfPtr->line = (int *)Tcl_Alloc(sizeof(int)); + cfPtr->line = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size)); cfPtr->line[0] = buf[1]; cfPtr->nline = 1; cfPtr->framePtr = NULL; cfPtr->nextPtr = NULL; @@ -2537,11 +2605,11 @@ * Free the list internalrep of objPtr - this will free argsPtr, but * bodyPtr retains a reference from the Proc structure. Then finish the * conversion to lambdaType. */ - LambdaSetIntRep(objPtr, procPtr, nsObjPtr); + LambdaSetInternalRep(objPtr, procPtr, nsObjPtr); return TCL_OK; } Proc * TclGetLambdaFromObj( @@ -2550,17 +2618,17 @@ Tcl_Obj **nsObjPtrPtr) { Proc *procPtr; Tcl_Obj *nsObjPtr; - LambdaGetIntRep(objPtr, procPtr, nsObjPtr); + LambdaGetInternalRep(objPtr, procPtr, nsObjPtr); if (procPtr == NULL) { if (SetLambdaFromAny(interp, objPtr) != TCL_OK) { return NULL; } - LambdaGetIntRep(objPtr, procPtr, nsObjPtr); + LambdaGetInternalRep(objPtr, procPtr, nsObjPtr); } assert(procPtr != NULL); if (procPtr->iPtr != (Interp *)interp) { return NULL; @@ -2587,21 +2655,21 @@ *---------------------------------------------------------------------- */ int Tcl_ApplyObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRApplyObjCmd, clientData, objc, objv); } int TclNRApplyObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Proc *procPtr = NULL; @@ -2666,11 +2734,11 @@ return result; } static int ApplyNR2( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { ApplyExtraData *extraPtr = (ApplyExtraData *)data[0]; @@ -2701,18 +2769,18 @@ 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); + int overflow, limit = 60; + Tcl_Size nameLen; + const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen); - overflow = (nameLen > limit); + overflow = (nameLen > (Tcl_Size)limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (lambda term \"%.*s%s\" line %d)", - (int)(overflow ? limit : nameLen), procName, + (overflow ? limit : (int)nameLen), procName, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } /* *---------------------------------------------------------------------- Index: generic/tclProcess.c ================================================================== --- generic/tclProcess.c +++ generic/tclProcess.c @@ -2,11 +2,11 @@ * tclProcess.c -- * * This file implements the "tcl::process" ensemble for subprocess * management as defined by TIP #462. * - * Copyright (c) 2017 Frederic Bonnet. + * Copyright © 2017 Frederic Bonnet. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -49,22 +49,14 @@ 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[]); +static Tcl_ObjCmdProc ProcessListObjCmd; +static Tcl_ObjCmdProc ProcessStatusObjCmd; +static Tcl_ObjCmdProc ProcessPurgeObjCmd; +static Tcl_ObjCmdProc ProcessAutopurgeObjCmd; /* *---------------------------------------------------------------------- * * InitProcessInfo -- @@ -400,11 +392,11 @@ *---------------------------------------------------------------------- */ static int ProcessListObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *list; @@ -451,32 +443,31 @@ *---------------------------------------------------------------------- */ static int ProcessStatusObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *dict; - int index, options = WNOHANG; + int options = WNOHANG; Tcl_HashEntry *entry; Tcl_HashSearch search; ProcessInfo *info; - int numPids; + Tcl_Size i, numPids; Tcl_Obj **pidObjs; int result; - int i; int pid; Tcl_Obj *const *savedobjv = objv; static const char *const switches[] = { "-wait", "--", NULL }; enum switchesEnum { STATUS_WAIT, STATUS_LAST - }; + } index; while (objc > 1) { if (TclGetString(objv[1])[0] != '-') { break; } @@ -483,11 +474,11 @@ if (Tcl_GetIndexFromObj(interp, objv[1], switches, "switches", 0, &index) != TCL_OK) { return TCL_ERROR; } ++objv; --objc; - if (STATUS_WAIT == (enum switchesEnum) index) { + if (STATUS_WAIT == index) { options = 0; } else { break; } } @@ -531,11 +522,11 @@ } else { /* * Only return statuses of provided processes. */ - result = Tcl_ListObjGetElements(interp, objv[1], &numPids, &pidObjs); + result = TclListObjGetElementsM(interp, objv[1], &numPids, &pidObjs); if (result != TCL_OK) { return result; } dict = Tcl_NewDictObj(); Tcl_MutexLock(&infoTablesMutex); @@ -599,23 +590,21 @@ *---------------------------------------------------------------------- */ static int ProcessPurgeObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_HashEntry *entry; Tcl_HashSearch search; ProcessInfo *info; - int numPids; + Tcl_Size i, numPids; Tcl_Obj **pidObjs; - int result; - int i; - int pid; + int result, pid; if (objc != 1 && objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "?pids?"); return TCL_ERROR; } @@ -646,11 +635,11 @@ } else { /* * Purge only provided processes. */ - result = Tcl_ListObjGetElements(interp, objv[1], &numPids, &pidObjs); + result = TclListObjGetElementsM(interp, objv[1], &numPids, &pidObjs); if (result != TCL_OK) { return result; } Tcl_MutexLock(&infoTablesMutex); for (i = 0; i < numPids; i++) { @@ -699,11 +688,11 @@ *---------------------------------------------------------------------- */ static int ProcessAutopurgeObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Index: generic/tclRegexp.c ================================================================== --- generic/tclRegexp.c +++ generic/tclRegexp.c @@ -2,19 +2,20 @@ * tclRegexp.c -- * * This file contains the public interfaces to the Tcl regular expression * mechanism. * - * Copyright (c) 1998 by Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1998 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclRegexp.h" +#include "tclTomMath.h" #include /* *---------------------------------------------------------------------- * The routines in this file use Henry Spencer's regular expression package @@ -24,11 +25,11 @@ * regc_nfa.c regcomp.c regcustom.h * rege_dfa.c regerror.c regerrs.h * regex.h regexec.c regfree.c * regfronts.c regguts.h * - * Copyright (c) 1998 Henry Spencer. All rights reserved. + * Copyright © 1998 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. @@ -86,11 +87,11 @@ static TclRegexp * CompileRegexp(Tcl_Interp *interp, const char *pattern, size_t length, int flags); static void DupRegexpInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); -static void FinalizeRegexp(ClientData clientData); +static void FinalizeRegexp(void *clientData); static void FreeRegexp(TclRegexp *regexpPtr); static void FreeRegexpInternalRep(Tcl_Obj *objPtr); static int RegExpExecUniChar(Tcl_Interp *interp, Tcl_RegExp re, const Tcl_UniChar *uniString, size_t numChars, size_t nmatches, int flags); @@ -104,26 +105,27 @@ const Tcl_ObjType tclRegexpType = { "regexp", /* name */ FreeRegexpInternalRep, /* freeIntRepProc */ DupRegexpInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetRegexpFromAny /* setFromAnyProc */ + SetRegexpFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; -#define RegexpSetIntRep(objPtr, rePtr) \ +#define RegexpSetInternalRep(objPtr, rePtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ (rePtr)->refCount++; \ ir.twoPtrValue.ptr1 = (rePtr); \ ir.twoPtrValue.ptr2 = NULL; \ - Tcl_StoreIntRep((objPtr), &tclRegexpType, &ir); \ + Tcl_StoreInternalRep((objPtr), &tclRegexpType, &ir); \ } while (0) -#define RegexpGetIntRep(objPtr, rePtr) \ +#define RegexpGetInternalRep(objPtr, rePtr) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), &tclRegexpType); \ + const Tcl_ObjInternalRep *irPtr; \ + irPtr = TclFetchInternalRep((objPtr), &tclRegexpType); \ (rePtr) = irPtr ? (TclRegexp *)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* @@ -153,11 +155,11 @@ Tcl_Interp *interp, /* For use in error reporting and to access * the interp regexp cache. */ const char *pattern) /* String for which to produce compiled * regular expression. */ { - return (Tcl_RegExp) CompileRegexp(interp, pattern, (int) strlen(pattern), + return (Tcl_RegExp) CompileRegexp(interp, pattern, strlen(pattern), REG_ADVANCED); } /* *---------------------------------------------------------------------- @@ -217,13 +219,13 @@ /* * Convert the string to Unicode and perform the match. */ Tcl_DStringInit(&ds); - ustr = Tcl_UtfToUniCharDString(text, -1, &ds); + ustr = Tcl_UtfToUniCharDString(text, TCL_INDEX_NONE, &ds); numChars = Tcl_DStringLength(&ds) / sizeof(Tcl_UniChar); - result = RegExpExecUniChar(interp, re, ustr, numChars, -1 /* nmatches */, + result = RegExpExecUniChar(interp, re, ustr, numChars, TCL_INDEX_NONE /* nmatches */, flags); Tcl_DStringFree(&ds); return result; } @@ -249,11 +251,11 @@ void Tcl_RegExpRange( Tcl_RegExp re, /* Compiled regular expression that has been * passed to Tcl_RegExpExec. */ - size_t index, /* 0 means give the range of the entire match, + Tcl_Size index, /* 0 means give the range of the entire match, * > 0 means give the range of a matching * subrange. */ const char **startPtr, /* Store address of first character in * (sub-)range here. */ const char **endPtr) /* Store address of character just after last @@ -260,13 +262,13 @@ * in (sub-)range here. */ { TclRegexp *regexpPtr = (TclRegexp *) re; const char *string; - if (index > regexpPtr->re.re_nsub) { + if (index < 0 || (size_t) index > regexpPtr->re.re_nsub) { *startPtr = *endPtr = NULL; - } else if (regexpPtr->matches[index].rm_so == TCL_INDEX_NONE) { + } else if (regexpPtr->matches[index].rm_so == (size_t) -1) { *startPtr = *endPtr = NULL; } else { if (regexpPtr->objPtr) { string = TclGetString(regexpPtr->objPtr); } else { @@ -359,27 +361,27 @@ void TclRegExpRangeUniChar( Tcl_RegExp re, /* Compiled regular expression that has been * passed to Tcl_RegExpExec. */ - size_t index, /* 0 means give the range of the entire match, + Tcl_Size index, /* 0 means give the range of the entire match, * > 0 means give the range of a matching - * subrange, TCL_INDEX_NONE means the range of the + * subrange, -1 means the range of the * rm_extend field. */ - size_t *startPtr, /* Store address of first character in + Tcl_Size *startPtr, /* Store address of first character in * (sub-)range here. */ - size_t *endPtr) /* Store address of character just after last + Tcl_Size *endPtr) /* Store address of character just after last * in (sub-)range here. */ { TclRegexp *regexpPtr = (TclRegexp *) re; - if ((regexpPtr->flags®_EXPECT) && (index == TCL_INDEX_NONE)) { + if ((regexpPtr->flags®_EXPECT) && (index == -1)) { *startPtr = regexpPtr->details.rm_extend.rm_so; *endPtr = regexpPtr->details.rm_extend.rm_eo; - } else if (index + 1 > regexpPtr->re.re_nsub + 1) { - *startPtr = TCL_INDEX_NONE; - *endPtr = TCL_INDEX_NONE; + } else if (index < 0 || (size_t) index > regexpPtr->re.re_nsub + 1) { + *startPtr = -1; + *endPtr = -1; } else { *startPtr = regexpPtr->matches[index].rm_so; *endPtr = regexpPtr->matches[index].rm_eo; } } @@ -439,20 +441,20 @@ Tcl_Interp *interp, /* Interpreter to use for error reporting. */ Tcl_RegExp re, /* Compiled regular expression; must have been * returned by previous call to * Tcl_GetRegExpFromObj. */ Tcl_Obj *textObj, /* Text against which to match re. */ - size_t offset, /* Character index that marks where matching + Tcl_Size offset, /* Character index that marks where matching * should begin. */ - size_t nmatches, /* How many subexpression matches (counting + Tcl_Size nmatches, /* How many subexpression matches (counting * the whole match as subexpression 0) are of * interest. -1 means all of them. */ int flags) /* Regular expression execution flags. */ { TclRegexp *regexpPtr = (TclRegexp *) re; Tcl_UniChar *udata; - size_t length; + Tcl_Size length; int reflags = regexpPtr->flags; #define TCL_REG_GLOBOK_FLAGS \ (TCL_REG_ADVANCED | TCL_REG_NOSUB | TCL_REG_NOCASE) /* @@ -479,11 +481,11 @@ */ regexpPtr->string = NULL; regexpPtr->objPtr = textObj; - udata = TclGetUnicodeFromObj(textObj, &length); + udata = Tcl_GetUnicodeFromObj(textObj, &length); if (offset > length) { offset = length; } udata += offset; @@ -591,25 +593,25 @@ * expression pattern. Internal rep will be * changed to compiled form of this regular * expression. */ int flags) /* Regular expression compilation flags. */ { - size_t length; + Tcl_Size length; TclRegexp *regexpPtr; const char *pattern; - RegexpGetIntRep(objPtr, regexpPtr); + RegexpGetInternalRep(objPtr, regexpPtr); if ((regexpPtr == NULL) || (regexpPtr->flags != flags)) { - pattern = TclGetStringFromObj(objPtr, &length); + pattern = Tcl_GetStringFromObj(objPtr, &length); regexpPtr = CompileRegexp(interp, pattern, length, flags); if (regexpPtr == NULL) { return NULL; } - RegexpSetIntRep(objPtr, regexpPtr); + RegexpSetInternalRep(objPtr, regexpPtr); } return (Tcl_RegExp) regexpPtr; } /* @@ -726,13 +728,13 @@ Tcl_ResetResult(interp); n = TclReError(status, buf, sizeof(buf)); p = (n > sizeof(buf)) ? "..." : ""; Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s%s%s", msg, buf, p)); - sprintf(cbuf, "%d", status); + snprintf(cbuf, sizeof(cbuf), "%d", status); (void) TclReError(REG_ITOA, cbuf, sizeof(cbuf)); - Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, NULL); + Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, (void *)NULL); } /* *---------------------------------------------------------------------- * @@ -754,11 +756,11 @@ FreeRegexpInternalRep( Tcl_Obj *objPtr) /* Regexp object with internal rep to free. */ { TclRegexp *regexpRepPtr; - RegexpGetIntRep(objPtr, regexpRepPtr); + RegexpGetInternalRep(objPtr, regexpRepPtr); assert(regexpRepPtr != NULL); /* * If this is the last reference to the regexp, free it. @@ -791,15 +793,15 @@ Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { TclRegexp *regexpPtr; - RegexpGetIntRep(srcPtr, regexpPtr); + RegexpGetInternalRep(srcPtr, regexpPtr); assert(regexpPtr != NULL); - RegexpSetIntRep(copyPtr, regexpPtr); + RegexpSetInternalRep(copyPtr, regexpPtr); } /* *---------------------------------------------------------------------- * @@ -916,12 +918,12 @@ */ regexpPtr = (TclRegexp*)Tcl_Alloc(sizeof(TclRegexp)); regexpPtr->objPtr = NULL; regexpPtr->string = NULL; - regexpPtr->details.rm_extend.rm_so = -1; - regexpPtr->details.rm_extend.rm_eo = -1; + regexpPtr->details.rm_extend.rm_so = TCL_INDEX_NONE; + regexpPtr->details.rm_extend.rm_eo = TCL_INDEX_NONE; /* * Get the up-to-date string representation and map to unicode. */ @@ -956,11 +958,11 @@ * Tcl_RegExpExecObj to optionally do a fast match (avoids RE engine). */ if (TclReToGlob(NULL, string, length, &stringBuf, &exact, NULL) == TCL_OK) { - regexpPtr->globObjPtr = TclDStringToObj(&stringBuf); + regexpPtr->globObjPtr = Tcl_DStringToObj(&stringBuf); Tcl_IncrRefCount(regexpPtr->globObjPtr); } else { regexpPtr->globObjPtr = NULL; } @@ -1050,11 +1052,11 @@ *---------------------------------------------------------------------- */ static void FinalizeRegexp( - TCL_UNUSED(ClientData)) + TCL_UNUSED(void *)) { int i; TclRegexp *regexpPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Index: generic/tclResolve.c ================================================================== --- generic/tclResolve.c +++ generic/tclResolve.c @@ -4,11 +4,11 @@ * Contains hooks for customized command/variable name resolution * schemes. These hooks allow extensions like [incr Tcl] to add their own * name resolution rules to the Tcl language. Rules can be applied to a * particular namespace, to the interpreter as a whole, or both. * - * Copyright (c) 1998 Lucent Technologies, Inc. + * Copyright © 1998 Lucent Technologies, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tclResult.c ================================================================== --- generic/tclResult.c +++ generic/tclResult.c @@ -1,17 +1,18 @@ /* * tclResult.c -- * * This file contains code to manage the interpreter result. * - * Copyright (c) 1997 by Sun Microsystems, Inc. + * Copyright © 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" +#include /* * Indices of the standard return options dictionary keys. */ @@ -23,11 +24,11 @@ /* * Function prototypes for local functions in this file: */ static Tcl_Obj ** GetKeys(void); -static void ReleaseKeys(ClientData clientData); +static void ReleaseKeys(void *clientData); static void ResetObjResult(Interp *iPtr); /* * This structure is used to take a snapshot of the interpreter state in * Tcl_SaveInterpState. You can snapshot the state, execute a command, and @@ -209,44 +210,40 @@ /* *---------------------------------------------------------------------- * * Tcl_SetObjResult -- - * - * Arrange for objPtr to be an interpreter's result value. + * Makes objPtr the interpreter's result value. * * Results: * None. * * Side effects: - * interp->objResultPtr is left pointing to the object referenced by - * 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. + * 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 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. */ + 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; - - 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); + if (objPtr == oldObjResult) { + /* This should be impossible */ + assert(objPtr->refCount != 0); + return; + } else { + iPtr->objResultPtr = objPtr; + Tcl_IncrRefCount(objPtr); + TclDecrRefCount(oldObjResult); + } } /* *---------------------------------------------------------------------- * @@ -355,16 +352,16 @@ { Interp *iPtr = (Interp *) interp; Tcl_Obj *elementPtr = Tcl_NewStringObj(element, -1); Tcl_Obj *listPtr = Tcl_NewListObj(1, &elementPtr); const char *bytes; - size_t length; + Tcl_Size length; if (Tcl_IsShared(iPtr->objResultPtr)) { Tcl_SetObjResult(interp, Tcl_DuplicateObj(iPtr->objResultPtr)); } - bytes = TclGetStringFromObj(iPtr->objResultPtr, &length); + bytes = Tcl_GetStringFromObj(iPtr->objResultPtr, &length); if (TclNeedSpace(bytes, bytes + length)) { Tcl_AppendToObj(iPtr->objResultPtr, " ", 1); } Tcl_AppendObjToObj(iPtr->objResultPtr, listPtr); Tcl_DecrRefCount(listPtr); @@ -460,11 +457,11 @@ Tcl_Free(objResultPtr->bytes); } objResultPtr->bytes = &tclEmptyString; objResultPtr->length = 0; } - TclFreeIntRep(objResultPtr); + TclFreeInternalRep(objResultPtr); } } /* *---------------------------------------------------------------------- @@ -496,11 +493,11 @@ * Scan through the arguments one at a time, appending them to the * errorCode field as list elements. */ va_start(argList, interp); - errorObj = Tcl_NewObj(); + TclNewObj(errorObj); /* * Scan through the arguments one at a time, appending them to the * errorCode field as list elements. */ @@ -657,11 +654,11 @@ *---------------------------------------------------------------------- */ static void ReleaseKeys( - ClientData clientData) + void *clientData) { Tcl_Obj **keys = (Tcl_Obj **)clientData; int i; for (i = KEY_CODE; i < KEY_LAST; i++) { @@ -719,23 +716,23 @@ iPtr->errorInfo = NULL; } Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO], &valuePtr); if (valuePtr != NULL) { - size_t length; + Tcl_Size length; - (void) TclGetStringFromObj(valuePtr, &length); + (void) Tcl_GetStringFromObj(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_Size len, valueObjc; Tcl_Obj **valueObjv; if (Tcl_IsShared(iPtr->errorStack)) { Tcl_Obj *newObj; @@ -748,19 +745,19 @@ /* * List extraction done after duplication to avoid moving the rug * if someone does [return -errorstack [info errorstack]] */ - if (Tcl_ListObjGetElements(interp, valuePtr, &valueObjc, + if (TclListObjGetElementsM(interp, valuePtr, &valueObjc, &valueObjv) == TCL_ERROR) { return TCL_ERROR; } iPtr->resetErrorStack = 0; - Tcl_ListObjLength(interp, iPtr->errorStack, &len); + TclListObjLengthM(interp, iPtr->errorStack, &len); /* - * Reset while keeping the list intrep as much as possible. + * Reset while keeping the list internalrep as much as possible. */ Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, valueObjc, valueObjv); } @@ -767,11 +764,11 @@ Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE], &valuePtr); if (valuePtr != NULL) { Tcl_SetObjErrorCode(interp, valuePtr); } else { - Tcl_SetErrorCode(interp, "NONE", NULL); + Tcl_SetErrorCode(interp, "NONE", (void *)NULL); } Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE], &valuePtr); if (valuePtr != NULL) { @@ -847,11 +844,11 @@ 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); + (void *)NULL); goto error; } while (!done) { Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr); @@ -896,11 +893,11 @@ */ 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); + Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_LEVEL", (void *)NULL); goto error; } Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_LEVEL]); } @@ -908,22 +905,22 @@ * Check for bogus -errorcode value. */ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORCODE], &valuePtr); if (valuePtr != NULL) { - int length; + Tcl_Size length; - if (TCL_ERROR == Tcl_ListObjLength(NULL, valuePtr, &length )) { + if (TCL_ERROR == TclListObjLengthM(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); + (void *)NULL); goto error; } } /* @@ -930,22 +927,22 @@ * Check for bogus -errorstack value. */ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORSTACK], &valuePtr); if (valuePtr != NULL) { - int length; + Tcl_Size length; - if (TCL_ERROR == Tcl_ListObjLength(NULL, valuePtr, &length )) { + if (TCL_ERROR == TclListObjLengthM(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); + (void *)NULL); goto error; } if (length % 2) { /* * Errorstack must always be an even-sized list @@ -953,11 +950,11 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "forbidden odd-sized list for -errorstack: \"%s\"", TclGetString(valuePtr))); Tcl_SetErrorCode(interp, "TCL", "RESULT", - "ODDSIZEDLIST_ERRORSTACK", NULL); + "ODDSIZEDLIST_ERRORSTACK", (void *)NULL); goto error; } } /* @@ -1098,19 +1095,20 @@ int Tcl_SetReturnOptions( Tcl_Interp *interp, Tcl_Obj *options) { - int objc, level, code; + Tcl_Size objc; + int level, code; Tcl_Obj **objv, *mergedOpts; Tcl_IncrRefCount(options); - if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv) + if (TCL_ERROR == TclListObjGetElementsM(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); + 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 { Index: generic/tclScan.c ================================================================== --- generic/tclScan.c +++ generic/tclScan.c @@ -1,18 +1,19 @@ /* * tclScan.c -- * * This file contains the implementation of the "scan" command. * - * Copyright (c) 1998 by Scriptics Corporation. + * Copyright © 1998 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclTomMath.h" +#include /* * Flag values used by Tcl_ScanObjCmd. */ @@ -256,11 +257,11 @@ int numVars, /* The number of variables passed to the scan * command. */ int *totalSubs) /* The number of variables that will be * required. */ { - int gotXpg, gotSequential, value, i, flags; + int gotXpg, gotSequential, i, flags; char *end; Tcl_UniChar ch = 0; int objIndex, xpgSize, nspace = numVars; int *nassign = (int *)TclStackAlloc(interp, nspace * sizeof(int)); Tcl_Obj *errorMsg; /* Place to build an error messages. Note that @@ -304,31 +305,37 @@ * 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. */ + /* 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; } - objIndex = value - 1; - if ((objIndex < 0) || (numVars && (objIndex >= numVars))) { + /* >=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) { + } + else if (numVars == 0) { /* * In the case where no vars are specified, the user can * specify %9999$ legally, so we have to consider special - * rules for growing the assign array. 'value' is guaranteed - * to be > 0. + * rules for growing the assign array. 'ull' is guaranteed + * to be > 0 and < INT_MAX as per checks above. */ - xpgSize = (xpgSize > value) ? xpgSize : value; + xpgSize = (xpgSize > (int)ull) ? xpgSize : (int)ull; } goto xpgCheckDone; } notXpg: @@ -336,21 +343,36 @@ if (gotXpg) { mixedXPG: Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot mix \"%\" and \"%n$\" conversion specifiers", -1)); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "MIXEDSPECTYPES", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "MIXEDSPECTYPES", (void *)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. */ + /* 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); } /* @@ -385,11 +407,11 @@ case 'c': if (flags & SCAN_WIDTH) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "field width may not be specified in %c conversion", -1)); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADWIDTH", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADWIDTH", (void *)NULL); goto error; } /* FALLTHRU */ case 'n': case 's': @@ -399,11 +421,11 @@ errorMsg = Tcl_NewStringObj( "field size modifier may not be specified in %", -1); Tcl_AppendToObj(errorMsg, buf, -1); Tcl_AppendToObj(errorMsg, " conversion", -1); Tcl_SetObjResult(interp, errorMsg); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADSIZE", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADSIZE", (void *)NULL); goto error; } /* * Fall through! */ @@ -451,20 +473,20 @@ } break; badSet: Tcl_SetObjResult(interp, Tcl_NewStringObj( "unmatched [ in format string", -1)); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BRACKET", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BRACKET", (void *)NULL); goto error; default: buf[Tcl_UniCharToUtf(ch, buf)] = '\0'; errorMsg = Tcl_NewStringObj( "bad scan conversion character \"", -1); Tcl_AppendToObj(errorMsg, buf, -1); Tcl_AppendToObj(errorMsg, "\"", -1); Tcl_SetObjResult(interp, errorMsg); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", (void *)NULL); goto error; } if (!(flags & SCAN_SUPPRESS)) { if (objIndex >= nspace) { /* @@ -471,19 +493,19 @@ * Expand the nassign buffer. If we are using XPG specifiers, * make sure that we grow to a large enough size. xpgSize is * guaranteed to be at least one larger than objIndex. */ - value = nspace; + int nspaceOrig = nspace; if (xpgSize) { nspace = xpgSize; } else { nspace += 16; /* formerly STATIC_LIST_SIZE */ } nassign = (int *)TclStackRealloc(interp, nassign, nspace * sizeof(int)); - for (i = value; i < nspace; i++) { + for (i = nspaceOrig; i < nspace; i++) { nassign[i] = 0; } } nassign[objIndex]++; objIndex++; @@ -507,11 +529,11 @@ for (i = 0; i < numVars; i++) { if (nassign[i] > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "variable is assigned by multiple \"%n$\" conversion specifiers", -1)); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "POLYASSIGNED", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "POLYASSIGNED", (void *)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 @@ -518,11 +540,11 @@ */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "variable is not assigned by any conversion specifiers", -1)); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "UNASSIGNED", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "UNASSIGNED", (void *)NULL); goto error; } } TclStackFree(interp, nassign); @@ -530,16 +552,16 @@ badIndex: if (gotXpg) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"%n$\" argument index out of range", -1)); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "INDEXRANGE", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "INDEXRANGE", (void *)NULL); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj( "different numbers of variable names and field specifiers", -1)); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "FIELDVARMISMATCH", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "FIELDVARMISMATCH", (void *)NULL); } error: TclStackFree(interp, nassign); return TCL_ERROR; @@ -562,11 +584,11 @@ *---------------------------------------------------------------------- */ int Tcl_ScanObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *format; @@ -573,11 +595,12 @@ 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; + int underflow = 0; + Tcl_Size width; Tcl_WideInt wideValue; Tcl_UniChar ch = 0, sch = 0; Tcl_Obj **objs = NULL, *objPtr = NULL; int flags; @@ -668,10 +691,11 @@ 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; @@ -681,11 +705,14 @@ /* * Parse any width specifier. */ if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ - width = (int) strtoul(format-1, (char **) &format, 10);/* 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; } @@ -874,11 +901,11 @@ case 'c': /* * Scan a single Unicode character. */ - offset = TclUtfToUCS4(string, &i); + offset = Tcl_UtfToUniChar(string, &i); string += offset; if (!(flags & SCAN_SUPPRESS)) { TclNewIntObj(objPtr, i); Tcl_IncrRefCount(objPtr); CLANG_ASSERT(objs); @@ -914,21 +941,22 @@ 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; + } else { + wideValue = WIDE_MAX; } } if ((flags & SCAN_UNSIGNED) && (wideValue < 0)) { mp_int big; if (mp_init_u64(&big, (Tcl_WideUInt)wideValue) != MP_OKAY) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "insufficient memory to create bignum", -1)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); return TCL_ERROR; } else { Tcl_SetBignumObj(objPtr, &big); } } else { @@ -952,11 +980,11 @@ } Tcl_DecrRefCount(objPtr); Tcl_SetObjResult(interp, Tcl_NewStringObj( "unsigned bignum scans are invalid", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", - "BADUNSIGNED",NULL); + "BADUNSIGNED", (void *)NULL); return TCL_ERROR; } } } else { if (TclGetLongFromObj(NULL, objPtr, &value) != TCL_OK) { @@ -970,11 +998,11 @@ #ifdef TCL_WIDE_INT_IS_LONG mp_int big; if (mp_init_u64(&big, (unsigned long)value) != MP_OKAY) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "insufficient memory to create bignum", -1)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); return TCL_ERROR; } else { Tcl_SetBignumObj(objPtr, &big); } #else @@ -990,11 +1018,11 @@ case 'f': /* * Scan a floating point number */ - objPtr = Tcl_NewDoubleObj(0.0); + TclNewDoubleObj(objPtr, 0.0); Tcl_IncrRefCount(objPtr); if (width == 0) { width = ~0; } if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, string, width, @@ -1015,12 +1043,12 @@ string = end; } else { double dvalue; if (Tcl_GetDoubleFromObj(NULL, objPtr, &dvalue) != TCL_OK) { #ifdef ACCEPT_NAN - const Tcl_ObjIntRep *irPtr - = TclFetchIntRep(objPtr, &tclDoubleType); + const Tcl_ObjInternalRep *irPtr + = TclFetchInternalRep(objPtr, &tclDoubleType); if (irPtr) { dvalue = irPtr->doubleValue; } else #endif { @@ -1064,34 +1092,49 @@ 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; i < totalVars; i++) { + for (i = 0; code == TCL_OK && i < totalVars; i++) { if (objs[i] != NULL) { - Tcl_ListObjAppendElement(NULL, objPtr, objs[i]); + code = Tcl_ListObjAppendElement(interp, objPtr, objs[i]); Tcl_DecrRefCount(objs[i]); } else { /* * More %-specifiers than matching chars, so we just spit out * empty strings for these. */ - Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewObj()); + 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) { - TclNewIndexObj(objPtr, TCL_INDEX_NONE); + TclNewIntObj(objPtr, -1); } else { if (objPtr) { Tcl_SetListObj(objPtr, 0, NULL); } else { TclNewObj(objPtr); Index: generic/tclStrToD.c ================================================================== --- generic/tclStrToD.c +++ generic/tclStrToD.c @@ -5,11 +5,11 @@ * to/from floating-point in Tcl. They include TclParseNumber, which * parses numbers from strings; TclDoubleDigits, which formats numbers * into strings of digits, and procedures for interconversion among * 'double' and 'mp_int' types. * - * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. + * Copyright © 2005 Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -19,10 +19,15 @@ #include #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. @@ -42,48 +47,47 @@ * feature where it retains intermediate results as IEEE 'long double' values * somewhat unpredictably. It is tempting to include fpu_control.h, but that * file exists only on Linux; it is missing on Cygwin and MinGW. Most gcc-isms * and ix86-isms are factored out here. */ - -#if defined(__GNUC__) +# if defined(__GNUC__) typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); -#define _FPU_GETCW(cw) __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw)) -#define _FPU_SETCW(cw) __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw)) -# define FPU_IEEE_ROUNDING 0x027F -# define ADJUST_FPU_CONTROL_WORD -#define TCL_IEEE_DOUBLE_ROUNDING \ +# define _FPU_GETCW(cw) __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw)) +# define FPU_IEEE_ROUNDING 0x027F +# define ADJUST_FPU_CONTROL_WORD +# define TCL_IEEE_DOUBLE_ROUNDING_DECL \ fpu_control_t roundTo53Bits = FPU_IEEE_ROUNDING; \ - fpu_control_t oldRoundingMode; \ + fpu_control_t oldRoundingMode; +# define TCL_IEEE_DOUBLE_ROUNDING \ _FPU_GETCW(oldRoundingMode); \ _FPU_SETCW(roundTo53Bits) -#define TCL_DEFAULT_DOUBLE_ROUNDING \ +# define TCL_DEFAULT_DOUBLE_ROUNDING \ _FPU_SETCW(oldRoundingMode) /* * Sun ProC needs sunmath for rounding control on x86 like gcc above. */ -#elif defined(__sun) -#include -#define TCL_IEEE_DOUBLE_ROUNDING \ +# elif defined(__sun) +# include +# define TCL_IEEE_DOUBLE_ROUNDING_DECL +# define TCL_IEEE_DOUBLE_ROUNDING \ ieee_flags("set","precision","double",NULL) -#define TCL_DEFAULT_DOUBLE_ROUNDING \ +# define TCL_DEFAULT_DOUBLE_ROUNDING \ ieee_flags("clear","precision",NULL,NULL) +# endif +#endif /* * Other platforms are assumed to always operate in full IEEE mode, so we make * the macros to go in and out of that mode do nothing. */ - -#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) +#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. @@ -255,38 +259,39 @@ 24, 26, 28, 31, 33, 35, 38, 40, 42, 45, 47, 49, 52, 54, 56, 59, 61 }; #define N_LOG2POW5 27 -static const Tcl_WideUInt wuipow5[27] = { - (Tcl_WideUInt) 1, /* 5**0 */ - (Tcl_WideUInt) 5, - (Tcl_WideUInt) 25, - (Tcl_WideUInt) 125, - (Tcl_WideUInt) 625, - (Tcl_WideUInt) 3125, /* 5**5 */ - (Tcl_WideUInt) 3125*5, - (Tcl_WideUInt) 3125*25, - (Tcl_WideUInt) 3125*125, - (Tcl_WideUInt) 3125*625, - (Tcl_WideUInt) 3125*3125, /* 5**10 */ - (Tcl_WideUInt) 3125*3125*5, - (Tcl_WideUInt) 3125*3125*25, - (Tcl_WideUInt) 3125*3125*125, - (Tcl_WideUInt) 3125*3125*625, - (Tcl_WideUInt) 3125*3125*3125, /* 5**15 */ - (Tcl_WideUInt) 3125*3125*3125*5, - (Tcl_WideUInt) 3125*3125*3125*25, - (Tcl_WideUInt) 3125*3125*3125*125, - (Tcl_WideUInt) 3125*3125*3125*625, - (Tcl_WideUInt) 3125*3125*3125*3125, /* 5**20 */ - (Tcl_WideUInt) 3125*3125*3125*3125*5, - (Tcl_WideUInt) 3125*3125*3125*3125*25, - (Tcl_WideUInt) 3125*3125*3125*3125*125, - (Tcl_WideUInt) 3125*3125*3125*3125*625, - (Tcl_WideUInt) 3125*3125*3125*3125*3125, /* 5**25 */ - (Tcl_WideUInt) 3125*3125*3125*3125*3125*5 /* 5**26 */ +static const Tcl_WideUInt wuipow5[] = { + (Tcl_WideUInt) 1U, /* 5**0 */ + (Tcl_WideUInt) 5U, + (Tcl_WideUInt) 25U, + (Tcl_WideUInt) 125U, + (Tcl_WideUInt) 625U, + (Tcl_WideUInt) 3125U, /* 5**5 */ + (Tcl_WideUInt) 3125U*5U, + (Tcl_WideUInt) 3125U*25U, + (Tcl_WideUInt) 3125U*125U, + (Tcl_WideUInt) 3125U*625U, + (Tcl_WideUInt) 3125U*3125U, /* 5**10 */ + (Tcl_WideUInt) 3125U*3125U*5U, + (Tcl_WideUInt) 3125U*3125U*25U, + (Tcl_WideUInt) 3125U*3125U*125U, + (Tcl_WideUInt) 3125U*3125U*625U, + (Tcl_WideUInt) 3125U*3125U*3125U, /* 5**15 */ + (Tcl_WideUInt) 3125U*3125U*3125U*5U, + (Tcl_WideUInt) 3125U*3125U*3125U*25U, + (Tcl_WideUInt) 3125U*3125U*3125U*125U, + (Tcl_WideUInt) 3125U*3125U*3125U*625U, + (Tcl_WideUInt) 3125U*3125U*3125U*3125U, /* 5**20 */ + (Tcl_WideUInt) 3125U*3125U*3125U*3125U*5U, + (Tcl_WideUInt) 3125U*3125U*3125U*3125U*25U, + (Tcl_WideUInt) 3125U*3125U*3125U*3125U*125U, + (Tcl_WideUInt) 3125U*3125U*3125U*3125U*625U, + (Tcl_WideUInt) 3125U*3125U*3125U*3125U*3125U, /* 5**25 */ + (Tcl_WideUInt) 3125U*3125U*3125U*3125U*3125U*5U, + (Tcl_WideUInt) 3125U*3125U*3125U*3125U*3125U*25U /* 5**27 */ }; /* * Static functions defined in this file. */ @@ -379,13 +384,13 @@ * The arguments bytes, numBytes, and objPtr are the inputs which * determine the string to be parsed. If bytes is non-NULL, it points to * the first byte to be scanned. If bytes is NULL, then objPtr must be * non-NULL, and the string representation of objPtr will be scanned * (generated first, if necessary). The numBytes argument determines the - * number of bytes to be scanned. If numBytes is negative, the first NUL - * byte encountered will terminate the scan. If numBytes is non-negative, - * then no more than numBytes bytes will be scanned. + * number of bytes to be scanned. If numBytes is TCL_INDEX_NONE, the first NUL + * byte encountered will terminate the scan. Otherwise, + * no more than numBytes bytes will be scanned. * * The argument flags is an input that controls the numeric formats * recognized by the parser. The flag bits are: * * - TCL_PARSE_INTEGER_ONLY: accept only integer values; reject @@ -477,11 +482,11 @@ const char *expected, /* Description of the type of number the * caller expects to be able to parse * ("integer", "boolean value", etc.). */ const char *bytes, /* Pointer to the start of the string to * scan. */ - size_t numBytes, /* Maximum number of bytes to scan, see + Tcl_Size numBytes, /* Maximum number of bytes to scan, see * above. */ const char **endPtrPtr, /* Place to store pointer to the character * that terminated the scan. */ int flags) /* Flags governing the parse. */ { @@ -522,41 +527,38 @@ * point. */ int exponentSignum = 0; /* Signum of the exponent of a floating point * number. */ long exponent = 0; /* Exponent of a floating point number. */ const char *p; /* Pointer to next character to scan. */ - size_t len; /* Number of characters remaining after p. */ + Tcl_Size len; /* Number of characters remaining after p. */ const char *acceptPoint; /* Pointer to position after last character in * an acceptable number. */ - size_t acceptLen; /* Number of characters following that + Tcl_Size acceptLen; /* Number of characters following that * point. */ int status = TCL_OK; /* Status to return to caller. */ char d = 0; /* Last hexadecimal digit scanned; initialized * to avoid a compiler warning. */ int shift = 0; /* Amount to shift when accumulating binary */ mp_err err = MP_OKAY; - int under = 0; /* Flag trailing '_' as error if true once - * number is accepted. */ -#define ALL_BITS ((Tcl_WideUInt)-1) -#define MOST_BITS (ALL_BITS >> 1) +#define MOST_BITS (UWIDE_MAX >> 1) /* * Initialize bytes to start of the object's string rep if the caller * didn't pass anything else. */ if (bytes == NULL) { if (interp == NULL && endPtrPtr == NULL) { - if (TclHasIntRep(objPtr, &tclDictType)) { + if (TclHasInternalRep(objPtr, &tclDictType)) { /* A dict can never be a (single) number */ return TCL_ERROR; } - if (TclHasIntRep(objPtr, &tclListType)) { - int length; + if (TclHasInternalRep(objPtr, &tclListType)) { + Tcl_Size length; /* A list can only be a (single) number if its length == 1 */ - TclListObjLength(NULL, objPtr, &length); + TclListObjLengthM(NULL, objPtr, &length); if (length != 1) { return TCL_ERROR; } } } @@ -567,10 +569,91 @@ 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, @@ -642,11 +725,11 @@ acceptState = state; acceptPoint = p; acceptLen = len; if (c == 'x' || c == 'X') { - if (flags & (TCL_PARSE_OCTAL_ONLY|TCL_PARSE_BINARY_ONLY) || under) { + if (flags & (TCL_PARSE_OCTAL_ONLY|TCL_PARSE_BINARY_ONLY)) { goto endgame; } state = ZERO_X; break; } @@ -655,30 +738,24 @@ } if (flags & TCL_PARSE_SCAN_PREFIXES) { goto zeroo; } if (c == 'b' || c == 'B') { - if ((flags & TCL_PARSE_OCTAL_ONLY) || under) { + if ((flags & TCL_PARSE_OCTAL_ONLY)) { goto endgame; } state = ZERO_B; break; } if (flags & TCL_PARSE_BINARY_ONLY) { goto zerob; } if (c == 'o' || c == 'O') { - if (under) { - goto endgame; - } state = ZERO_O; break; } if (c == 'd' || c == 'D') { - if (under) { - goto endgame; - } state = ZERO_D; break; } goto decimal; @@ -695,42 +772,49 @@ /* FALLTHROUGH */ case ZERO_O: zeroo: if (c == '0') { numTrailZeros++; - under = 0; state = OCTAL; break; } else if (c >= '1' && c <= '7') { - under = 0; if (objPtr != NULL) { shift = 3 * (numTrailZeros + 1); significandOverflow = AccumulateDecimalDigit( (unsigned)(c-'0'), numTrailZeros, &significandWide, &significandBig, significandOverflow); if (!octalSignificandOverflow) { /* - * Shifting by more bits than are in the value being - * shifted is at least de facto nonportable. Check for - * too large shifts first. + * Shifting by as many or more bits than are in the + * value being shifted is undefined behavior. Check + * for too large shifts first. */ if ((octalSignificandWide != 0) && (((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt)) || (octalSignificandWide > - ((Tcl_WideUInt)-1 >> shift)))) { + (UWIDE_MAX >> shift)))) { octalSignificandOverflow = 1; err = mp_init_u64(&octalSignificandBig, octalSignificandWide); } } if (!octalSignificandOverflow) { - octalSignificandWide = - (octalSignificandWide << shift) + (c - '0'); + /* + * 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); } @@ -749,14 +833,10 @@ 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 @@ -772,48 +852,50 @@ case ZERO_X: zerox: if (c == '0') { numTrailZeros++; - under = 0; state = HEXADECIMAL; break; } else if (isdigit(UCHAR(c))) { - under = 0; d = (c-'0'); } else if (c >= 'A' && c <= 'F') { - under = 0; d = (c-'A'+10); } else if (c >= 'a' && c <= 'f') { - under = 0; d = (c-'a'+10); - } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { - /* Ignore numeric "white space" */ - under = 1; - break; } else { goto endgame; } if (objPtr != NULL) { shift = 4 * (numTrailZeros + 1); if (!significandOverflow) { /* - * Shifting by more bits than are in the value being - * shifted is at least de facto nonportable. Check for too - * large shifts first. + * Shifting by as many or more bits than are in the + * value being shifted is undefined behavior. Check + * for too large shifts first. */ if (significandWide != 0 && ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || - significandWide > ((Tcl_WideUInt)-1 >> shift))) { + significandWide > (UWIDE_MAX >> shift))) { significandOverflow = 1; err = mp_init_u64(&significandBig, significandWide); } } if (!significandOverflow) { - significandWide = (significandWide << shift) + d; + /* + * 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); } @@ -828,44 +910,49 @@ case BINARY: acceptState = state; acceptPoint = p; acceptLen = len; - /* FALLTHRU */ + /* FALLTHRU */ case ZERO_B: zerob: if (c == '0') { numTrailZeros++; - under = 0; state = BINARY; break; - } else if (c == '_' && !(flags & TCL_PARSE_NO_UNDERSCORE)) { - /* Ignore numeric "white space" */ - under = 1; - break; } else if (c != '1') { goto endgame; } if (objPtr != NULL) { shift = numTrailZeros + 1; if (!significandOverflow) { /* - * Shifting by more bits than are in the value being - * shifted is at least de facto nonportable. Check for too - * large shifts first. + * Shifting by as many or more bits than are in the + * value being shifted is undefined behavior. Check + * for too large shifts first. */ if (significandWide != 0 && ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || - significandWide > ((Tcl_WideUInt)-1 >> shift))) { + significandWide > (UWIDE_MAX >> shift))) { significandOverflow = 1; err = mp_init_u64(&significandBig, significandWide); } } if (!significandOverflow) { - significandWide = (significandWide << shift) + 1; + /* + * 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); } @@ -878,21 +965,14 @@ 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: @@ -905,11 +985,10 @@ 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( @@ -917,25 +996,18 @@ &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; @@ -957,11 +1029,10 @@ case LEADING_RADIX_POINT: if (c == '0') { numDigitsAfterDp++; numTrailZeros++; - under = 0; state = FRACTION; break; } else if (isdigit(UCHAR(c))) { numDigitsAfterDp++; if (objPtr != NULL) { @@ -974,17 +1045,12 @@ 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: /* @@ -992,16 +1058,14 @@ * 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 */ @@ -1011,17 +1075,12 @@ * 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: /* @@ -1036,17 +1095,12 @@ 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 @@ -1053,56 +1107,49 @@ * 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; @@ -1110,28 +1157,25 @@ * 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; @@ -1138,18 +1182,16 @@ /* * 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'; @@ -1160,11 +1202,10 @@ } else { goto endgame; } numSigDigs++; significandWide = (significandWide << 4) + d; - under = 0; state = sNANHEX; break; } goto endgame; case sNANFINISH: @@ -1173,12 +1214,12 @@ case sINFINITY: acceptState = state; acceptPoint = p; acceptLen = len; goto endgame; - } + next: p++; len--; } endgame: @@ -1196,12 +1237,12 @@ * Back up to the last accepting state in the lexer. * If the last char seen is the numeric whitespace character '_', * backup to that. */ - p = under ? acceptPoint-1 : acceptPoint; - len = under ? acceptLen-1 : acceptLen; + p = acceptPoint; + len = acceptLen; if (!(flags & TCL_PARSE_NO_WHITESPACE)) { /* * Accept trailing whitespace. */ @@ -1223,11 +1264,11 @@ /* * Generate and store the appropriate internal rep. */ if (status == TCL_OK && objPtr != NULL) { - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); switch (acceptState) { case SIGNUM: case ZERO_X: case ZERO_O: case ZERO_B: @@ -1257,11 +1298,19 @@ significandOverflow = 1; err = mp_init_u64(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { - significandWide <<= shift; + /* + * 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) { @@ -1281,11 +1330,19 @@ significandOverflow = 1; err = mp_init_u64(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { - significandWide <<= shift; + /* + * 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) { @@ -1306,11 +1363,19 @@ err = mp_init_u64(&octalSignificandBig, octalSignificandWide); } if (shift) { if (!octalSignificandOverflow) { - octalSignificandWide <<= shift; + /* + * 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); } } @@ -1321,22 +1386,22 @@ octalSignificandOverflow = 1; } else { objPtr->typePtr = &tclIntType; if (signum) { objPtr->internalRep.wideValue = - - (Tcl_WideInt) octalSignificandWide; + (Tcl_WideInt)(-octalSignificandWide); } else { objPtr->internalRep.wideValue = - (Tcl_WideInt) octalSignificandWide; + (Tcl_WideInt)octalSignificandWide; } } } if ((err == MP_OKAY) && octalSignificandOverflow) { if (signum) { err = mp_neg(&octalSignificandBig, &octalSignificandBig); } - TclSetBignumIntRep(objPtr, &octalSignificandBig); + TclSetBignumInternalRep(objPtr, &octalSignificandBig); } if (err != MP_OKAY) { return TCL_ERROR; } break; @@ -1357,22 +1422,22 @@ significandOverflow = 1; } else { objPtr->typePtr = &tclIntType; if (signum) { objPtr->internalRep.wideValue = - - (Tcl_WideInt) significandWide; + (Tcl_WideInt)(-significandWide); } else { objPtr->internalRep.wideValue = - (Tcl_WideInt) significandWide; + (Tcl_WideInt)significandWide; } } } if ((err == MP_OKAY) && significandOverflow) { if (signum) { err = mp_neg(&significandBig, &significandBig); } - TclSetBignumIntRep(objPtr, &significandBig); + TclSetBignumInternalRep(objPtr, &significandBig); } if (err != MP_OKAY) { return TCL_ERROR; } break; @@ -1465,11 +1530,11 @@ expected); Tcl_AppendLimitedToObj(msg, bytes, numBytes, 50, ""); Tcl_AppendToObj(msg, "\"", -1); Tcl_SetObjResult(interp, msg); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", (void *)NULL); } } /* * Free memory. @@ -1528,11 +1593,11 @@ */ *wideRepPtr = digit; return 0; } else if (numZeros >= maxpow10_wide - || w > ((Tcl_WideUInt)-1-digit)/pow10_wide[numZeros+1]) { + || w > (UWIDE_MAX-digit)/pow10_wide[numZeros+1]) { /* * Wide multiplication will overflow. Expand the number to a * bignum and fall through into the bignum case. */ @@ -1618,30 +1683,38 @@ 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. */ + 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. + * 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. */ - - TCL_IEEE_DOUBLE_ROUNDING; + volatile double retval; /* Value of the number. */ /* - * Test for the easy cases. + * Test for zero significand, which requires explicit construction + * of -0.0. (Unary minus returns a positive zero.) */ - if (significand == 0) { return copysign(0.0, -signum); } + + /* + * Set the FP control word for 53 bits, WARNING: It must be reset + * before returning. + */ + TCL_IEEE_DOUBLE_ROUNDING; + if (numSigDigs <= QUICK_MAX) { if (exponent >= 0) { if (exponent <= mmaxpow) { /* * The significand is an exact integer, and so is @@ -1683,11 +1756,11 @@ } } } /* - * All the easy cases have failed. Promote ths significand to bignum and + * All the easy cases have failed. Promote the significand to bignum and * call MakeHighPrecisionDouble to do it the hard way. */ if (mp_init_u64(&significandBig, significand) != MP_OKAY) { return 0.0; @@ -1737,31 +1810,43 @@ 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; + 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. + * 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. */ - - TCL_IEEE_DOUBLE_ROUNDING; + volatile double retval; /* - * Quick checks for zero, and over/underflow. Be careful to avoid - * integer overflow when calculating with 'exponent'. + * A zero significand requires explicit construction of -0.0. + * (Unary minus returns positive zero.) */ - if (mp_iszero(significand)) { return copysign(0.0, -signum); } + + /* + * Set the 53-bit rounding mode. WARNING: It must be reset before + * returning. + */ + TCL_IEEE_DOUBLE_ROUNDING; + + /* + * Make quick checks for over/underflow. Be careful to avoid + * integer overflow when calculating with 'exponent'. + */ if (exponent >= 0 && exponent-1 > maxDigits-numSigDigs) { retval = HUGE_VAL; goto returnValue; } else if (exponent < 0 && numSigDigs+exponent < minDigits+1) { retval = 0.0; @@ -1973,11 +2058,11 @@ } /* * Compute twoMd as 2*M*d, where d is the exact value. * This is done by multiplying by 5**(M5+exponent) and then multiplying - * by 2**(M5+exponent+1), which is, of couse, a left shift. + * by 2**(M5+exponent+1), which is, of course, a left shift. */ if (mp_init_copy(&twoMd, exactSignificand) != MP_OKAY) { mp_clear(&twoMv); return approxResult; @@ -2060,11 +2145,11 @@ * If we're in the 'round to even' case, and the significand is already * even, we're done. Return the approximate result. */ if (roundToEven) { rteSignificand = frexp(approxResult, &rteExponent); - rteSigWide = (Tcl_WideInt) ldexp(rteSignificand, FP_PRECISION); + rteSigWide = (Tcl_WideInt)ldexp(rteSignificand, FP_PRECISION); if ((rteSigWide & 1) == 0) { mp_clear(&twoMd); mp_clear(&twoMv); return approxResult; } @@ -2202,14 +2287,15 @@ /* *---------------------------------------------------------------------- * * RequiredPrecision -- * - * Determines the number of bits needed to hold an intger. + * Determines the number of bits needed to hold an integer. * * Results: - * Returns the position of the most significant bit (0 - 63). Returns 0 + * Returns the position of the most significant bit (1 - 64), starting + * the counting at 1 for the LSB. (RP(1) -> 1). Returns 0 * if the number is zero. * *---------------------------------------------------------------------- */ @@ -2217,10 +2303,17 @@ RequiredPrecision( Tcl_WideUInt w) /* Number to interrogate. */ { int rv; unsigned long wi; + + if (w == 0) { + return 0; + } + if (sizeof(Tcl_WideUInt) <= sizeof(size_t)) { + return 1 + TclMSB(w); + } if (w & ((Tcl_WideUInt) 0xFFFFFFFF << 32)) { wi = (unsigned long) (w >> 32); rv = 32; } else { wi = (unsigned long) w; rv = 0; @@ -2916,11 +3009,11 @@ if (ilim1 < 0) { return NULL; } ilim = ilim1; --k; - d *= 10.0; + d = d * 10.0; ++ieps; } /* * Compute estimated roundoff error. @@ -2933,11 +3026,11 @@ * Handle the peculiar case where the result has no significant digits. */ retval = (char *)Tcl_Alloc(len + 1); if (ilim == 0) { - d -= 5.; + d = d - 5.; if (d > eps.d) { *retval = '1'; *decpt = k; return retval; } else if (d < -eps.d) { @@ -3566,11 +3659,11 @@ */ if (m2plus > m2minus) { mp_clear(&mplus); } - mp_clear_multi(&b, &mminus, &temp, NULL); + mp_clear_multi(&b, &mminus, &temp, (void *)NULL); *s = '\0'; *decpt = k; if (endPtr) { *endPtr = s; } @@ -3723,19 +3816,17 @@ 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; + default: + return 0; } - Tcl_Panic("in ShouldBankerRoundUp, trichotomy fails!"); - return 0; } /* *---------------------------------------------------------------------- * @@ -3768,20 +3859,18 @@ 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; + switch (r) { case MP_EQ: return isodd; case MP_GT: return 1; + default: + return 0; } - Tcl_Panic("in ShouldBankerRoundUpToNext, trichotomy fails!"); - return 0; } /* *---------------------------------------------------------------------- * @@ -4007,11 +4096,11 @@ */ if (m2plus > m2minus) { mp_clear(&mplus); } - mp_clear_multi(&b, &mminus, &dig, &S, NULL); + mp_clear_multi(&b, &mminus, &dig, &S, (void *)NULL); *s = '\0'; *decpt = k; if (endPtr) { *endPtr = s; } @@ -4182,11 +4271,11 @@ /* * Endgame - store the location of the decimal point and the end of the * string. */ - mp_clear_multi(&b, &S, &dig, NULL); + mp_clear_multi(&b, &S, &dig, (void *)NULL); *s = '\0'; *decpt = k; if (endPtr) { *endPtr = s; } @@ -4409,11 +4498,11 @@ ++b2; ++s2; ++m2plus; } - if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] <= 64) { + if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] < 64) { /* * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit word, * then all our intermediate calculations can be done using exact * 64-bit arithmetic with no need for expensive multiprecision * operations. (This will be true for all numbers in the range @@ -4466,11 +4555,11 @@ b2 -= s2; s2 = 0; } else if (s2 >= b2 && b2 > 0) { s2 -= b2; b2 = 0; } - if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] <= 64) { + if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] < 64) { /* * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit word, * then all our intermediate calculations can be done using exact * 64-bit arithmetic with no need for expensive multiprecision * operations. @@ -4707,26 +4796,26 @@ /* * Infinite values can't convert to bignum. */ - if (TclIsInfinite(d)) { + if (isinf(d)) { if (interp != NULL) { const char *s = "integer value too large to represent"; Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1)); - Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL); + Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (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); + Tcl_WideInt w = (Tcl_WideInt)ldexp(fract, mantBits); int shift = expt - mantBits; err = mp_init_i64(b, w); if (err != MP_OKAY) { /* just skip */ @@ -5181,27 +5270,27 @@ strcpy(buffer, "NaN"); return; #else union { double dv; - Tcl_WideUInt iv; + uint64_t iv; } bitwhack; bitwhack.dv = value; if (n770_fp) { bitwhack.iv = Nokia770Twiddle(bitwhack.iv); } - if (bitwhack.iv & ((Tcl_WideUInt) 1 << 63)) { - bitwhack.iv &= ~ ((Tcl_WideUInt) 1 << 63); + if (bitwhack.iv & (UINT64_C(1) << 63)) { + bitwhack.iv &= ~ (UINT64_C(1) << 63); *buffer++ = '-'; } *buffer++ = 'N'; *buffer++ = 'a'; *buffer++ = 'N'; - bitwhack.iv &= (((Tcl_WideUInt) 1) << 51) - 1; + bitwhack.iv &= ((UINT64_C(1)) << 51) - 1; if (bitwhack.iv != 0) { - sprintf(buffer, "(%" TCL_LL_MODIFIER "x)", bitwhack.iv); + snprintf(buffer, TCL_DOUBLE_SPACE, "(%" PRIx64 ")", bitwhack.iv); } else { *buffer = '\0'; } #endif /* IEEE_FLOATING_POINT */ } Index: generic/tclStringObj.c ================================================================== --- generic/tclStringObj.c +++ generic/tclStringObj.c @@ -1,76 +1,76 @@ /* * 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 + * 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 Unicode data (unless Tcl_GetUnicode - * is explicitly called). + * numChars, but we don't store the fixed form encoding (unless + * Tcl_GetUnicode is explicitly called). * - * The String object type stores one or both formats. The default - * behavior is to store UTF. Once Unicode is calculated by a function, it - * is stored in the internal rep for future access (without an additional - * O(n) cost). + * 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 the space for the string or Unicode representation, we - * allocate double the space for the string or Unicode and use the + * reallocating space, we allocate double the space and use the * internal representation to keep track of how much space is used vs. * allocated. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright (c) 1999 by Scriptics Corporation. + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclTomMath.h" #include "tclStringRep.h" - #include "assert.h" /* * Prototypes for functions defined later in this file: */ static void AppendPrintfToObjVA(Tcl_Obj *objPtr, const char *format, va_list argList); static void AppendUnicodeToUnicodeRep(Tcl_Obj *objPtr, - const Tcl_UniChar *unicode, size_t appendNumChars); + const Tcl_UniChar *unicode, Tcl_Size appendNumChars); static void AppendUnicodeToUtfRep(Tcl_Obj *objPtr, - const Tcl_UniChar *unicode, size_t numChars); + const Tcl_UniChar *unicode, Tcl_Size numChars); static void AppendUtfToUnicodeRep(Tcl_Obj *objPtr, - const char *bytes, size_t numBytes); + const char *bytes, Tcl_Size numBytes); static void AppendUtfToUtfRep(Tcl_Obj *objPtr, - const char *bytes, size_t numBytes); + const char *bytes, Tcl_Size numBytes); static void DupStringInternalRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); -static size_t ExtendStringRepWithUnicode(Tcl_Obj *objPtr, - const Tcl_UniChar *unicode, size_t numChars); +static Tcl_Size ExtendStringRepWithUnicode(Tcl_Obj *objPtr, + const Tcl_UniChar *unicode, Tcl_Size numChars); static void ExtendUnicodeRepWithString(Tcl_Obj *objPtr, - const char *bytes, size_t numBytes, - size_t numAppendChars); + const char *bytes, Tcl_Size numBytes, + Tcl_Size numAppendChars); static void FillUnicodeRep(Tcl_Obj *objPtr); static void FreeStringInternalRep(Tcl_Obj *objPtr); -static void GrowStringBuffer(Tcl_Obj *objPtr, size_t needed, int flag); -static void GrowUnicodeBuffer(Tcl_Obj *objPtr, size_t needed); +static void GrowStringBuffer(Tcl_Obj *objPtr, Tcl_Size needed, int flag); +static void GrowUnicodeBuffer(Tcl_Obj *objPtr, Tcl_Size needed); static int SetStringFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void SetUnicodeObj(Tcl_Obj *objPtr, - const Tcl_UniChar *unicode, size_t numChars); -static size_t UnicodeLength(const Tcl_UniChar *unicode); + const Tcl_UniChar *unicode, Tcl_Size numChars); +static Tcl_Size UnicodeLength(const Tcl_UniChar *unicode); static void UpdateStringOfString(Tcl_Obj *objPtr); + +#define ISCONTINUATION(bytes) (\ + ((bytes)[0] & 0xC0) == 0x80) /* * The structure below defines the string Tcl object type by means of * functions that can be invoked by generic object code. */ @@ -78,11 +78,12 @@ const Tcl_ObjType tclStringType = { "string", /* name */ FreeStringInternalRep, /* freeIntRepPro */ DupStringInternalRep, /* dupIntRepProc */ UpdateStringOfString, /* updateStringProc */ - SetStringFromAny /* setFromAnyProc */ + SetStringFromAny, /* setFromAnyProc */ + TCL_OBJTYPE_V0 }; /* * TCL STRING GROWTH ALGORITHM * @@ -121,100 +122,83 @@ #endif static void GrowStringBuffer( Tcl_Obj *objPtr, - size_t needed, - int flag) + Tcl_Size needed, /* Not including terminating nul */ + int flag) /* If 0, try to overallocate */ { /* - * Pre-conditions: + * Preconditions: * objPtr->typePtr == &tclStringType * needed > stringPtr->allocated * flag || objPtr->bytes != NULL */ String *stringPtr = GET_STRING(objPtr); - char *ptr = NULL; - size_t attempt; + char *ptr; + Tcl_Size capacity; + + assert(needed <= TCL_SIZE_MAX - 1); + needed += 1; /* Include terminating nul */ if (objPtr->bytes == &tclEmptyString) { objPtr->bytes = NULL; } + /* + * In code below, note 'capacity' and 'needed' include terminating nul, + * while stringPtr->allocated does not. + */ 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); - } + 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 = attempt; + stringPtr->allocated = capacity - 1; /* Does not include slot for end nul */ } static void GrowUnicodeBuffer( Tcl_Obj *objPtr, - size_t needed) + Tcl_Size needed) { /* - * Pre-conditions: + * Preconditions: * objPtr->typePtr == &tclStringType * needed > stringPtr->maxChars */ - String *ptr = NULL, *stringPtr = GET_STRING(objPtr); - size_t attempt; + 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) { - /* - * 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; + /* 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); } /* *---------------------------------------------------------------------- @@ -231,11 +215,11 @@ * Results: * A newly created string object is returned that has ref count zero. * * Side effects: * The new object's internal string representation will be set to a copy - * of the length bytes starting at "bytes". If "length" is negative, use + * of the length bytes starting at "bytes". If "length" is TCL_INDEX_NONE, use * bytes up to the first NUL byte; i.e., assume "bytes" points to a * C-style NUL-terminated string. The object's type is set to NULL. An * extra NUL is added to the end of the new object's byte array. * *---------------------------------------------------------------------- @@ -245,29 +229,29 @@ #undef Tcl_NewStringObj Tcl_Obj * Tcl_NewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ - size_t length) /* The number of bytes to copy from "bytes" + Tcl_Size length) /* The number of bytes to copy from "bytes" * when initializing the new object. If - * negative, use bytes up to the first NUL + * TCL_INDEX_NONE, use bytes up to the first NUL * byte. */ { return Tcl_DbNewStringObj(bytes, length, "unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ - size_t length) /* The number of bytes to copy from "bytes" + Tcl_Size length) /* The number of bytes to copy from "bytes" * when initializing the new object. If -1, * use bytes up to the first NUL byte. */ { Tcl_Obj *objPtr; - if (length == TCL_INDEX_NONE) { + if (length < 0) { length = (bytes? strlen(bytes) : 0); } TclNewStringObj(objPtr, bytes, length); return objPtr; } @@ -292,11 +276,11 @@ * Results: * A newly created string object is returned that has ref count zero. * * Side effects: * The new object's internal string representation will be set to a copy - * of the length bytes starting at "bytes". If "length" is negative, use + * of the length bytes starting at "bytes". If "length" is TCL_INDEX_NONE, use * bytes up to the first NUL byte; i.e., assume "bytes" points to a * C-style NUL-terminated string. The object's type is set to NULL. An * extra NUL is added to the end of the new object's byte array. * *---------------------------------------------------------------------- @@ -305,11 +289,11 @@ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ - size_t length, /* The number of bytes to copy from "bytes" + Tcl_Size length, /* The number of bytes to copy from "bytes" * when initializing the new object. If -1, * use bytes up to the first NUL byte. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for @@ -327,11 +311,11 @@ #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ - size_t length, /* The number of bytes to copy from "bytes" + Tcl_Size length, /* The number of bytes to copy from "bytes" * when initializing the new object. If -1, * use bytes up to the first NUL byte. */ TCL_UNUSED(const char *) /*file*/, TCL_UNUSED(int) /*line*/) { @@ -360,11 +344,11 @@ Tcl_Obj * Tcl_NewUnicodeObj( const Tcl_UniChar *unicode, /* The unicode string used to initialize the * new object. */ - size_t numChars) /* Number of characters in the unicode + Tcl_Size numChars) /* Number of characters in the unicode * string. */ { Tcl_Obj *objPtr; TclNewObj(objPtr); @@ -378,26 +362,77 @@ * Tcl_GetCharLength -- * * Get the length of the Unicode string from the Tcl object. * * Results: - * Pointer to unicode string representing the unicode object. + * Pointer to Unicode string representing the Unicode object. * * Side effects: * Frees old internal rep. Allocates memory for new "String" internal * rep. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_GetCharLength( Tcl_Obj *objPtr) /* The String object to get the num chars * of. */ { String *stringPtr; - size_t numChars = 0; + Tcl_Size numChars = 0; + + /* + * Quick, no-shimmer return for short string reps. + */ + + if ((objPtr->bytes) && (objPtr->length < 2)) { + /* 0 bytes -> 0 chars; 1 byte -> 1 char */ + return objPtr->length; + } + + /* + * Optimize the case where we're really dealing with a bytearray object; + * we don't need to convert to a string to perform the get-length operation. + * + * Starting in Tcl 8.7, we check for a "pure" bytearray, because the + * machinery behind that test is using a proper bytearray ObjType. We + * could also compute length of an improper bytearray without shimmering + * but there's no value in that. We *want* to shimmer an improper bytearray + * because improper bytearrays have worthless internal reps. + */ + + if (TclIsPureByteArray(objPtr)) { + (void) Tcl_GetByteArrayFromObj(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. */ @@ -416,33 +451,20 @@ * 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; -} - + (void) Tcl_GetByteArrayFromObj(objPtr, &numChars); + } else { + Tcl_GetString(objPtr); + numChars = TclNumUtfChars(objPtr->bytes, objPtr->length); + } + + return numChars; +} + + /* *---------------------------------------------------------------------- * * TclCheckEmptyString -- * @@ -459,18 +481,23 @@ */ int TclCheckEmptyString( Tcl_Obj *objPtr) { - int length = -1; + Tcl_Size length = TCL_INDEX_NONE; if (objPtr->bytes == &tclEmptyString) { return TCL_EMPTYSTRING_YES; } + + if (TclIsPureByteArray(objPtr) + && Tcl_GetCharLength(objPtr) == 0) { + return TCL_EMPTYSTRING_YES; + } if (TclListObjIsCanonical(objPtr)) { - Tcl_ListObjLength(NULL, objPtr, &length); + TclListObjLengthM(NULL, objPtr, &length); return length == 0; } if (TclIsPureDict(objPtr)) { Tcl_DictObjSize(NULL, objPtr, &length); @@ -503,23 +530,27 @@ int Tcl_GetUniChar( Tcl_Obj *objPtr, /* The object to get the Unicode charater * from. */ - size_t index) /* Get the index'th Unicode character. */ + Tcl_Size index) /* Get the index'th Unicode character. */ { String *stringPtr; int ch; + + if (index < 0) { + return -1; + } /* - * Optimize the case where we're really dealing with a bytearray object + * Optimize the case where we're really dealing with a ByteArray object * we don't need to convert to a string to perform the indexing operation. */ if (TclIsPureByteArray(objPtr)) { - size_t length = 0; - unsigned char *bytes = TclGetByteArrayFromObj(objPtr, &length); + Tcl_Size length = 0; + unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &length); if (index >= length) { return -1; } return bytes[index]; @@ -536,46 +567,71 @@ /* * If numChars is unknown, compute it. */ if (stringPtr->numChars == TCL_INDEX_NONE) { - TclNumUtfChars(stringPtr->numChars, objPtr->bytes, objPtr->length); + TclNumUtfCharsM(stringPtr->numChars, objPtr->bytes, objPtr->length); } + if (index >= stringPtr->numChars) { + return -1; + } if (stringPtr->numChars == objPtr->length) { - return (Tcl_UniChar) objPtr->bytes[index]; + return (unsigned char) objPtr->bytes[index]; } FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } if (index >= stringPtr->numChars) { return -1; } ch = stringPtr->unicode[index]; -#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; +} + +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_GetByteArrayFromObj(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); +#undef Tcl_UtfToUniChar + Tcl_UtfToUniChar(begin, &ch); return ch; } /* *---------------------------------------------------------------------- * - * Tcl_GetUnicodeFromObj -- + * Tcl_GetUnicodeFromObj/TclGetUnicodeFromObj -- * * Get the Unicode form of the String object with length. If the object * is not already a String object, it will be converted to one. If the * String object does not have a Unicode rep, then one is create from the * UTF string format. @@ -587,15 +643,46 @@ * Converts the object to have the String internal rep. * *---------------------------------------------------------------------- */ +#undef Tcl_GetUnicodeFromObj +#if !defined(TCL_NO_DEPRECATED) +Tcl_UniChar * +TclGetUnicodeFromObj( + Tcl_Obj *objPtr, /* The object to find the Unicode string + * for. */ + void *lengthPtr) /* If non-NULL, the location where the string + * rep's Tcl_UniChar length should be stored. If + * NULL, no length is stored. */ +{ + String *stringPtr; + + SetStringFromAny(NULL, objPtr); + stringPtr = GET_STRING(objPtr); + + if (stringPtr->hasUnicode == 0) { + FillUnicodeRep(objPtr); + stringPtr = GET_STRING(objPtr); + } + + if (lengthPtr != NULL) { + if (stringPtr->numChars > INT_MAX) { + Tcl_Panic("Tcl_GetUnicodeFromObj with 'int' lengthPtr" + " cannot handle such long strings. Please use 'Tcl_Size'"); + } + *(int *)lengthPtr = (int)stringPtr->numChars; + } + return stringPtr->unicode; +} +#endif /* !defined(TCL_NO_DEPRECATED) */ + Tcl_UniChar * Tcl_GetUnicodeFromObj( Tcl_Obj *objPtr, /* The object to find the unicode string * for. */ - int *lengthPtr) /* If non-NULL, the location where the string + Tcl_Size *lengthPtr) /* If non-NULL, the location where the string * rep's unichar length should be stored. If * NULL, no length is stored. */ { String *stringPtr; @@ -618,12 +705,13 @@ * * Tcl_GetRange -- * * Create a Tcl Object that contains the chars between first and last of * the object indicated by "objPtr". If the object is not already a - * String object, convert it to one. The first and last indices are - * assumed to be in the appropriate range. + * String object, convert it to one. If first is TCL_INDEX_NONE, the + * returned string start at the beginning of objPtr. If last is + * TCL_INDEX_NONE, the returned string ends at the end of objPtr. * * Results: * Returns a new Tcl Object of the String type. * * Side effects: @@ -633,37 +721,35 @@ */ Tcl_Obj * Tcl_GetRange( Tcl_Obj *objPtr, /* The Tcl object to find the range of. */ - size_t first, /* First index of the range. */ - size_t last) /* Last index of the range. */ + Tcl_Size first, /* First index of the range. */ + Tcl_Size last) /* Last index of the range. */ { Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */ String *stringPtr; - size_t length = 0; + Tcl_Size length = 0; - if (first == TCL_INDEX_NONE) { - first = TCL_INDEX_START; - } - if (last + 2 <= first + 1) { - return Tcl_NewObj(); + 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 = TclGetByteArrayFromObj(objPtr, &length); + unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &length); - if (last >= length) { + if (last < 0 || last >= length) { last = length - 1; } if (last < first) { - return Tcl_NewObj(); + TclNewObj(newObjPtr); + return newObjPtr; } return Tcl_NewByteArrayObj(bytes + first, last - first + 1); } /* @@ -677,20 +763,21 @@ /* * If numChars is unknown, compute it. */ if (stringPtr->numChars == TCL_INDEX_NONE) { - TclNumUtfChars(stringPtr->numChars, objPtr->bytes, objPtr->length); + TclNumUtfCharsM(stringPtr->numChars, objPtr->bytes, objPtr->length); } if (stringPtr->numChars == objPtr->length) { - if (last >= stringPtr->numChars) { + if (last < 0 || last >= stringPtr->numChars) { last = stringPtr->numChars - 1; } if (last < first) { - return Tcl_NewObj(); + TclNewObj(newObjPtr); + return newObjPtr; } - newObjPtr = Tcl_NewStringObj(objPtr->bytes + first, last-first+1); + newObjPtr = Tcl_NewStringObj(objPtr->bytes + first, last - first + 1); /* * Since we know the char length of the result, store it. */ @@ -700,29 +787,63 @@ return newObjPtr; } FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } - if (last > stringPtr->numChars) { - last = stringPtr->numChars; + if (last < 0 || last >= stringPtr->numChars) { + last = stringPtr->numChars - 1; + } + if (last < first) { + TclNewObj(newObjPtr); + return newObjPtr; + } + return Tcl_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_GetByteArrayFromObj(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) { - 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); + 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); } /* *---------------------------------------------------------------------- * @@ -734,11 +855,11 @@ * Results: * None. * * Side effects: * The object's string representation will be set to a copy of the - * "length" bytes starting at "bytes". If "length" is negative, use bytes + * "length" bytes starting at "bytes". If "length" is TCL_INDEX_NONE, use bytes * up to the first NUL byte; i.e., assume "bytes" points to a C-style * NUL-terminated string. The object's old string and internal * representations are freed and the object's type is set NULL. * *---------------------------------------------------------------------- @@ -747,11 +868,11 @@ void Tcl_SetStringObj( Tcl_Obj *objPtr, /* Object whose internal rep to init. */ const char *bytes, /* Points to the first of the length bytes * used to initialize the object. */ - size_t length) /* The number of bytes to copy from "bytes" + Tcl_Size length) /* The number of bytes to copy from "bytes" * when initializing the object. If -1, * use bytes up to the first NUL byte.*/ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetStringObj"); @@ -759,11 +880,11 @@ /* * Set the type to NULL and free any internal rep for the old type. */ - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); /* * Free any old string rep, then set the string rep to a copy of the * length bytes starting at "bytes". */ @@ -778,38 +899,41 @@ /* *---------------------------------------------------------------------- * * Tcl_SetObjLength -- * - * This function changes the length of the string representation of an - * object. + * 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, - * 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". + * 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. */ - size_t length) /* Number of bytes desired for string + Tcl_Size length) /* Number of bytes desired for string * representation of object, not including * terminating null byte. */ { String *stringPtr; + if (length < 0) { + Tcl_Panic("Tcl_SetObjLength: length requested is negative: " + "%" TCL_SIZE_MODIFIER "d (integer overflow?)", length); + } if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetObjLength"); } if (objPtr->bytes && objPtr->length == length) { @@ -837,11 +961,11 @@ objPtr->length = length; objPtr->bytes[length] = 0; /* - * Invalidate the unicode data. + * Invalidate the Unicode data. */ stringPtr->numChars = TCL_INDEX_NONE; stringPtr->hasUnicode = 0; } else { @@ -850,11 +974,11 @@ SET_STRING(objPtr, stringPtr); stringPtr->maxChars = length; } /* - * Mark the new end of the unicode string + * Mark the new end of the Unicode string */ stringPtr->numChars = length; stringPtr->unicode[length] = 0; stringPtr->hasUnicode = 1; @@ -891,15 +1015,20 @@ int Tcl_AttemptSetObjLength( Tcl_Obj *objPtr, /* Pointer to object. This object must not * currently be shared. */ - size_t length) /* Number of bytes desired for string + Tcl_Size length) /* Number of bytes desired for string * representation of object, not including * terminating null byte. */ { String *stringPtr; + + if (length < 0) { + /* Negative lengths => most likely integer overflow */ + return 0; + } if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_AttemptSetObjLength"); } if (objPtr->bytes && objPtr->length == length) { @@ -919,13 +1048,13 @@ */ char *newBytes; if (objPtr->bytes == &tclEmptyString) { - newBytes = (char *)Tcl_AttemptAlloc(length + 1); + newBytes = (char *)Tcl_AttemptAlloc(length + 1U); } else { - newBytes = (char *)Tcl_AttemptRealloc(objPtr->bytes, length + 1); + newBytes = (char *)Tcl_AttemptRealloc(objPtr->bytes, length + 1U); } if (newBytes == NULL) { return 0; } objPtr->bytes = newBytes; @@ -934,18 +1063,18 @@ objPtr->length = length; objPtr->bytes[length] = 0; /* - * Invalidate the unicode data. + * Invalidate the Unicode data. */ stringPtr->numChars = TCL_INDEX_NONE; stringPtr->hasUnicode = 0; } else { /* - * Changing length of pure unicode string. + * Changing length of pure Unicode string. */ if (length > stringPtr->maxChars) { stringPtr = stringAttemptRealloc(stringPtr, length); if (stringPtr == NULL) { @@ -954,11 +1083,11 @@ SET_STRING(objPtr, stringPtr); stringPtr->maxChars = length; } /* - * Mark the new end of the unicode string. + * Mark the new end of the Unicode string. */ stringPtr->unicode[length] = 0; stringPtr->numChars = length; stringPtr->hasUnicode = 1; @@ -988,47 +1117,48 @@ */ void Tcl_SetUnicodeObj( Tcl_Obj *objPtr, /* The object to set the string of. */ - const Tcl_UniChar *unicode, /* The unicode string used to initialize the + const Tcl_UniChar *unicode, /* The Unicode string used to initialize the * object. */ - size_t numChars) /* Number of characters in the unicode + Tcl_Size numChars) /* Number of characters in the Unicode * string. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetUnicodeObj"); } - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); SetUnicodeObj(objPtr, unicode, numChars); } -static size_t +static Tcl_Size UnicodeLength( const Tcl_UniChar *unicode) { - size_t numChars = 0; + Tcl_Size numChars = 0; if (unicode) { - while ((numChars != TCL_INDEX_NONE) && (unicode[numChars] != 0)) { + /* 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 + const Tcl_UniChar *unicode, /* The Unicode string used to initialize the * object. */ - size_t numChars) /* Number of characters in the unicode + Tcl_Size numChars) /* Number of characters in the Unicode * string. */ { String *stringPtr; - if (numChars == TCL_INDEX_NONE) { + if (numChars < 0) { numChars = UnicodeLength(unicode); } /* * Allocate enough space for the String structure + Unicode string. @@ -1069,24 +1199,24 @@ void Tcl_AppendLimitedToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* Points to the bytes to append to the * object. */ - size_t length, /* The number of bytes available to be + Tcl_Size length, /* The number of bytes available to be * appended from "bytes". If -1, then * all bytes up to a NUL byte are available. */ - size_t limit, /* The maximum number of bytes to append to + Tcl_Size limit, /* The maximum number of bytes to append to * the object. */ const char *ellipsis) /* Ellipsis marker string, appended to the * object to indicate not all available bytes * at "bytes" were appended. */ { String *stringPtr; - size_t toCopy = 0; - size_t eLen = 0; + Tcl_Size toCopy = 0; + Tcl_Size eLen = 0; - if (length == TCL_INDEX_NONE) { + if (length < 0) { length = (bytes ? strlen(bytes) : 0); } if (length == 0) { return; } @@ -1100,14 +1230,14 @@ if (ellipsis == NULL) { ellipsis = "..."; } eLen = strlen(ellipsis); while (eLen > limit) { - eLen = TclUtfPrev(ellipsis+eLen, ellipsis) - ellipsis; + eLen = Tcl_UtfPrev(ellipsis+eLen, ellipsis) - ellipsis; } - toCopy = TclUtfPrev(bytes+limit+1-eLen, bytes) - bytes; + toCopy = Tcl_UtfPrev(bytes+limit+1-eLen, bytes) - bytes; } /* * If objPtr has a valid Unicode rep, then append the Unicode conversion * of "bytes" to the objPtr's Unicode rep, otherwise append "bytes" to @@ -1119,11 +1249,17 @@ } SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); - if (stringPtr->hasUnicode && (stringPtr->numChars+1) > 1) { + /* 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); } @@ -1130,11 +1266,11 @@ if (length <= limit) { return; } stringPtr = GET_STRING(objPtr); - if (stringPtr->hasUnicode && (stringPtr->numChars+1) > 1) { + if (stringPtr->hasUnicode && (stringPtr->numChars) > 0) { AppendUtfToUnicodeRep(objPtr, ellipsis, eLen); } else { AppendUtfToUtfRep(objPtr, ellipsis, eLen); } } @@ -1159,24 +1295,24 @@ void Tcl_AppendToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* Points to the bytes to append to the * object. */ - size_t length) /* The number of bytes to append from "bytes". - * If -1, then append all bytes up to NUL + Tcl_Size length) /* The number of bytes to append from "bytes". + * If TCL_INDEX_NONE, then append all bytes up to NUL * byte. */ { - Tcl_AppendLimitedToObj(objPtr, bytes, length, TCL_INDEX_NONE, NULL); + Tcl_AppendLimitedToObj(objPtr, bytes, length, TCL_SIZE_MAX, NULL); } /* *---------------------------------------------------------------------- * - * TclAppendUnicodeToObj -- + * Tcl_AppendUnicodeToObj -- * * This function appends a Unicode string to an object in the most - * efficient manner possible. Length must be >= 0. + * efficient manner possible. * * Results: * None. * * Side effects: @@ -1184,20 +1320,21 @@ * *---------------------------------------------------------------------- */ void -TclAppendUnicodeToObj( +Tcl_AppendUnicodeToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ - const Tcl_UniChar *unicode, /* The unicode string to append to the + const Tcl_UniChar *unicode, /* The Unicode string to append to the * object. */ - size_t length) /* Number of chars in "unicode". */ + Tcl_Size length) /* Number of chars in Unicode. Negative + * lengths means nul terminated */ { String *stringPtr; if (Tcl_IsShared(objPtr)) { - Tcl_Panic("%s called with shared object", "TclAppendUnicodeToObj"); + Tcl_Panic("%s called with shared object", "Tcl_AppendUnicodeToObj"); } if (length == 0) { return; } @@ -1242,36 +1379,36 @@ Tcl_AppendObjToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ Tcl_Obj *appendObjPtr) /* Object to append. */ { String *stringPtr; - size_t length = 0, numChars; - size_t appendNumChars = TCL_INDEX_NONE; + Tcl_Size length = 0, numChars; + Tcl_Size appendNumChars = TCL_INDEX_NONE; const char *bytes; - /* - * Special case: second object is standard-empty is fast case. We know - * 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); + 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_GetByteArrayFromObj(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 @@ -1283,14 +1420,14 @@ * cases. * * First, get the lengths. */ - size_t lengthSrc = 0; + Tcl_Size lengthSrc = 0; - (void) TclGetByteArrayFromObj(objPtr, &length); - (void) TclGetByteArrayFromObj(appendObjPtr, &lengthSrc); + (void) Tcl_GetByteArrayFromObj(objPtr, &length); + (void) Tcl_GetByteArrayFromObj(appendObjPtr, &lengthSrc); /* * Grow buffer enough for the append. */ @@ -1306,11 +1443,11 @@ * Now do the append knowing that buffer growth cannot cause any * trouble. */ TclAppendBytesToByteArray(objPtr, - Tcl_GetByteArrayFromObj(appendObjPtr, NULL), lengthSrc); + Tcl_GetByteArrayFromObj(appendObjPtr, (Tcl_Size *) NULL), lengthSrc); return; } /* * Must append as strings. @@ -1317,10 +1454,17 @@ */ 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. */ @@ -1327,17 +1471,17 @@ if (stringPtr->hasUnicode) { /* * If appendObjPtr is not of the "String" type, don't convert it. */ - if (TclHasIntRep(appendObjPtr, &tclStringType)) { + if (TclHasInternalRep(appendObjPtr, &tclStringType)) { Tcl_UniChar *unicode = - TclGetUnicodeFromObj(appendObjPtr, &numChars); + Tcl_GetUnicodeFromObj(appendObjPtr, &numChars); AppendUnicodeToUnicodeRep(objPtr, unicode, numChars); } else { - bytes = TclGetStringFromObj(appendObjPtr, &length); + bytes = Tcl_GetStringFromObj(appendObjPtr, &length); AppendUtfToUnicodeRep(objPtr, bytes, length); } return; } @@ -1345,33 +1489,33 @@ * 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); + bytes = Tcl_GetStringFromObj(appendObjPtr, &length); numChars = stringPtr->numChars; - if ((numChars != TCL_INDEX_NONE) && TclHasIntRep(appendObjPtr, &tclStringType)) { + if ((numChars >= 0) && TclHasInternalRep(appendObjPtr, &tclStringType)) { String *appendStringPtr = GET_STRING(appendObjPtr); appendNumChars = appendStringPtr->numChars; } AppendUtfToUtfRep(objPtr, bytes, length); - if ((numChars != TCL_INDEX_NONE) && (appendNumChars != TCL_INDEX_NONE)) { + if ((numChars >= 0) && (appendNumChars >= 0)) { stringPtr->numChars = numChars + appendNumChars; } } /* *---------------------------------------------------------------------- * * AppendUnicodeToUnicodeRep -- * - * This function appends the contents of "unicode" to the Unicode rep of - * "objPtr". objPtr must already have a valid Unicode rep. + * Appends the contents of unicode to the Unicode rep of + * objPtr, which must already have a valid Unicode rep. * * Results: * None. * * Side effects: @@ -1382,16 +1526,16 @@ static void AppendUnicodeToUnicodeRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const Tcl_UniChar *unicode, /* String to append. */ - size_t appendNumChars) /* Number of chars of "unicode" to append. */ + Tcl_Size appendNumChars) /* Number of chars of "unicode" to append. */ { String *stringPtr; - size_t numChars; + Tcl_Size numChars; - if (appendNumChars == TCL_INDEX_NONE) { + if (appendNumChars < 0) { appendNumChars = UnicodeLength(unicode); } if (appendNumChars == 0) { return; } @@ -1398,42 +1542,42 @@ SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); /* - * If not enough space has been allocated for the unicode rep, reallocate + * If not enough space has been allocated for the Unicode rep, reallocate * the internal rep object with additional space. First try to double the * required allocation; if that fails, try a more modest increase. See the * "TCL STRING GROWTH ALGORITHM" comment at the top of this file for an * explanation of this growth algorithm. */ numChars = stringPtr->numChars + appendNumChars; if (numChars > stringPtr->maxChars) { - size_t index = TCL_INDEX_NONE; + Tcl_Size offset = -1; /* - * Protect against case where unicode points into the existing + * Protect against case where Unicode points into the existing * stringPtr->unicode array. Force it to follow any relocations due to * the reallocs below. */ if (unicode && unicode >= stringPtr->unicode && unicode <= stringPtr->unicode + stringPtr->maxChars) { - index = unicode - stringPtr->unicode; + offset = unicode - stringPtr->unicode; } GrowUnicodeBuffer(objPtr, numChars); stringPtr = GET_STRING(objPtr); /* - * Relocate unicode if needed; see above. + * Relocate Unicode if needed; see above. */ - if (index != TCL_INDEX_NONE) { - unicode = stringPtr->unicode + index; + if (offset >= 0) { + unicode = stringPtr->unicode + offset; } } /* * Copy the new string onto the end of the old string, then add the @@ -1470,11 +1614,11 @@ static void AppendUnicodeToUtfRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const Tcl_UniChar *unicode, /* String to convert to UTF. */ - size_t numChars) /* Number of chars of "unicode" to convert. */ + Tcl_Size numChars) /* Number of chars of Unicode to convert. */ { String *stringPtr = GET_STRING(objPtr); numChars = ExtendStringRepWithUnicode(objPtr, unicode, numChars); @@ -1503,11 +1647,11 @@ static void AppendUtfToUnicodeRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* String to convert to Unicode. */ - size_t numBytes) /* Number of bytes of "bytes" to convert. */ + Tcl_Size numBytes) /* Number of bytes of "bytes" to convert. */ { String *stringPtr; if (numBytes == 0) { return; @@ -1539,14 +1683,14 @@ static void AppendUtfToUtfRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* String to append. */ - size_t numBytes) /* Number of bytes of "bytes" to append. */ + Tcl_Size numBytes) /* Number of bytes of "bytes" to append. */ { String *stringPtr; - size_t newLength, oldLength; + Tcl_Size newLength, oldLength; if (numBytes == 0) { return; } @@ -1557,24 +1701,27 @@ if (objPtr->bytes == NULL) { objPtr->length = 0; } oldLength = objPtr->length; + if (numBytes > TCL_SIZE_MAX - oldLength) { + Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", TCL_SIZE_MAX); + } newLength = numBytes + oldLength; stringPtr = GET_STRING(objPtr); if (newLength > stringPtr->allocated) { - size_t offset = TCL_INDEX_NONE; + Tcl_Size offset = -1; /* * Protect against case where unicode points into the existing * stringPtr->unicode array. Force it to follow any relocations due to * the reallocs below. */ - if (bytes && bytes >= objPtr->bytes - && bytes <= objPtr->bytes + objPtr->length) { + if (bytes && objPtr->bytes && (bytes >= objPtr->bytes) + && (bytes <= objPtr->bytes + objPtr->length)) { offset = bytes - objPtr->bytes; } /* * TODO: consider passing flag=1: no overalloc on first append. This @@ -1585,20 +1732,20 @@ /* * Relocate bytes if needed; see above. */ - if (offset != TCL_INDEX_NONE) { + if (offset >= 0) { bytes = objPtr->bytes + offset; } } /* * Invalidate the unicode data. */ - stringPtr->numChars = TCL_INDEX_NONE; + stringPtr->numChars = -1; stringPtr->hasUnicode = 0; if (bytes) { memmove(objPtr->bytes + oldLength, bytes, numBytes); } @@ -1670,16 +1817,16 @@ int Tcl_AppendFormatToObj( Tcl_Interp *interp, Tcl_Obj *appendObj, const char *format, - int objc, + Tcl_Size objc, Tcl_Obj *const objv[]) { const char *span = format, *msg, *errCode; - int objIndex = 0, gotXpg = 0, gotSequential = 0; - size_t originalLength, limit, numBytes = 0; + int gotXpg = 0, gotSequential = 0; + Tcl_Size objIndex = 0, originalLength, limit, numBytes = 0; Tcl_UniChar ch = 0; static const char *mixedXPG = "cannot mix \"%\" and \"%n$\" conversion specifiers"; static const char *const badIndex[2] = { "not enough arguments for all format specifiers", @@ -1688,26 +1835,27 @@ 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; + (void)Tcl_GetStringFromObj(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 width, gotPrecision, precision, sawFlag, useShort = 0, useBig = 0; + int gotPrecision, sawFlag, useShort = 0, useBig = 0; + Tcl_Size width, precision; #ifndef TCL_WIDE_INT_IS_LONG int useWide = 0; #endif - int newXpg, numChars, allocSegment = 0, segmentLimit; - size_t segmentNumBytes; + int newXpg, allocSegment = 0; + Tcl_Size numChars, segmentLimit, segmentNumBytes; Tcl_Obj *segment; int step = TclUtfToUniChar(format, &ch); format += step; if (ch != '%') { @@ -1810,25 +1958,29 @@ * Step 3. Minimum field width. */ width = 0; if (isdigit(UCHAR(ch))) { - width = strtoul(format, &end, 10); - if (width < 0) { + /* 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 >= TCL_SIZE_MAX) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } + width = (Tcl_Size)ull; format = end; step = TclUtfToUniChar(format, &ch); } else if (ch == '*') { if (objIndex >= objc - 1) { msg = badIndex[gotXpg]; errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH"; goto errorMsg; } - if (TclGetIntFromObj(interp, objv[objIndex], &width) != TCL_OK) { + if (TclGetSizeIntFromObj(interp, objv[objIndex], &width) != TCL_OK) { goto error; } if (width < 0) { width = -width; gotMinus = 1; @@ -1835,11 +1987,11 @@ } objIndex++; format += step; step = TclUtfToUniChar(format, &ch); } - if (width > (int) limit) { + if (width > limit) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } @@ -1852,20 +2004,29 @@ gotPrecision = 1; format += step; step = TclUtfToUniChar(format, &ch); } if (isdigit(UCHAR(ch))) { - precision = strtoul(format, &end, 10); + /* 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 >= TCL_SIZE_MAX) { + msg = overflow; + errCode = "OVERFLOW"; + goto errorMsg; + } + precision = (Tcl_Size)ull; format = end; step = TclUtfToUniChar(format, &ch); } else if (ch == '*') { if (objIndex >= objc - 1) { msg = badIndex[gotXpg]; errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH"; goto errorMsg; } - if (TclGetIntFromObj(interp, objv[objIndex], &precision) + if (TclGetSizeIntFromObj(interp, objv[objIndex], &precision) != TCL_OK) { goto error; } /* @@ -1940,11 +2101,15 @@ goto errorMsg; case 's': if (gotPrecision) { numChars = Tcl_GetCharLength(segment); if (precision < numChars) { - segment = Tcl_GetRange(segment, 0, precision - 1); + if (precision < 1) { + TclNewObj(segment); + } else { + segment = Tcl_GetRange(segment, 0, precision - 1); + } numChars = precision; Tcl_IncrRefCount(segment); allocSegment = 1; } } @@ -1954,15 +2119,14 @@ 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); + if ((unsigned)code > 0x10FFFF) { + code = 0xFFFD; } + length = Tcl_UniCharToUtf(code, buf); segment = Tcl_NewStringObj(buf, length); Tcl_IncrRefCount(segment); allocSegment = 1; break; } @@ -1978,11 +2142,12 @@ 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; + int isNegative = 0; + Tcl_Size toAppend; #ifndef TCL_WIDE_INT_IS_LONG if (ch == 'p') { useWide = 1; } @@ -2036,11 +2201,11 @@ if (l == (long) 0) gotHash = 0; } TclNewObj(segment); allocSegment = 1; - segmentLimit = INT_MAX; + segmentLimit = TCL_SIZE_MAX; Tcl_IncrRefCount(segment); if ((isNegative || gotPlus || gotSpace) && (useBig || ch=='d')) { Tcl_AppendToObj(segment, (isNegative ? "-" : gotPlus ? "+" : " "), 1); @@ -2061,16 +2226,20 @@ break; case 'b': Tcl_AppendToObj(segment, "0b", 2); segmentLimit -= 2; break; + case 'd': + Tcl_AppendToObj(segment, "0d", 2); + segmentLimit -= 2; + break; } } switch (ch) { case 'd': { - size_t length; + Tcl_Size length; Tcl_Obj *pure; const char *bytes; if (useShort) { TclNewIntObj(pure, s); @@ -2082,11 +2251,11 @@ pure = Tcl_NewBignumObj(&big); } else { TclNewIntObj(pure, l); } Tcl_IncrRefCount(pure); - bytes = TclGetStringFromObj(pure, &length); + bytes = Tcl_GetStringFromObj(pure, &length); /* * Already did the sign above. */ @@ -2101,25 +2270,25 @@ * entirely of one-byte encoded characters, so "length" is the * number of chars. */ if (gotPrecision) { - if (length < (size_t)precision) { + if (length < precision) { segmentLimit -= precision - length; } - while (length < (size_t)precision) { + while (length < precision) { Tcl_AppendToObj(segment, "0", 1); length++; } gotZero = 0; } if (gotZero) { length += Tcl_GetCharLength(segment); - if (length < (size_t)width) { + if (length < width) { segmentLimit -= width - length; } - while (length < (size_t)width) { + while (length < width) { Tcl_AppendToObj(segment, "0", 1); length++; } } if (toAppend > segmentLimit) { @@ -2139,11 +2308,11 @@ case 'X': case 'b': { Tcl_WideUInt bits = 0; Tcl_WideInt numDigits = 0; int numBits = 4, base = 16, index = 0, shift = 0; - size_t length; + Tcl_Size length; Tcl_Obj *pure; char *bytes; if (ch == 'u') { base = 10; @@ -2233,25 +2402,25 @@ } if (useBig) { mp_clear(&big); } if (gotPrecision) { - if (length < (size_t)precision) { + if (length < precision) { segmentLimit -= precision - length; } - while (length < (size_t)precision) { + while (length < precision) { Tcl_AppendToObj(segment, "0", 1); length++; } gotZero = 0; } if (gotZero) { length += Tcl_GetCharLength(segment); - if (length < (size_t)width) { + if (length < width) { segmentLimit -= width - length; } - while (length < (size_t)width) { + while (length < width) { Tcl_AppendToObj(segment, "0", 1); length++; } } if (toAppend > segmentLimit) { @@ -2300,19 +2469,21 @@ } if (gotPlus) { *p++ = '+'; } if (width) { - p += sprintf(p, "%d", width); + p += snprintf( + p, TCL_INTEGER_SPACE, "%" TCL_SIZE_MODIFIER "d", width); if (width > length) { length = width; } } if (gotPrecision) { *p++ = '.'; - p += sprintf(p, "%d", precision); - if (precision > INT_MAX - length) { + p += snprintf( + p, TCL_INTEGER_SPACE, "%" TCL_SIZE_MODIFIER "d", precision); + if (precision > TCL_SIZE_MAX - length) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } length += precision; @@ -2331,11 +2502,11 @@ msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } bytes = TclGetString(segment); - if (!Tcl_AttemptSetObjLength(segment, sprintf(bytes, spec, d))) { + if (!Tcl_AttemptSetObjLength(segment, snprintf(bytes, segment->length, spec, d))) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } if (ch == 'A') { @@ -2348,11 +2519,11 @@ } default: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad field specifier \"%c\"", ch)); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", (void *)NULL); } goto error; } if (width>0 && numChars<0) { @@ -2366,11 +2537,11 @@ Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1); numChars++; } } - (void)TclGetStringFromObj(segment, &segmentNumBytes); + (void)Tcl_GetStringFromObj(segment, &segmentNumBytes); if (segmentNumBytes > limit) { if (allocSegment) { Tcl_DecrRefCount(segment); } msg = overflow; @@ -2408,11 +2579,11 @@ return TCL_OK; errorMsg: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1)); - Tcl_SetErrorCode(interp, "TCL", "FORMAT", errCode, NULL); + Tcl_SetErrorCode(interp, "TCL", "FORMAT", errCode, (void *)NULL); } error: Tcl_SetObjLength(appendObj, originalLength); return TCL_ERROR; } @@ -2433,11 +2604,11 @@ Tcl_Obj * Tcl_Format( Tcl_Interp *interp, const char *format, - int objc, + Tcl_Size objc, Tcl_Obj *const objv[]) { int result; Tcl_Obj *objPtr; @@ -2466,11 +2637,12 @@ AppendPrintfToObjVA( Tcl_Obj *objPtr, const char *format, va_list argList) { - int code, objc; + int code; + Tcl_Size objc; Tcl_Obj **objv, *list; const char *p; TclNewObj(list); p = format; @@ -2510,11 +2682,11 @@ * Within that buffer, we trim both ends if needed so that we * copy only whole characters, and avoid copying any partial * multi-byte characters. */ - q = TclUtfPrev(end, bytes); + q = Tcl_UtfPrev(end, bytes); if (!Tcl_UtfCharComplete(q, (end - q))) { end = q; } q = bytes + 4; @@ -2526,16 +2698,20 @@ Tcl_ListObjAppendElement(NULL, list, Tcl_NewStringObj(bytes , (end - bytes))); break; } + case 'p': + if (sizeof(size_t) == sizeof(Tcl_WideInt)) { + size = 2; + } + /* FALLTHRU */ case 'c': case 'i': case 'u': case 'd': case 'o': - case 'p': case 'x': case 'X': seekingConversion = 0; switch (size) { case -1: @@ -2627,11 +2803,11 @@ default: p++; } } while (seekingConversion); } - TclListObjGetElements(NULL, list, &objc, &objv); + TclListObjGetElementsM(NULL, list, &objc, &objv); code = Tcl_AppendFormatToObj(NULL, objPtr, format, objc, objv); if (code != TCL_OK) { Tcl_AppendPrintfToObj(objPtr, "Unable to format \"%s\" with supplied arguments: %s", format, TclGetString(list)); @@ -2713,16 +2889,16 @@ */ char * TclGetStringStorage( Tcl_Obj *objPtr, - size_t *sizePtr) + Tcl_Size *sizePtr) { String *stringPtr; - if (!TclHasIntRep(objPtr, &tclStringType) || objPtr->bytes == NULL) { - return TclGetStringFromObj(objPtr, sizePtr); + if (!TclHasInternalRep(objPtr, &tclStringType) || objPtr->bytes == NULL) { + return Tcl_GetStringFromObj(objPtr, sizePtr); } stringPtr = GET_STRING(objPtr); *sizePtr = stringPtr->allocated; return objPtr->bytes; @@ -2747,17 +2923,20 @@ Tcl_Obj * TclStringRepeat( Tcl_Interp *interp, Tcl_Obj *objPtr, - size_t count, + Tcl_Size count, int flags) { Tcl_Obj *objResultPtr; int inPlace = flags & TCL_STRING_IN_PLACE; - size_t length = 0, unichar = 0, done = 1; + Tcl_Size length = 0; + int unichar = 0; + Tcl_Size done = 1; int binary = TclIsPureByteArray(objPtr); + Tcl_Size maxCount; /* assert (count >= 2) */ /* * Analyze to determine what representation result should be. @@ -2765,56 +2944,64 @@ * Produce pure bytearray when possible. * Error on overflow. */ if (!binary) { - if (TclHasIntRep(objPtr, &tclStringType)) { + if (TclHasInternalRep(objPtr, &tclStringType)) { String *stringPtr = GET_STRING(objPtr); if (stringPtr->hasUnicode) { unichar = 1; } } } if (binary) { /* Result will be pure byte array. Pre-size it */ - (void)TclGetByteArrayFromObj(objPtr, &length); + (void)Tcl_GetByteArrayFromObj(objPtr, &length); + maxCount = TCL_SIZE_MAX; } else if (unichar) { /* Result will be pure Tcl_UniChar array. Pre-size it. */ - (void)TclGetUnicodeFromObj(objPtr, &length); + (void)Tcl_GetUnicodeFromObj(objPtr, &length); + maxCount = TCL_SIZE_MAX/sizeof(Tcl_UniChar); } else { /* Result will be concat of string reps. Pre-size it. */ - (void)TclGetStringFromObj(objPtr, &length); + (void)Tcl_GetStringFromObj(objPtr, &length); + maxCount = TCL_SIZE_MAX; } if (length == 0) { /* Any repeats of empty is empty. */ return objPtr; } - if (count > INT_MAX/length) { + /* maxCount includes space for null */ + if (count > (maxCount-1)) { if (interp) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "max size for a Tcl value (%d bytes) exceeded", INT_MAX)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + 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", (void *)NULL); } return NULL; } if (binary) { /* Efficiently produce a pure byte array result */ objResultPtr = (!inPlace || Tcl_IsShared(objPtr)) ? Tcl_DuplicateObj(objPtr) : objPtr; + /* Allocate count*length space */ Tcl_SetByteArrayLength(objResultPtr, count*length); /* PANIC? */ Tcl_SetByteArrayLength(objResultPtr, length); while (count - done > done) { Tcl_AppendObjToObj(objResultPtr, objResultPtr); done *= 2; } TclAppendBytesToByteArray(objResultPtr, - Tcl_GetByteArrayFromObj(objResultPtr, NULL), + Tcl_GetByteArrayFromObj(objResultPtr, (Tcl_Size *) NULL), (count - done) * length); } else if (unichar) { /* * Efficiently produce a pure Tcl_UniChar array result. */ @@ -2824,44 +3011,46 @@ } 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_Z_MODIFIER "u bytes", + TCL_SIZE_MODIFIER "d bytes", STRING_SIZE(count*length))); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); } return NULL; } Tcl_SetObjLength(objResultPtr, length); while (count - done > done) { Tcl_AppendObjToObj(objResultPtr, objResultPtr); done *= 2; } - TclAppendUnicodeToObj(objResultPtr, Tcl_GetUnicode(objResultPtr), + Tcl_AppendUnicodeToObj(objResultPtr, Tcl_GetUnicode(objResultPtr), (count - done) * length); } else { /* * Efficiently concatenate string reps. */ if (!inPlace || Tcl_IsShared(objPtr)) { objResultPtr = Tcl_NewStringObj(TclGetString(objPtr), length); } else { - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); objResultPtr = objPtr; } + /* TODO - overflow check */ if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "string size overflow: unable to alloc %" TCL_Z_MODIFIER "u bytes", + "string size overflow: unable to alloc %" TCL_SIZE_MODIFIER "d bytes", count*length)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); } return NULL; } Tcl_SetObjLength(objResultPtr, length); while (count - done > done) { @@ -2892,27 +3081,33 @@ */ Tcl_Obj * TclStringCat( Tcl_Interp *interp, - int objc, + Tcl_Size objc, Tcl_Obj * const objv[], int flags) { Tcl_Obj *objResultPtr, * const *ov; - int oc, binary = 1; - size_t length = 0; - int allowUniChar = 1, requestUniChar = 0; - int first = objc - 1; /* Index of first value possibly not empty */ - int last = 0; /* Index of last value possibly not empty */ - int inPlace = flags & TCL_STRING_IN_PLACE; + int binary = 1; + Tcl_Size oc, length = 0; + int allowUniChar = 1, requestUniChar = 0, forceUniChar = 0; + Tcl_Size first = objc - 1; /* Index of first value possibly not empty */ + Tcl_Size last = 0; /* Index of last value possibly not empty */ + int inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv); /* assert ( objc >= 0 ) */ if (objc <= 1) { - /* Only one or no objects; return first or empty */ - return objc ? objv[0] : Tcl_NewObj(); + if (objc != 1) { + /* Negative (shouldn't be) no objects; return empty */ + Tcl_Obj *obj; + TclNewObj(obj); + return obj; + } + /* One object; return first */ + return objv[0]; } /* assert ( objc >= 2 ) */ /* @@ -2935,19 +3130,21 @@ * Non-empty string rep. Not a pure bytearray, so we won't * create a pure bytearray. */ binary = 0; - if ((objPtr->typePtr) && (objPtr->typePtr != &tclStringType)) { + if (ov > objv+1 && ISCONTINUATION(TclGetString(objPtr))) { + forceUniChar = 1; + } else 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)) { + if (TclHasInternalRep(objPtr, &tclStringType)) { /* Have a pure Unicode value; ask to preserve it */ requestUniChar = 1; } else { /* Have another type; prevent shimmer */ allowUniChar = 0; @@ -2958,11 +3155,11 @@ if (binary) { /* * Result will be pure byte array. Pre-size it */ - size_t numBytes = 0; + Tcl_Size numBytes = 0; ov = objv; oc = objc; do { Tcl_Obj *objPtr = *ov++; @@ -2971,22 +3168,25 @@ * value we know we can safely use, or it is an empty string. * We don't need to count bytes for the empty strings. */ if (TclIsPureByteArray(objPtr)) { - (void)TclGetByteArrayFromObj(objPtr, &numBytes); /* PANIC? */ + (void)Tcl_GetByteArrayFromObj(objPtr, &numBytes); /* PANIC? */ if (numBytes) { last = objc - oc; if (length == 0) { first = last; + } + if (length > (TCL_SIZE_MAX-numBytes)) { + goto overflow; } length += numBytes; } } } while (--oc); - } else if (allowUniChar && requestUniChar) { + } else if ((allowUniChar && requestUniChar) || forceUniChar) { /* * Result will be pure Tcl_UniChar array. Pre-size it. */ ov = objv; @@ -2993,17 +3193,20 @@ oc = objc; do { Tcl_Obj *objPtr = *ov++; if ((objPtr->bytes == NULL) || (objPtr->length)) { - size_t numChars; + Tcl_Size numChars; - (void)TclGetUnicodeFromObj(objPtr, &numChars); /* PANIC? */ + (void)Tcl_GetUnicodeFromObj(objPtr, &numChars); /* PANIC? */ if (numChars) { last = objc - oc; if (length == 0) { first = last; + } + if (length > (Tcl_Size) ((TCL_SIZE_MAX/sizeof(Tcl_UniChar))-numChars)) { + goto overflow; } length += numChars; } } } while (--oc); @@ -3022,15 +3225,16 @@ /* assert ( pendingPtr == NULL ) */ /* assert ( length == 0 ) */ Tcl_Obj *objPtr = *ov++; - if (objPtr->bytes == NULL) { + if (objPtr->bytes == NULL + && TclCheckEmptyString(objPtr) != TCL_EMPTYSTRING_YES) { /* No string rep; Take the chance we can avoid making it */ pendingPtr = objPtr; } else { - (void)TclGetStringFromObj(objPtr, &length); /* PANIC? */ + (void)Tcl_GetStringFromObj(objPtr, &length); /* PANIC? */ } } while (--oc && (length == 0) && (pendingPtr == NULL)); /* * Either we found a possibly non-empty value, and we remember @@ -3040,11 +3244,11 @@ */ first = last = objc - oc - 1; if (oc && (length == 0)) { - size_t numBytes; + Tcl_Size numBytes; /* assert ( pendingPtr != NULL ) */ /* * There's a pending value followed by more values. Loop over @@ -3052,41 +3256,41 @@ * is found, or the pending value gets its string generated. */ do { Tcl_Obj *objPtr = *ov++; - (void)TclGetStringFromObj(objPtr, &numBytes); /* PANIC? */ + (void)Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ } while (--oc && numBytes == 0 && pendingPtr->bytes == NULL); if (numBytes) { last = objc -oc -1; } if (oc || numBytes) { - (void)TclGetStringFromObj(pendingPtr, &length); + (void)Tcl_GetStringFromObj(pendingPtr, &length); } if (length == 0) { if (numBytes) { first = last; } - } else if (numBytes + length > (size_t)INT_MAX) { + } else if (numBytes > (TCL_SIZE_MAX - length)) { goto overflow; } length += numBytes; } } while (oc && (length == 0)); while (oc) { - size_t numBytes; + Tcl_Size numBytes; Tcl_Obj *objPtr = *ov++; /* assert ( length > 0 && pendingPtr == NULL ) */ TclGetString(objPtr); /* PANIC? */ numBytes = objPtr->length; if (numBytes) { last = objc - oc; - if (numBytes + length > (size_t)INT_MAX) { + if (numBytes > (TCL_SIZE_MAX - length)) { goto overflow; } length += numBytes; } --oc; @@ -3098,10 +3302,11 @@ /* 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; @@ -3108,15 +3313,15 @@ /* * Broken interface! Byte array value routines offer no way to handle * failure to allocate enough space. Following stanza may panic. */ - if (inPlace && !Tcl_IsShared(*objv)) { - size_t start = 0; + if (inPlace) { + Tcl_Size start = 0; objResultPtr = *objv++; objc--; - (void)TclGetByteArrayFromObj(objResultPtr, &start); + (void)Tcl_GetByteArrayFromObj(objResultPtr, &start); dst = Tcl_SetByteArrayLength(objResultPtr, length) + start; } else { objResultPtr = Tcl_NewByteArrayObj(NULL, length); dst = Tcl_SetByteArrayLength(objResultPtr, length); } @@ -3128,35 +3333,35 @@ * value we know we can safely use, or it is an empty string. * We don't need to copy bytes from the empty strings. */ if (TclIsPureByteArray(objPtr)) { - size_t more = 0; - unsigned char *src = TclGetByteArrayFromObj(objPtr, &more); + Tcl_Size more = 0; + unsigned char *src = Tcl_GetByteArrayFromObj(objPtr, &more); memcpy(dst, src, more); dst += more; } } - } else if (allowUniChar && requestUniChar) { + } else if ((allowUniChar && requestUniChar) || forceUniChar) { /* Efficiently produce a pure Tcl_UniChar array result */ Tcl_UniChar *dst; - if (inPlace && !Tcl_IsShared(*objv)) { - size_t start; + if (inPlace) { + Tcl_Size start; objResultPtr = *objv++; objc--; /* Ugly interface! Force resize of the unicode array. */ - (void)TclGetUnicodeFromObj(objResultPtr, &start); + (void)Tcl_GetUnicodeFromObj(objResultPtr, &start); Tcl_InvalidateStringRep(objResultPtr); if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "concatenation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes", STRING_SIZE(length))); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); } return NULL; } dst = Tcl_GetUnicode(objResultPtr) + start; } else { @@ -3169,69 +3374,69 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); } return NULL; } dst = Tcl_GetUnicode(objResultPtr); } while (objc--) { Tcl_Obj *objPtr = *objv++; if ((objPtr->bytes == NULL) || (objPtr->length)) { - size_t more; - Tcl_UniChar *src = TclGetUnicodeFromObj(objPtr, &more); + Tcl_Size more; + Tcl_UniChar *src = Tcl_GetUnicodeFromObj(objPtr, &more); memcpy(dst, src, more * sizeof(Tcl_UniChar)); dst += more; } } } else { /* Efficiently concatenate string reps */ char *dst; - if (inPlace && !Tcl_IsShared(*objv)) { - size_t start; + if (inPlace) { + Tcl_Size start; objResultPtr = *objv++; objc--; - (void)TclGetStringFromObj(objResultPtr, &start); + (void)Tcl_GetStringFromObj(objResultPtr, &start); if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "concatenation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes", + "concatenation failed: unable to alloc %" TCL_SIZE_MODIFIER "d bytes", length)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); } return NULL; } dst = TclGetString(objResultPtr) + start; /* assert ( length > start ) */ - TclFreeIntRep(objResultPtr); + TclFreeInternalRep(objResultPtr); } else { TclNewObj(objResultPtr); /* PANIC? */ if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) { Tcl_DecrRefCount(objResultPtr); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "concatenation failed: unable to alloc %" TCL_Z_MODIFIER "u bytes", + "concatenation failed: unable to alloc %" TCL_SIZE_MODIFIER "d bytes", length)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)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); + Tcl_Size more; + char *src = Tcl_GetStringFromObj(objPtr, &more); memcpy(dst, src, more); dst += more; } } @@ -3241,12 +3446,12 @@ return objResultPtr; overflow: if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "max size for a Tcl value (%d bytes) exceeded", INT_MAX)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + "max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", TCL_SIZE_MAX)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); } return NULL; } /* @@ -3269,20 +3474,22 @@ TclStringCmp( Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr, int checkEq, /* comparison is only for equality */ int nocase, /* comparison is not case sensitive */ - size_t reqlength) /* requested length */ + Tcl_Size reqlength) /* requested length in characters; + * TCL_INDEX_NONE to compare whole strings */ { - char *s1, *s2; + const char *s1, *s2; int empty, match; - size_t length, s1len = 0, s2len = 0; + Tcl_Size length, s1len = 0, s2len = 0; memCmpFn_t memCmpFn; if ((reqlength == 0) || (value1Ptr == value2Ptr)) { /* * Always match at 0 chars of if it is the same obj. + * Note: as documented reqlength negative means it is ignored */ match = 0; } else { if (!nocase && TclIsPureByteArray(value1Ptr) && TclIsPureByteArray(value2Ptr)) { @@ -3291,51 +3498,57 @@ * type conversions and it is much faster. Only do this if we're * case-sensitive (which is all that really makes sense with byte * arrays anyway, and we have no memcasecmp() for some reason... :^) */ - s1 = (char *) TclGetByteArrayFromObj(value1Ptr, &s1len); - s2 = (char *) TclGetByteArrayFromObj(value2Ptr, &s2len); + s1 = (char *) Tcl_GetByteArrayFromObj(value1Ptr, &s1len); + s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len); memCmpFn = memcmp; - } else if (TclHasIntRep(value1Ptr, &tclStringType) - && TclHasIntRep(value2Ptr, &tclStringType)) { + } else if (TclHasInternalRep(value1Ptr, &tclStringType) + && TclHasInternalRep(value2Ptr, &tclStringType)) { /* - * Do a unicode-specific comparison if both of the args are of - * String type. If the char length == byte length, we can do a - * memcmp. In benchmark testing this proved the most efficient - * check between the unicode and string comparison operations. + * Do a Unicode-specific comparison if both of the args are of String + * type. If the char length == byte length, we can do a memcmp. In + * benchmark testing this proved the most efficient check between the + * Unicode and string comparison operations. */ if (nocase) { - s1 = (char *) TclGetUnicodeFromObj(value1Ptr, &s1len); - s2 = (char *) TclGetUnicodeFromObj(value2Ptr, &s2len); + s1 = (char *) Tcl_GetUnicodeFromObj(value1Ptr, &s1len); + s2 = (char *) Tcl_GetUnicodeFromObj(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)) { + /* each byte represents one character so s1l3n, s2l3n, and + * reqlength are in both bytes and characters + */ s1 = value1Ptr->bytes; s2 = value2Ptr->bytes; memCmpFn = memcmp; } else { s1 = (char *) Tcl_GetUnicode(value1Ptr); s2 = (char *) Tcl_GetUnicode(value2Ptr); if ( -#ifdef WORDS_BIGENDIAN +#if defined(WORDS_BIGENDIAN) 1 #else checkEq #endif ) { memCmpFn = memcmp; s1len *= sizeof(Tcl_UniChar); s2len *= sizeof(Tcl_UniChar); + if (reqlength > 0) { + reqlength *= sizeof(Tcl_UniChar); + } } else { - memCmpFn = (memCmpFn_t) TclUniCharNcmp; + memCmpFn = (memCmpFn_t)(void *)TclUniCharNcmp; } } } } else { empty = TclCheckEmptyString(value1Ptr); @@ -3342,11 +3555,11 @@ if (empty > 0) { switch (TclCheckEmptyString(value2Ptr)) { case -1: s1 = 0; s1len = 0; - s2 = TclGetStringFromObj(value2Ptr, &s2len); + s2 = Tcl_GetStringFromObj(value2Ptr, &s2len); break; case 0: match = -1; goto matchdone; case 1: @@ -3357,11 +3570,11 @@ } else if (TclCheckEmptyString(value2Ptr) > 0) { switch (empty) { case -1: s2 = 0; s2len = 0; - s1 = TclGetStringFromObj(value1Ptr, &s1len); + s1 = Tcl_GetStringFromObj(value1Ptr, &s1len); break; case 0: match = 1; goto matchdone; case 1: @@ -3368,14 +3581,14 @@ default: /* avoid warn: `s1` may be used uninitialized */ match = 0; goto matchdone; } } else { - s1 = TclGetStringFromObj(value1Ptr, &s1len); - s2 = TclGetStringFromObj(value2Ptr, &s2len); + s1 = Tcl_GetStringFromObj(value1Ptr, &s1len); + s2 = Tcl_GetStringFromObj(value2Ptr, &s2len); } - if (!nocase && checkEq) { + if (!nocase && checkEq && reqlength < 0) { /* * When we have equal-length we can check only for * (in)equality. We can use memcmp in all (n)eq cases because * we don't need to worry about lexical LE/BE variance. */ @@ -3388,34 +3601,38 @@ * (\xC0\x80 in Tcl's utf rep). We can use the more efficient * TclpUtfNcmp2 if we are case-sensitive and no specific * length was requested. */ - if ((reqlength == TCL_INDEX_NONE) && !nocase) { - memCmpFn = (memCmpFn_t) TclpUtfNcmp2; + if ((reqlength < 0) && !nocase) { + memCmpFn = (memCmpFn_t)(void *)TclpUtfNcmp2; } else { s1len = Tcl_NumUtfChars(s1, s1len); s2len = Tcl_NumUtfChars(s2, s2len); - memCmpFn = (memCmpFn_t) + memCmpFn = (memCmpFn_t)(void *) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp); } } } + /* At this point s1len, s2len, and reqlength should by now have been + * adjusted so that they are all in the units expected by the selected + * comparison function. + */ length = (s1len < s2len) ? s1len : s2len; - if (reqlength == TCL_INDEX_NONE) { + if (reqlength < 0) { /* - * The requested length is negative, so we ignore it by setting it - * to length + 1 so we correct the match var. + * The requested length is negative, so ignore it by setting it + * to length + 1 to correct the match var. */ reqlength = length + 1; } else if (reqlength > 0 && reqlength < length) { length = reqlength; } - if (checkEq && (s1len != s2len)) { + if (checkEq && reqlength < 0 && (s1len != s2len)) { match = 1; /* This will be reversed below. */ } else { /* * The comparison function should compare up to the minimum byte * length only. @@ -3452,18 +3669,18 @@ Tcl_Obj * TclStringFirst( Tcl_Obj *needle, Tcl_Obj *haystack, - size_t start) + Tcl_Size start) { - size_t lh = 0, ln = Tcl_GetCharLength(needle); - size_t value = TCL_INDEX_NONE; + Tcl_Size lh = 0, ln = Tcl_GetCharLength(needle); + Tcl_Size value = -1; Tcl_UniChar *checkStr, *endStr, *uh, *un; Tcl_Obj *obj; - if (start == TCL_INDEX_NONE) { + if (start < 0) { start = 0; } if (ln == 0) { /* We don't find empty substrings. Bizarre! * Whenever this routine is turned into a proper substring @@ -3471,14 +3688,14 @@ goto firstEnd; } if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) { unsigned char *end, *check, *bh; - unsigned char *bn = TclGetByteArrayFromObj(needle, &ln); + unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln); /* Find bytes in bytes */ - bh = TclGetByteArrayFromObj(haystack, &lh); + bh = Tcl_GetByteArrayFromObj(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; @@ -3517,12 +3734,12 @@ * locking down in practice more firmly just what encodings produce * what supported results for the objPtr->bytes values. For now, * do only the well-defined Tcl_UniChar array search. */ - un = TclGetUnicodeFromObj(needle, &ln); - uh = TclGetUnicodeFromObj(haystack, &lh); + un = Tcl_GetUnicodeFromObj(needle, &ln); + uh = Tcl_GetUnicodeFromObj(haystack, &lh); if ((lh < ln) || (start > lh - ln)) { /* Don't start the loop if there cannot be a valid answer */ goto firstEnd; } endStr = uh + lh; @@ -3559,14 +3776,14 @@ Tcl_Obj * TclStringLast( Tcl_Obj *needle, Tcl_Obj *haystack, - size_t last) + Tcl_Size last) { - size_t lh = 0, ln = Tcl_GetCharLength(needle); - size_t value = TCL_INDEX_NONE; + Tcl_Size lh = 0, ln = Tcl_GetCharLength(needle); + Tcl_Size value = -1; Tcl_UniChar *checkStr, *uh, *un; Tcl_Obj *obj; if (ln == 0) { /* @@ -3577,14 +3794,14 @@ */ goto lastEnd; } if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) { - unsigned char *check, *bh = TclGetByteArrayFromObj(haystack, &lh); - unsigned char *bn = TclGetByteArrayFromObj(needle, &ln); + unsigned char *check, *bh = Tcl_GetByteArrayFromObj(haystack, &lh); + unsigned char *bn = Tcl_GetByteArrayFromObj(needle, &ln); - if (last + 1 >= lh + 1) { + if (last >= lh) { last = lh - 1; } if (last + 1 < ln) { /* Don't start the loop if there cannot be a valid answer */ goto lastEnd; @@ -3600,14 +3817,14 @@ check--; } goto lastEnd; } - uh = TclGetUnicodeFromObj(haystack, &lh); - un = TclGetUnicodeFromObj(needle, &ln); + uh = Tcl_GetUnicodeFromObj(haystack, &lh); + un = Tcl_GetUnicodeFromObj(needle, &ln); - if (last + 1 >= lh + 1) { + if (last >= lh) { last = lh - 1; } if (last + 1 < ln) { /* Don't start the loop if there cannot be a valid answer */ goto lastEnd; @@ -3646,11 +3863,11 @@ static void ReverseBytes( unsigned char *to, /* Copy bytes into here... */ unsigned char *from, /* ...from here... */ - size_t count) /* Until this many are copied, */ + Tcl_Size count) /* Until this many are copied, */ /* reversing as you go. */ { unsigned char *src = from + count; if (to == from) { @@ -3676,38 +3893,39 @@ String *stringPtr; Tcl_UniChar ch = 0; int inPlace = flags & TCL_STRING_IN_PLACE; if (TclIsPureByteArray(objPtr)) { - size_t numBytes = 0; - unsigned char *from = TclGetByteArrayFromObj(objPtr, &numBytes); + Tcl_Size numBytes = 0; + unsigned char *from = Tcl_GetByteArrayFromObj(objPtr, &numBytes); if (!inPlace || Tcl_IsShared(objPtr)) { objPtr = Tcl_NewByteArrayObj(NULL, numBytes); } - ReverseBytes(Tcl_GetByteArrayFromObj(objPtr, NULL), from, numBytes); + ReverseBytes(Tcl_GetByteArrayFromObj(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)) { - Tcl_UniChar *to; - /* - * Create a non-empty, pure unicode value, so we can coax - * Tcl_SetObjLength into growing the unicode rep buffer. + * Create a non-empty, pure Unicode value, so we can coax + * Tcl_SetObjLength into growing the Unicode rep buffer. */ objPtr = Tcl_NewUnicodeObj(&ch, 1); Tcl_SetObjLength(objPtr, stringPtr->numChars); to = Tcl_GetUnicode(objPtr); + stringPtr = GET_STRING(objPtr); while (--src >= from) { *to++ = *src; } } else { /* @@ -3721,52 +3939,50 @@ } } } if (objPtr->bytes) { - size_t numChars = stringPtr->numChars; - size_t numBytes = objPtr->length; + Tcl_Size numChars = stringPtr->numChars; + Tcl_Size numBytes = objPtr->length; char *to, *from = objPtr->bytes; if (!inPlace || Tcl_IsShared(objPtr)) { TclNewObj(objPtr); Tcl_SetObjLength(objPtr, numBytes); } to = objPtr->bytes; - if ((numChars == TCL_INDEX_NONE) || (numChars < numBytes)) { + if (numChars < numBytes) { /* * Either numChars == -1 and we don't know how many chars are * represented by objPtr->bytes and we need Pass 1 just in case, * or numChars >= 0 and we know we have fewer chars than bytes, so * we know there's a multibyte character needing Pass 1. * * Pass 1. Reverse the bytes of each multi-byte character. */ - size_t charCount = 0; - size_t bytesLeft = numBytes; + Tcl_Size bytesLeft = numBytes; + int chw; while (bytesLeft) { /* * NOTE: We know that the from buffer is NUL-terminated. It's * part of the contract for objPtr->bytes values. Thus, we can * skip calling Tcl_UtfCharComplete() here. */ - size_t bytesInChar = TclUtfToUniChar(from, &ch); + int bytesInChar = Tcl_UtfToUniChar(from, &chw); ReverseBytes((unsigned char *)to, (unsigned char *)from, bytesInChar); to += bytesInChar; from += bytesInChar; bytesLeft -= bytesInChar; - charCount++; } from = to = objPtr->bytes; - stringPtr->numChars = charCount; } /* Pass 2. Reverse all the bytes. */ ReverseBytes((unsigned char *)to, (unsigned char *)from, numBytes); } @@ -3801,25 +4017,28 @@ Tcl_Obj * TclStringReplace( Tcl_Interp *interp, /* For error reporting, may be NULL */ Tcl_Obj *objPtr, /* String to act upon */ - size_t first, /* First index to replace */ - size_t count, /* How many chars to replace */ + Tcl_Size first, /* First index to replace */ + Tcl_Size count, /* How many chars to replace */ Tcl_Obj *insertPtr, /* Replacement string, may be NULL */ int flags) /* TCL_STRING_IN_PLACE => attempt in-place */ { int inPlace = flags & TCL_STRING_IN_PLACE; Tcl_Obj *result; /* Replace nothing with nothing */ - if ((insertPtr == NULL) && (count == 0)) { + if ((insertPtr == NULL) && (count <= 0)) { if (inPlace) { return objPtr; } else { return Tcl_DuplicateObj(objPtr); } + } + if (first < 0) { + first = 0; } /* * The caller very likely had to call Tcl_GetCharLength() or similar * to be able to process index values. This means it is likely that @@ -3826,12 +4045,12 @@ * objPtr is either a proper "bytearray" or a "string" or else it has * a known and short string rep. */ if (TclIsPureByteArray(objPtr)) { - size_t numBytes = 0; - unsigned char *bytes = TclGetByteArrayFromObj(objPtr, &numBytes); + Tcl_Size numBytes = 0; + unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &numBytes); if (insertPtr == NULL) { /* Replace something with nothing. */ assert ( first <= numBytes ) ; @@ -3849,13 +4068,13 @@ if ((first == 0) && (count == numBytes)) { return insertPtr; } if (TclIsPureByteArray(insertPtr)) { - size_t newBytes = 0; + Tcl_Size newBytes = 0; unsigned char *iBytes - = TclGetByteArrayFromObj(insertPtr, &newBytes); + = Tcl_GetByteArrayFromObj(insertPtr, &newBytes); if (count == newBytes && inPlace && !Tcl_IsShared(objPtr)) { /* * Removal count and replacement count are equal. * Other conditions permit. Do in-place splice. @@ -3864,16 +4083,16 @@ memcpy(bytes + first, iBytes, count); Tcl_InvalidateStringRep(objPtr); return objPtr; } - if ((size_t)newBytes > INT_MAX - (numBytes - count)) { + if (newBytes > (TCL_SIZE_MAX - (numBytes - count))) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "max size for a Tcl value (%d bytes) exceeded", - INT_MAX)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + "max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", + TCL_SIZE_MAX)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", (void *)NULL); } return NULL; } result = Tcl_NewByteArrayObj(NULL, numBytes - count + newBytes); /* PANIC? */ @@ -3894,21 +4113,21 @@ * all single-byte characters so we can index it directly. */ /* The traditional implementation... */ { - size_t numChars; - Tcl_UniChar *ustring = TclGetUnicodeFromObj(objPtr, &numChars); + Tcl_Size numChars; + Tcl_UniChar *ustring = Tcl_GetUnicodeFromObj(objPtr, &numChars); /* TODO: Is there an in-place option worth pursuing here? */ result = Tcl_NewUnicodeObj(ustring, first); if (insertPtr) { Tcl_AppendObjToObj(result, insertPtr); } - if (first + count < (size_t)numChars) { - TclAppendUnicodeToObj(result, ustring + first + count, + if ((first + count) < numChars) { + Tcl_AppendUnicodeToObj(result, ustring + first + count, numChars - first - count); } return result; } @@ -3918,11 +4137,11 @@ *--------------------------------------------------------------------------- * * FillUnicodeRep -- * * Populate the Unicode internal rep with the Unicode form of its string - * rep. The object must alread have a "String" internal rep. + * rep. The object must already have a "String" internal rep. * * Results: * None. * * Side effects: @@ -3944,22 +4163,22 @@ static void ExtendUnicodeRepWithString( Tcl_Obj *objPtr, const char *bytes, - size_t numBytes, - size_t numAppendChars) + Tcl_Size numBytes, + Tcl_Size numAppendChars) { String *stringPtr = GET_STRING(objPtr); - size_t needed, numOrigChars = 0; + Tcl_Size needed, numOrigChars = 0; Tcl_UniChar *dst, unichar = 0; if (stringPtr->hasUnicode) { numOrigChars = stringPtr->numChars; } if (numAppendChars == TCL_INDEX_NONE) { - TclNumUtfChars(numAppendChars, bytes, numBytes); + TclNumUtfCharsM(numAppendChars, bytes, numBytes); } needed = numOrigChars + numAppendChars; if (needed > stringPtr->maxChars) { GrowUnicodeBuffer(objPtr, needed); @@ -3970,13 +4189,18 @@ if (bytes) { stringPtr->numChars = needed; } else { numAppendChars = 0; } - for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) { + dst = stringPtr->unicode + numOrigChars; + if (numAppendChars-- > 0) { bytes += TclUtfToUniChar(bytes, &unichar); - *dst = unichar; + *dst++ = unichar; + while (numAppendChars-- > 0) { + bytes += TclUtfToUniChar(bytes, &unichar); + *dst++ = unichar; + } } *dst = 0; } /* @@ -4011,11 +4235,10 @@ /* * 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; @@ -4063,33 +4286,33 @@ * * Results: * This operation always succeeds and returns TCL_OK. * * Side effects: - * Any old internal reputation for objPtr is freed and the internal - * representation is set to "String". + * Any old internal representation for objPtr is freed and the internal + * representation is set to &tclStringType. * *---------------------------------------------------------------------- */ static int SetStringFromAny( TCL_UNUSED(Tcl_Interp *), Tcl_Obj *objPtr) /* The object to convert. */ { - if (!TclHasIntRep(objPtr, &tclStringType)) { + if (!TclHasInternalRep(objPtr, &tclStringType)) { String *stringPtr = stringAlloc(0); /* * Convert whatever we have into an untyped value. Just A String. */ (void) TclGetString(objPtr); - TclFreeIntRep(objPtr); + TclFreeInternalRep(objPtr); /* - * Create a basic String intrep that just points to the UTF-8 string + * Create a basic String internalrep that just points to the UTF-8 string * already in place at objPtr->bytes. */ stringPtr->numChars = -1; stringPtr->allocated = objPtr->length; @@ -4111,11 +4334,11 @@ * * Results: * None. * * Side effects: - * The object's string may be set by converting its Unicode represention + * The object's string may be set by converting its Unicode representation * to UTF format. * *---------------------------------------------------------------------- */ @@ -4134,32 +4357,32 @@ */ stringPtr->allocated = 0; if (stringPtr->numChars == 0) { - TclInitStringRep(objPtr, NULL, 0); + TclInitEmptyStringRep(objPtr); } else { (void) ExtendStringRepWithUnicode(objPtr, stringPtr->unicode, stringPtr->numChars); } } -static size_t +static Tcl_Size ExtendStringRepWithUnicode( Tcl_Obj *objPtr, const Tcl_UniChar *unicode, - size_t numChars) + Tcl_Size numChars) { /* - * Pre-condition: this is the "string" Tcl_ObjType. + * Precondition: this is the "string" Tcl_ObjType. */ - size_t i, origLength, size = 0; + Tcl_Size i, origLength, size = 0; char *dst; String *stringPtr = GET_STRING(objPtr); - if (numChars == TCL_INDEX_NONE) { + if (numChars < 0) { numChars = UnicodeLength(unicode); } if (numChars == 0) { return 0; @@ -4172,18 +4395,22 @@ /* * Quick cheap check in case we have more than enough room. */ - if (numChars <= (INT_MAX - size)/TCL_UTF_MAX + if (numChars <= (TCL_SIZE_MAX - size)/TCL_UTF_MAX && stringPtr->allocated >= size + numChars * TCL_UTF_MAX) { goto copyBytes; } - for (i = 0; i < numChars; i++) { + for (i = 0; i < numChars && size >= 0; i++) { + /* TODO - overflow check! I don't think check below at end suffices */ size += TclUtfCount(unicode[i]); } + if (size < 0) { + Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", TCL_SIZE_MAX); + } /* * Grow space if needed. */ Index: generic/tclStringRep.h ================================================================== --- generic/tclStringRep.h +++ generic/tclStringRep.h @@ -1,31 +1,14 @@ /* * 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. + * 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 @@ -37,41 +20,41 @@ /* * The following structure is the internal rep for a String object. It keeps * track of how much memory has been used and how much has been allocated for - * the Unicode and UTF string to enable growing and shrinking of the UTF and - * Unicode reps of the String object with fewer mallocs. To optimize string + * the various representations to enable growing and shrinking of + * the String object with fewer mallocs. To optimize string * length and indexing operations, this structure also stores the number of - * characters (same of UTF and Unicode!) once that value has been computed. - * - * 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! + * code points (independent of encoding form) once that value has been computed. */ typedef struct { - size_t numChars; /* The number of chars in the string. -1 means - * this value has not been calculated. Any other - * means that there is a valid Unicode rep, or - * that the number of UTF bytes == the number - * of chars. */ - size_t allocated; /* The amount of space actually allocated for - * the UTF string (minus 1 byte for the - * termination char). */ - size_t maxChars; /* Max number of chars that can fit in the - * space allocated for the unicode array. */ + Tcl_Size numChars; /* The number of chars in the string. + * TCL_INDEX_NONE means this value has not been + * calculated. Any other means that there is a valid + * Unicode rep, or that the number of UTF bytes == + * the number of chars. */ + Tcl_Size allocated; /* The amount of space allocated for + * the UTF-8 string. Does not include nul + * terminator so actual allocation is + * (allocated+1). */ + Tcl_Size maxChars; /* Max number of chars that can fit in the + * space allocated for the Unicode array. */ int hasUnicode; /* Boolean determining whether the string has - * a Unicode representation. */ - Tcl_UniChar unicode[TCLFLEXARRAY]; /* The array of Unicode chars. The actual size - * of this field depends on the 'maxChars' - * field above. */ + * a Tcl_UniChar representation. */ + Tcl_UniChar unicode[TCLFLEXARRAY]; /* The array of Tcl_UniChar units. + * The actual size of this field depends on + * the maxChars field above. */ } String; +/* Limit on string lengths. The -1 because limit does not include the nul */ +#define STRING_MAXCHARS \ + ((Tcl_Size)((TCL_SIZE_MAX - offsetof(String, unicode))/sizeof(Tcl_UniChar) - 1)) +/* Memory needed to hold a string of length numChars - including NUL */ #define STRING_SIZE(numChars) \ - (offsetof(String, unicode) + ((numChars + 1) * sizeof(Tcl_UniChar))) + (offsetof(String, unicode) + sizeof(Tcl_UniChar) + ((numChars) * sizeof(Tcl_UniChar))) #define stringAttemptAlloc(numChars) \ (String *) Tcl_AttemptAlloc(STRING_SIZE(numChars)) #define stringAlloc(numChars) \ (String *) Tcl_Alloc(STRING_SIZE(numChars)) #define stringRealloc(ptr, numChars) \ ADDED generic/tclStubCall.c Index: generic/tclStubCall.c ================================================================== --- /dev/null +++ generic/tclStubCall.c @@ -0,0 +1,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 +#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" > 8 */ + "_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: + */ Index: generic/tclStubInit.c ================================================================== --- generic/tclStubInit.c +++ generic/tclStubInit.c @@ -1,11 +1,11 @@ /* * tclStubInit.c -- * * This file contains the initializers for the Tcl stub vectors. * - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -53,31 +53,154 @@ #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 TclpInetNtoa #undef TclWinGetServByName #undef TclWinGetSockOpt #undef TclWinSetSockOpt #undef TclWinNToHS -#undef TclStaticPackage +#undef TclStaticLibrary #undef Tcl_BackgroundError -#define TclStaticPackage Tcl_StaticPackage +#define TclStaticLibrary Tcl_StaticLibrary #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 +#undef Tcl_UniCharLen +#undef TclObjInterpProc +#if !defined(_WIN32) && !defined(__CYGWIN__) +# undef Tcl_WinConvertError +# define Tcl_WinConvertError 0 +#endif +#if defined(TCL_NO_DEPRECATED) +# undef TclGetStringFromObj +# undef TclGetBytesFromObj +# undef TclGetUnicodeFromObj +# define TclGetStringFromObj 0 +# define TclGetBytesFromObj 0 +# define TclGetUnicodeFromObj 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 + +#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(size_t)) && (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(size_t)) && (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(size_t)) && (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(size_t)) && (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(size_t)) && (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(size_t)) && 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 @@ -111,12 +234,13 @@ #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_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 @@ -126,14 +250,15 @@ #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_s_mp_balance_mul mp_balance_mul +#define TclBN_mp_balance_mul s_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 @@ -141,25 +266,28 @@ #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 +# 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) @@ -210,11 +338,11 @@ if ((longValue >= (long)(INT_MIN)) && (longValue <= (long)(UINT_MAX))) { *ptr = (int)longValue; } else { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "integer value too large to represent as non-long integer", -1)); + "integer value too large to represent", -1)); result = TCL_ERROR; } } return result; } @@ -226,11 +354,11 @@ if ((longValue >= (long)(INT_MIN)) && (longValue <= (long)(UINT_MAX))) { *ptr = (int)longValue; } else { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "integer value too large to represent as non-long integer", -1)); + "integer value too large to represent", -1)); result = TCL_ERROR; } } return result; } @@ -244,11 +372,17 @@ } #define Tcl_UtfNcasecmp (int(*)(const char*,const char*,unsigned long))(void *)utfNcasecmp #endif /* TCL_WIDE_INT_IS_LONG */ -#endif /* __CYGWIN__ */ +#else /* __CYGWIN__ */ +# define TclWinGetTclInstance 0 +# define TclpGetPid 0 +# define TclWinFlushDirtyChannels 0 +# define TclWinNoBackslash 0 +# define TclWinAddProcess 0 +#endif /* * WARNING: The contents of this file is automatically generated by the * tools/genStubs.tcl script. Any modifications to the function declarations * below should be made in the generic/tcl.decls script. @@ -306,37 +440,37 @@ TclGetFrame, /* 32 */ 0, /* 33 */ 0, /* 34 */ 0, /* 35 */ 0, /* 36 */ - TclGetLoadedPackages, /* 37 */ + 0, /* 37 */ TclGetNamespaceForQualName, /* 38 */ TclGetObjInterpProc, /* 39 */ TclGetOpenMode, /* 40 */ TclGetOriginalCommand, /* 41 */ TclpGetUserHome, /* 42 */ - 0, /* 43 */ - TclGuessPackageName, /* 44 */ + TclGetObjInterpProc2, /* 43 */ + 0, /* 44 */ TclHideUnsafeCommands, /* 45 */ TclInExit, /* 46 */ 0, /* 47 */ 0, /* 48 */ 0, /* 49 */ 0, /* 50 */ TclInterpInit, /* 51 */ 0, /* 52 */ - TclInvokeObjectCommand, /* 53 */ - TclInvokeStringCommand, /* 54 */ + 0, /* 53 */ + 0, /* 54 */ TclIsProc, /* 55 */ 0, /* 56 */ 0, /* 57 */ TclLookupVar, /* 58 */ 0, /* 59 */ TclNeedSpace, /* 60 */ TclNewProcBodyObj, /* 61 */ TclObjCommandComplete, /* 62 */ - TclObjInterpProc, /* 63 */ + 0, /* 63 */ TclObjInvoke, /* 64 */ 0, /* 65 */ 0, /* 66 */ 0, /* 67 */ 0, /* 68 */ @@ -370,11 +504,11 @@ TclRenameCommand, /* 96 */ TclResetShadowedCmdRefs, /* 97 */ TclServiceIdle, /* 98 */ 0, /* 99 */ 0, /* 100 */ - TclSetPreInitScript, /* 101 */ + 0, /* 101 */ TclSetupEnv, /* 102 */ TclSockGetPort, /* 103 */ 0, /* 104 */ 0, /* 105 */ 0, /* 106 */ @@ -401,11 +535,11 @@ 0, /* 127 */ Tcl_PopCallFrame, /* 128 */ Tcl_PushCallFrame, /* 129 */ Tcl_RemoveInterpResolvers, /* 130 */ Tcl_SetNamespaceResolvers, /* 131 */ - TclpHasSockets, /* 132 */ + 0, /* 132 */ 0, /* 133 */ 0, /* 134 */ 0, /* 135 */ 0, /* 136 */ 0, /* 137 */ @@ -488,15 +622,15 @@ TclSetObjNameOfExecutable, /* 214 */ TclStackAlloc, /* 215 */ TclStackFree, /* 216 */ TclPushStackFrame, /* 217 */ TclPopStackFrame, /* 218 */ - 0, /* 219 */ + TclpCreateTemporaryDirectory, /* 219 */ 0, /* 220 */ - 0, /* 221 */ - 0, /* 222 */ - 0, /* 223 */ + TclListTestObj, /* 221 */ + TclListObjValidate, /* 222 */ + TclGetCStackPtr, /* 223 */ TclGetPlatform, /* 224 */ TclTraceDictPath, /* 225 */ TclObjBeingDeleted, /* 226 */ TclSetNsPath, /* 227 */ 0, /* 228 */ @@ -526,127 +660,60 @@ TclPtrGetVar, /* 252 */ TclPtrSetVar, /* 253 */ TclPtrIncrObjVar, /* 254 */ TclPtrObjMakeUpvar, /* 255 */ TclPtrUnsetVar, /* 256 */ - TclStaticPackage, /* 257 */ - TclpCreateTemporaryDirectory, /* 258 */ - TclAppendUnicodeToObj, /* 259 */ - TclGetBytesFromObj, /* 260 */ + TclStaticLibrary, /* 257 */ + 0, /* 258 */ + TclMSB, /* 259 */ + 0, /* 260 */ + TclUnusedStubEntry, /* 261 */ }; static const TclIntPlatStubs tclIntPlatStubs = { TCL_STUB_MAGIC, 0, -#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */ - TclGetAndDetachPids, /* 0 */ + 0, /* 0 */ TclpCloseFile, /* 1 */ TclpCreateCommandChannel, /* 2 */ TclpCreatePipe, /* 3 */ - TclpCreateProcess, /* 4 */ - TclUnixWaitForFile_, /* 5 */ + TclWinGetTclInstance, /* 4 */ + TclUnixWaitForFile, /* 5 */ TclpMakeFile, /* 6 */ TclpOpenFile, /* 7 */ - TclUnixWaitForFile, /* 8 */ + TclpGetPid, /* 8 */ TclpCreateTempFile, /* 9 */ 0, /* 10 */ - 0, /* 11 */ + TclGetAndDetachPids, /* 11 */ 0, /* 12 */ 0, /* 13 */ - TclUnixCopyFile, /* 14 */ - TclMacOSXGetFileAttribute, /* 15 */ - TclMacOSXSetFileAttribute, /* 16 */ - TclMacOSXCopyFileAttributes, /* 17 */ - TclMacOSXMatchType, /* 18 */ - TclMacOSXNotifierAddRunLoopMode, /* 19 */ - 0, /* 20 */ - 0, /* 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 */ + 0, /* 14 */ TclpCreateProcess, /* 15 */ TclpIsAtty, /* 16 */ TclUnixCopyFile, /* 17 */ - TclpMakeFile, /* 18 */ - TclpOpenFile, /* 19 */ + 0, /* 18 */ + 0, /* 19 */ TclWinAddProcess, /* 20 */ 0, /* 21 */ - TclpCreateTempFile, /* 22 */ + 0, /* 22 */ 0, /* 23 */ TclWinNoBackslash, /* 24 */ 0, /* 25 */ 0, /* 26 */ TclWinFlushDirtyChannels, /* 27 */ 0, /* 28 */ TclWinCPUID, /* 29 */ TclUnixOpenTemporaryFile, /* 30 */ -#endif /* WIN */ -#ifdef MAC_OSX_TCL /* MACOSX */ - TclGetAndDetachPids, /* 0 */ - TclpCloseFile, /* 1 */ - TclpCreateCommandChannel, /* 2 */ - TclpCreatePipe, /* 3 */ - TclpCreateProcess, /* 4 */ - TclUnixWaitForFile_, /* 5 */ - TclpMakeFile, /* 6 */ - TclpOpenFile, /* 7 */ - TclUnixWaitForFile, /* 8 */ - TclpCreateTempFile, /* 9 */ - 0, /* 10 */ - 0, /* 11 */ - 0, /* 12 */ - 0, /* 13 */ - TclUnixCopyFile, /* 14 */ - TclMacOSXGetFileAttribute, /* 15 */ - TclMacOSXSetFileAttribute, /* 16 */ - TclMacOSXCopyFileAttributes, /* 17 */ - TclMacOSXMatchType, /* 18 */ - TclMacOSXNotifierAddRunLoopMode, /* 19 */ - 0, /* 20 */ - 0, /* 21 */ - TclpCreateTempFile_, /* 22 */ - 0, /* 23 */ - 0, /* 24 */ - 0, /* 25 */ - 0, /* 26 */ - 0, /* 27 */ - 0, /* 28 */ - TclWinCPUID, /* 29 */ - TclUnixOpenTemporaryFile, /* 30 */ -#endif /* MACOSX */ }; static const TclPlatStubs tclPlatStubs = { TCL_STUB_MAGIC, 0, -#ifdef MAC_OSX_TCL /* MACOSX */ 0, /* 0 */ Tcl_MacOSXOpenVersionedBundleResources, /* 1 */ -#endif /* MACOSX */ + Tcl_MacOSXNotifierAddRunLoopMode, /* 2 */ + Tcl_WinConvertError, /* 3 */ }; const TclTomMathStubs tclTomMathStubs = { TCL_STUB_MAGIC, 0, @@ -719,17 +786,17 @@ TclBN_mp_init_u64, /* 66 */ 0, /* 67 */ TclBN_mp_set_u64, /* 68 */ TclBN_mp_get_mag_u64, /* 69 */ TclBN_mp_set_i64, /* 70 */ - 0, /* 71 */ - 0, /* 72 */ + TclBN_mp_unpack, /* 71 */ + TclBN_mp_pack, /* 72 */ 0, /* 73 */ 0, /* 74 */ 0, /* 75 */ TclBN_mp_signed_rsh, /* 76 */ - 0, /* 77 */ + TclBN_mp_pack_count, /* 77 */ TclBN_mp_to_ubin, /* 78 */ 0, /* 79 */ TclBN_mp_to_radix, /* 80 */ }; @@ -749,28 +816,12 @@ 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_CreateFileHandler, /* 9 */ + Tcl_DeleteFileHandler, /* 10 */ Tcl_SetTimer, /* 11 */ Tcl_Sleep, /* 12 */ Tcl_WaitForEvent, /* 13 */ Tcl_AppendAllObjTypes, /* 14 */ Tcl_AppendStringsToObj, /* 15 */ @@ -797,17 +848,17 @@ 0, /* 36 */ Tcl_GetInt, /* 37 */ Tcl_GetIntFromObj, /* 38 */ Tcl_GetLongFromObj, /* 39 */ Tcl_GetObjType, /* 40 */ - Tcl_GetStringFromObj, /* 41 */ + TclGetStringFromObj, /* 41 */ Tcl_InvalidateStringRep, /* 42 */ Tcl_ListObjAppendList, /* 43 */ Tcl_ListObjAppendElement, /* 44 */ - Tcl_ListObjGetElements, /* 45 */ + TclListObjGetElements, /* 45 */ Tcl_ListObjIndex, /* 46 */ - Tcl_ListObjLength, /* 47 */ + TclListObjLength, /* 47 */ Tcl_ListObjReplace, /* 48 */ 0, /* 49 */ Tcl_NewByteArrayObj, /* 50 */ Tcl_NewDoubleObj, /* 51 */ 0, /* 52 */ @@ -837,11 +888,11 @@ 0, /* 76 */ 0, /* 77 */ Tcl_BadChannelOption, /* 78 */ Tcl_CallWhenDeleted, /* 79 */ Tcl_CancelIdleCall, /* 80 */ - 0, /* 81 */ + Tcl_Close, /* 81 */ Tcl_CommandComplete, /* 82 */ Tcl_Concat, /* 83 */ Tcl_ConvertElement, /* 84 */ Tcl_ConvertCountedElement, /* 85 */ Tcl_CreateAlias, /* 86 */ @@ -923,19 +974,11 @@ 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_GetOpenFile, /* 167 */ Tcl_GetPathType, /* 168 */ Tcl_Gets, /* 169 */ Tcl_GetsObj, /* 170 */ Tcl_GetServiceMode, /* 171 */ Tcl_GetChild, /* 172 */ @@ -954,11 +997,11 @@ Tcl_IsSafe, /* 185 */ Tcl_JoinPath, /* 186 */ Tcl_LinkVar, /* 187 */ 0, /* 188 */ Tcl_MakeFileChannel, /* 189 */ - Tcl_MakeSafe, /* 190 */ + 0, /* 190 */ Tcl_MakeTcpClientChannel, /* 191 */ Tcl_Merge, /* 192 */ Tcl_NextHashEntry, /* 193 */ Tcl_NotifyChannel, /* 194 */ Tcl_ObjGetVar2, /* 195 */ @@ -1006,12 +1049,12 @@ 0, /* 237 */ Tcl_SetVar2, /* 238 */ Tcl_SignalId, /* 239 */ Tcl_SignalMsg, /* 240 */ Tcl_SourceRCFile, /* 241 */ - Tcl_SplitList, /* 242 */ - Tcl_SplitPath, /* 243 */ + TclSplitList, /* 242 */ + TclSplitPath, /* 243 */ 0, /* 244 */ 0, /* 245 */ 0, /* 246 */ 0, /* 247 */ Tcl_TraceVar2, /* 248 */ @@ -1076,11 +1119,11 @@ Tcl_InitNotifier, /* 307 */ Tcl_MutexLock, /* 308 */ Tcl_MutexUnlock, /* 309 */ Tcl_ConditionNotify, /* 310 */ Tcl_ConditionWait, /* 311 */ - Tcl_NumUtfChars, /* 312 */ + TclNumUtfChars, /* 312 */ Tcl_ReadChars, /* 313 */ 0, /* 314 */ 0, /* 315 */ Tcl_SetSystemEncoding, /* 316 */ Tcl_SetVar2Ex, /* 317 */ @@ -1089,17 +1132,17 @@ Tcl_UniCharAtIndex, /* 320 */ Tcl_UniCharToLower, /* 321 */ Tcl_UniCharToTitle, /* 322 */ Tcl_UniCharToUpper, /* 323 */ Tcl_UniCharToUtf, /* 324 */ - Tcl_UtfAtIndex, /* 325 */ - Tcl_UtfCharComplete, /* 326 */ + TclUtfAtIndex, /* 325 */ + TclUtfCharComplete, /* 326 */ Tcl_UtfBackslash, /* 327 */ Tcl_UtfFindFirst, /* 328 */ Tcl_UtfFindLast, /* 329 */ - Tcl_UtfNext, /* 330 */ - Tcl_UtfPrev, /* 331 */ + TclUtfNext, /* 330 */ + TclUtfPrev, /* 331 */ Tcl_UtfToExternal, /* 332 */ Tcl_UtfToExternalDString, /* 333 */ Tcl_UtfToLower, /* 334 */ Tcl_UtfToTitle, /* 335 */ Tcl_UtfToChar16, /* 336 */ @@ -1116,11 +1159,11 @@ Tcl_UniCharIsDigit, /* 347 */ Tcl_UniCharIsLower, /* 348 */ Tcl_UniCharIsSpace, /* 349 */ Tcl_UniCharIsUpper, /* 350 */ Tcl_UniCharIsWordChar, /* 351 */ - 0, /* 352 */ + Tcl_Char16Len, /* 352 */ 0, /* 353 */ Tcl_Char16ToUtfDString, /* 354 */ Tcl_UtfToChar16DString, /* 355 */ Tcl_GetRegExpFromObj, /* 356 */ 0, /* 357 */ @@ -1144,15 +1187,15 @@ Tcl_UniCharIsPunct, /* 375 */ Tcl_RegExpExecObj, /* 376 */ Tcl_RegExpGetInfo, /* 377 */ Tcl_NewUnicodeObj, /* 378 */ Tcl_SetUnicodeObj, /* 379 */ - Tcl_GetCharLength, /* 380 */ - Tcl_GetUniChar, /* 381 */ + TclGetCharLength, /* 380 */ + TclGetUniChar, /* 381 */ 0, /* 382 */ - Tcl_GetRange, /* 383 */ - 0, /* 384 */ + TclGetRange, /* 383 */ + Tcl_AppendUnicodeToObj, /* 384 */ Tcl_RegExpMatchObj, /* 385 */ Tcl_SetNotifier, /* 386 */ Tcl_GetAllocMutex, /* 387 */ Tcl_GetChannelNames, /* 388 */ Tcl_GetChannelNamesEx, /* 389 */ @@ -1198,11 +1241,11 @@ Tcl_AttemptDbCkalloc, /* 429 */ Tcl_AttemptRealloc, /* 430 */ Tcl_AttemptDbCkrealloc, /* 431 */ Tcl_AttemptSetObjLength, /* 432 */ Tcl_GetChannelThread, /* 433 */ - Tcl_GetUnicodeFromObj, /* 434 */ + TclGetUnicodeFromObj, /* 434 */ 0, /* 435 */ 0, /* 436 */ Tcl_SubstObj, /* 437 */ Tcl_DetachChannel, /* 438 */ Tcl_IsStandardChannel, /* 439 */ @@ -1225,11 +1268,11 @@ Tcl_FSOpenFileChannel, /* 456 */ Tcl_FSGetCwd, /* 457 */ Tcl_FSChdir, /* 458 */ Tcl_FSConvertToPathType, /* 459 */ Tcl_FSJoinPath, /* 460 */ - Tcl_FSSplitPath, /* 461 */ + TclFSSplitPath, /* 461 */ Tcl_FSEqualPaths, /* 462 */ Tcl_FSGetNormalizedPath, /* 463 */ Tcl_FSJoinToPath, /* 464 */ Tcl_FSGetInternalRep, /* 465 */ Tcl_FSGetTranslatedPath, /* 466 */ @@ -1261,11 +1304,11 @@ Tcl_Tell, /* 492 */ Tcl_ChannelWideSeekProc, /* 493 */ Tcl_DictObjPut, /* 494 */ Tcl_DictObjGet, /* 495 */ Tcl_DictObjRemove, /* 496 */ - Tcl_DictObjSize, /* 497 */ + TclDictObjSize, /* 497 */ Tcl_DictObjFirst, /* 498 */ Tcl_DictObjNext, /* 499 */ Tcl_DictObjDone, /* 500 */ Tcl_DictObjPutKeyList, /* 501 */ Tcl_DictObjRemoveKeyList, /* 502 */ @@ -1368,11 +1411,11 @@ Tcl_GetSizeFromStat, /* 599 */ Tcl_GetBlocksFromStat, /* 600 */ Tcl_GetBlockSizeFromStat, /* 601 */ Tcl_SetEnsembleParameterList, /* 602 */ Tcl_GetEnsembleParameterList, /* 603 */ - Tcl_ParseArgsObjv, /* 604 */ + TclParseArgsObjv, /* 604 */ Tcl_GetErrorLine, /* 605 */ Tcl_SetErrorLine, /* 606 */ Tcl_TransferResult, /* 607 */ Tcl_InterpActive, /* 608 */ Tcl_BackgroundException, /* 609 */ @@ -1400,21 +1443,61 @@ Tcl_OpenTcpServerEx, /* 631 */ TclZipfs_Mount, /* 632 */ TclZipfs_Unmount, /* 633 */ TclZipfs_TclLibrary, /* 634 */ TclZipfs_MountBuffer, /* 635 */ - Tcl_FreeIntRep, /* 636 */ + Tcl_FreeInternalRep, /* 636 */ Tcl_InitStringRep, /* 637 */ - Tcl_FetchIntRep, /* 638 */ - Tcl_StoreIntRep, /* 639 */ + Tcl_FetchInternalRep, /* 638 */ + Tcl_StoreInternalRep, /* 639 */ Tcl_HasStringRep, /* 640 */ Tcl_IncrRefCount, /* 641 */ Tcl_DecrRefCount, /* 642 */ Tcl_IsShared, /* 643 */ Tcl_LinkArray, /* 644 */ Tcl_GetIntForIndex, /* 645 */ Tcl_UtfToUniChar, /* 646 */ Tcl_UniCharToUtfDString, /* 647 */ Tcl_UtfToUniCharDString, /* 648 */ + TclGetBytesFromObj, /* 649 */ + Tcl_GetBytesFromObj, /* 650 */ + Tcl_GetStringFromObj, /* 651 */ + Tcl_GetUnicodeFromObj, /* 652 */ + Tcl_GetSizeIntFromObj, /* 653 */ + Tcl_UtfCharComplete, /* 654 */ + Tcl_UtfNext, /* 655 */ + Tcl_UtfPrev, /* 656 */ + Tcl_UniCharIsUnicode, /* 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 */ + 0, /* 686 */ + 0, /* 687 */ + TclUnusedStubEntry, /* 688 */ }; /* !END!: Do not edit above this line. */ Index: generic/tclStubLib.c ================================================================== --- generic/tclStubLib.c +++ generic/tclStubLib.c @@ -2,12 +2,12 @@ * tclStubLib.c -- * * Stub object that will be statically linked into extensions that want * to access Tcl. * - * Copyright (c) 1998-1999 by Scriptics Corporation. - * Copyright (c) 1998 Paul Duffin. + * Copyright © 1998-1999 Scriptics Corporation. + * Copyright © 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -15,15 +15,17 @@ 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 */ @@ -52,15 +54,18 @@ Tcl_Interp *interp, const char *version, int exact, int magic) { - Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *)interp; const char *actualVersion = NULL; - ClientData pkgData = NULL; + void *pkgData = NULL; const TclStubs *stubsPtr = iPtr->stubTable; + const char *tclName = (((exact&0xFF00) >= 0x900) ? "tcl" : "Tcl"); +#undef TCL_STUB_MAGIC /* We need the TCL_STUB_MAGIC from Tcl 8.x here */ +#define TCL_STUB_MAGIC ((int) 0xFCA3BACF) /* * We can't optimize this check by caching tclStubsPtr because that * prevents apps from being able to load/unload Tcl dynamically multiple * times. [Bug 615304] */ @@ -69,11 +74,11 @@ iPtr->legacyResult = "interpreter uses an incompatible stubs mechanism"; iPtr->legacyFreeProc = 0; /* TCL_STATIC */ return NULL; } - actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData); + actualVersion = stubsPtr->tcl_PkgRequireEx(interp, tclName, version, 0, &pkgData); if (actualVersion == NULL) { return NULL; } if (exact&1) { const char *p = version; @@ -89,23 +94,26 @@ while (*p && (*p == *q)) { p++; q++; } if (*p || ISDIGIT(*q)) { /* Construct error message */ - stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); + stubsPtr->tcl_PkgRequireEx(interp, tclName, version, 1, NULL); return NULL; } } else { - actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); + actualVersion = stubsPtr->tcl_PkgRequireEx(interp, tclName, version, 1, NULL); if (actualVersion == NULL) { return NULL; } } } if (((exact&0xFF00) < 0x900)) { /* We are running Tcl 8.x */ stubsPtr = (TclStubs *)pkgData; + } + if (tclStubsHandle == NULL) { + tclStubsHandle = INT2PTR(-1); } tclStubsPtr = stubsPtr; if (stubsPtr->hooks) { tclPlatStubsPtr = stubsPtr->hooks->tclPlatStubs; ADDED generic/tclStubLibTbl.c Index: generic/tclStubLibTbl.c ================================================================== --- /dev/null +++ generic/tclStubLibTbl.c @@ -0,0 +1,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: + */ Index: generic/tclTest.c ================================================================== --- generic/tclTest.c +++ generic/tclTest.c @@ -4,14 +4,14 @@ * This file contains C command functions for a bunch of additional Tcl * commands that are used for testing out Tcl's C interfaces. These * commands are not normally included in Tcl applications; they're only * used for testing. * - * Copyright (c) 1993-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 Ajuba Solutions. - * Copyright (c) 2003 by Kevin B. Kenny. All rights reserved. + * Copyright © 1993-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Ajuba Solutions. + * Copyright © 2003 Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -36,10 +36,12 @@ /* * 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); @@ -50,10 +52,26 @@ */ 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". */ @@ -72,12 +90,11 @@ 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 */ + int flags; /* ORed combination of various bitfields. */ }; TCL_DECLARE_MUTEX(asyncTestMutex) static TestAsyncHandler *firstHandler = NULL; @@ -116,17 +133,10 @@ 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; @@ -158,13 +168,11 @@ * 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; @@ -200,25 +208,23 @@ 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 Tcl_CmdObjTraceProc ObjTraceProc; static void ObjTraceDeleteProc(void *clientData); static void PrintParse(Tcl_Interp *interp, Tcl_Parse *parsePtr); -static void SpecialFree(void *blockPtr); +static Tcl_FreeProc SpecialFree; static int StaticInitProc(Tcl_Interp *interp); static Tcl_CmdProc TestasyncCmd; static Tcl_ObjCmdProc TestbumpinterpepochObjCmd; static Tcl_ObjCmdProc TestbytestringObjCmd; static Tcl_ObjCmdProc TestsetbytearraylengthObjCmd; static Tcl_ObjCmdProc TestpurebytesobjObjCmd; static Tcl_ObjCmdProc TeststringbytesObjCmd; -static Tcl_CmdProc TestcmdinfoCmd; +static Tcl_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; @@ -249,12 +255,14 @@ 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_ObjCmdProc TestmsbObjCmd; static Tcl_CmdProc TestsetmainloopCmd; static Tcl_CmdProc TestexitmainloopCmd; static Tcl_CmdProc TestpanicCmd; static Tcl_ObjCmdProc TestparseargsCmd; static Tcl_ObjCmdProc TestparserObjCmd; @@ -264,22 +272,20 @@ 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 TeststaticlibraryCmd; static Tcl_CmdProc TesttranslatefilenameCmd; static Tcl_CmdProc TestupvarCmd; -static Tcl_ObjCmdProc TestWrongNumArgsObjCmd; +static Tcl_ObjCmdProc2 TestWrongNumArgsObjCmd; static Tcl_ObjCmdProc TestGetIndexFromObjStructObjCmd; static Tcl_CmdProc TestChannelCmd; static Tcl_CmdProc TestChannelEventCmd; static Tcl_CmdProc TestSocketCmd; static Tcl_ObjCmdProc TestFilesystemObjCmd; @@ -321,21 +327,25 @@ static Tcl_Obj * SimpleRedirect(Tcl_Obj *pathPtr); static Tcl_FSMatchInDirectoryProc SimpleMatchInDirectory; static Tcl_ObjCmdProc TestUtfNextCmd; static Tcl_ObjCmdProc TestUtfPrevCmd; static Tcl_ObjCmdProc TestNumUtfCharsCmd; +static Tcl_ObjCmdProc TestGetUniCharCmd; static Tcl_ObjCmdProc TestFindFirstCmd; static Tcl_ObjCmdProc TestFindLastCmd; static Tcl_ObjCmdProc TestHashSystemHashCmd; +static Tcl_ObjCmdProc TestGetIntForIndexCmd; +static Tcl_ObjCmdProc TestLutilCmd; static Tcl_NRPostProc NREUnwind_callback; static Tcl_ObjCmdProc TestNREUnwind; static Tcl_ObjCmdProc TestNRELevels; static Tcl_ObjCmdProc TestInterpResolverCmd; -#if defined(HAVE_CPUID) || defined(_WIN32) +#if defined(HAVE_CPUID) && !defined(MAC_OSX_TCL) static Tcl_ObjCmdProc TestcpuidCmd; #endif +static Tcl_ObjCmdProc TestApplyLambdaObjCmd; static const Tcl_Filesystem testReportingFilesystem = { "reporting", sizeof(Tcl_Filesystem), TCL_FILESYSTEM_VERSION_1, @@ -433,36 +443,120 @@ * 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; - int objc, index; + Tcl_Size objc; + int index; static const char *const specialOptions[] = { "-appinitprocerror", "-appinitprocdeleteinterp", "-appinitprocclosestderr", "-appinitprocsetrcfile", NULL }; - if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) { return TCL_ERROR; } #ifndef TCL_WITH_EXTERNAL_TOMMATH - if (Tcl_TomMath_InitStubs(interp, "8.5-") == NULL) { + if (Tcl_TomMath_InitStubs(interp, "8.7-") == NULL) { return TCL_ERROR; } #endif if (Tcl_OOInitStubs(interp) == NULL) { return TCL_ERROR; } - /* TIP #268: Full patchlevel instead of just major.minor */ - if (Tcl_PkgProvideEx(interp, "Tcltest", TCL_PATCH_LEVEL, NULL) == TCL_ERROR) { + if (Tcl_GetCommandInfo(interp, "::tcl::build-info", &info)) { +#if TCL_MAJOR_VERSION > 8 + if (info.isNativeObjectProc == 2) { + Tcl_CreateObjCommand2(interp, "::tcl::test::build-info", + info.objProc2, (void *)version, NULL); + } else +#endif + Tcl_CreateObjCommand(interp, "::tcl::test::build-info", + info.objProc, (void *)version, NULL); + } + if (Tcl_PkgProvideEx(interp, "tcl::test", TCL_PATCH_LEVEL, NULL) == TCL_ERROR) { return TCL_ERROR; } /* * Create additional commands and math functions for testing Tcl. @@ -473,11 +567,11 @@ Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testpurebytesobj", TestpurebytesobjObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testsetbytearraylength", TestsetbytearraylengthObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testbytestring", TestbytestringObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "teststringbytes", TeststringbytesObjCmd, NULL, NULL); - Tcl_CreateObjCommand(interp, "testwrongnumargs", TestWrongNumArgsObjCmd, + Tcl_CreateObjCommand2(interp, "testwrongnumargs", TestWrongNumArgsObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemObjCmd, NULL, NULL); @@ -490,11 +584,13 @@ NULL, NULL); Tcl_CreateCommand(interp, "testchannelevent", TestChannelEventCmd, NULL, NULL); Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, NULL, NULL); - Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, 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); @@ -551,12 +647,14 @@ 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_CreateObjCommand(interp, "testmsb", TestmsbObjCmd, 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, @@ -569,12 +667,10 @@ 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, @@ -591,19 +687,23 @@ 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, "teststaticpkg", TeststaticpkgCmd, + 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, @@ -610,11 +710,11 @@ NULL); Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd, NULL, NULL); Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd, NULL, NULL); -#if defined(HAVE_CPUID) || defined(_WIN32) +#if defined(HAVE_CPUID) && !defined(MAC_OSX_TCL) Tcl_CreateObjCommand(interp, "testcpuid", TestcpuidCmd, NULL, NULL); #endif Tcl_CreateObjCommand(interp, "testnreunwind", TestNREUnwind, NULL, NULL); @@ -624,10 +724,14 @@ NULL, NULL); Tcl_CreateObjCommand(interp, "testgetencpath", TestgetencpathObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testsetencpath", TestsetencpathObjCmd, 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) { @@ -636,10 +740,14 @@ #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 */ @@ -661,11 +769,11 @@ Tcl_UnregisterChannel(interp, Tcl_GetChannel(interp, "stderr", &mode)); return TCL_ERROR; } case 3: - if (objc-1) { + if (objc > 1) { Tcl_SetVar2Ex(interp, "tcl_rcFileName", NULL, objv[1], TCL_GLOBAL_ONLY); } return TCL_ERROR; } @@ -700,11 +808,26 @@ int Tcltest_SafeInit( Tcl_Interp *interp) /* Interpreter for application. */ { - if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { + 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); } @@ -736,11 +859,11 @@ int id, code; static int nextId = 1; if (argc < 2) { wrongNumArgs: - Tcl_AppendResult(interp, "wrong # args", NULL); + Tcl_AppendResult(interp, "wrong # args", (void *)NULL); return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { if (argc != 3) { goto wrongNumArgs; @@ -754,11 +877,11 @@ asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc, INT2PTR(asyncPtr->id)); asyncPtr->nextPtr = firstHandler; firstHandler = asyncPtr; Tcl_MutexUnlock(&asyncTestMutex); - Tcl_SetObjResult(interp, Tcl_NewIntObj(asyncPtr->id)); + 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; @@ -810,11 +933,10 @@ } } 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) { @@ -826,28 +948,22 @@ if (asyncPtr->id == id) { Tcl_ThreadId threadID; if (Tcl_CreateThread(&threadID, AsyncThreadProc, INT2PTR(id), TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) { - Tcl_AppendResult(interp, "can't create thread", NULL); + Tcl_AppendResult(interp, "can't create thread", (void *)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 + "\": must be create, delete, int, mark, or marklater", (void *)NULL); + return TCL_ERROR; } return TCL_OK; } static int @@ -883,11 +999,11 @@ listArgv[1] = Tcl_GetStringResult(interp); listArgv[2] = string; listArgv[3] = NULL; cmd = Tcl_Merge(3, listArgv); if (interp != NULL) { - code = Tcl_EvalEx(interp, cmd, -1, 0); + code = Tcl_EvalEx(interp, cmd, TCL_INDEX_NONE, 0); } else { /* * this should not happen, but by definition of how async handlers are * invoked, it's possible. Better error checking is needed here. */ @@ -910,11 +1026,10 @@ * Invokes Tcl_AsyncMark on the handler * *---------------------------------------------------------------------- */ -#if TCL_THREADS static Tcl_ThreadCreateType AsyncThreadProc( void *clientData) /* Parameter is the id of a * TestAsyncHandler, defined above. */ { @@ -932,11 +1047,10 @@ } Tcl_MutexUnlock(&asyncTestMutex); Tcl_ExitThread(TCL_OK); TCL_THREAD_CREATE_RETURN; } -#endif static int TestbumpinterpepochObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ @@ -954,11 +1068,45 @@ } /* *---------------------------------------------------------------------- * - * TestcmdinfoCmd -- + * 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. * @@ -970,76 +1118,134 @@ * *---------------------------------------------------------------------- */ static int -TestcmdinfoCmd( +TestcmdinfoObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { + static const char *const subcmds[] = { + "call", "call2", "create", "delete", "get", "modify", NULL + }; + enum options { + CMDINFO_CALL, CMDINFO_CALL2, CMDINFO_CREATE, + CMDINFO_DELETE, CMDINFO_GET, CMDINFO_MODIFY + } idx; Tcl_CmdInfo info; + Tcl_Obj **cmdObjv; + Tcl_Size cmdObjc; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " option cmdName\"", NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "command arg"); 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) { + 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, argv[2]); + Tcl_DeleteCommand(interp, Tcl_GetString(objv[2])); Tcl_DStringResult(interp, &delString); - } else if (strcmp(argv[1], "get") == 0) { - if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) { - Tcl_AppendResult(interp, "??", NULL); + break; + case CMDINFO_GET: + if (Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ==0) { + Tcl_AppendResult(interp, "??", (void *)NULL); return TCL_OK; } if (info.proc == CmdProc1) { Tcl_AppendResult(interp, "CmdProc1", " ", - (char *) info.clientData, NULL); + (char *) info.clientData, (void *)NULL); } else if (info.proc == CmdProc2) { Tcl_AppendResult(interp, "CmdProc2", " ", - (char *) info.clientData, NULL); + (char *) info.clientData, (void *)NULL); } else { - Tcl_AppendResult(interp, "unknown", NULL); + Tcl_AppendResult(interp, "unknown", (void *)NULL); } if (info.deleteProc == CmdDelProc1) { Tcl_AppendResult(interp, " CmdDelProc1", " ", - (char *) info.deleteData, NULL); + (char *) info.deleteData, (void *)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) { + (char *) info.deleteData, (void *)NULL); + } else { + Tcl_AppendResult(interp, " unknown", (void *)NULL); + } + Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, (void *)NULL); + if (info.isNativeObjectProc == 0) { + Tcl_AppendResult(interp, " stringProc", (void *)NULL); + } else if (info.isNativeObjectProc == 1) { + Tcl_AppendResult(interp, " nativeObjectProc", (void *)NULL); + } else if (info.isNativeObjectProc == 2) { + Tcl_AppendResult(interp, " nativeObjectProc2", (void *)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"; - 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; - } + 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, (void *)NULL); return TCL_OK; } static int CmdProc1( @@ -1046,11 +1252,11 @@ void *clientData, /* String to return. */ Tcl_Interp *interp, /* Current interpreter. */ TCL_UNUSED(int) /*argc*/, TCL_UNUSED(const char **) /*argv*/) { - Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData, NULL); + Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData, (void *)NULL); return TCL_OK; } static int CmdProc2( @@ -1057,13 +1263,35 @@ void *clientData, /* String to return. */ Tcl_Interp *interp, /* Current interpreter. */ TCL_UNUSED(int) /*argc*/, TCL_UNUSED(const char **) /*argv*/) { - Tcl_AppendResult(interp, "CmdProc2 ", (char *) clientData, NULL); + Tcl_AppendResult(interp, "CmdProc2 ", (char *) clientData, (void *)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. */ { @@ -1103,45 +1331,67 @@ TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { - Tcl_Command token; - int *l; + TestCommandTokenRef *refPtr; + int id; char buf[30]; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " option arg\"", NULL); + " option arg\"", (void *)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) { + 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, (void *)NULL); + } else { + if (sscanf(argv[2], "%d", &id) != 1) { + Tcl_AppendResult(interp, "bad command token \"", argv[2], + "\"", (void *)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], - "\"", NULL); + "\"", (void *)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; - } + 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", (void *)NULL); + return TCL_ERROR; + } + } + return TCL_OK; } /* *---------------------------------------------------------------------- @@ -1171,21 +1421,21 @@ Tcl_DString buffer; int result; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " option script\"", NULL); + " option script\"", (void *)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); + result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0); if (result == TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL); + Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (void *)NULL); } Tcl_DeleteTrace(interp, cmdTrace); Tcl_DStringFree(&buffer); } else if (strcmp(argv[1], "deletetest") == 0) { /* @@ -1194,20 +1444,20 @@ * 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); + 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], -1, 0); + result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0); if (result == TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL); + Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (void *)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 @@ -1218,14 +1468,14 @@ deleteCalled = 0; cmdTrace = Tcl_CreateObjTrace(interp, 50000, TCL_ALLOW_INLINE_COMPILATION, ObjTraceProc, &deleteCalled, ObjTraceDeleteProc); - result = Tcl_EvalEx(interp, argv[2], -1, 0); + result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0); Tcl_DeleteTrace(interp, cmdTrace); if (!deleteCalled) { - Tcl_AppendResult(interp, "Delete wasn't called", NULL); + Tcl_AppendResult(interp, "Delete wasn't called", (void *)NULL); return TCL_ERROR; } else { return result; } } else if (strcmp(argv[1], "doubletest") == 0) { @@ -1232,21 +1482,21 @@ 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); + result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0); if (result == TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL); + Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (void *)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); + "\": must be tracetest, deletetest, doubletest or resulttest", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -1298,14 +1548,14 @@ static int ObjTraceProc( TCL_UNUSED(void *), Tcl_Interp *interp, /* Tcl interpreter */ - TCL_UNUSED(int) /*level*/, + TCL_UNUSED(int) /* level */, const char *command, TCL_UNUSED(Tcl_Command), - TCL_UNUSED(int) /*objc*/, + TCL_UNUSED(int) /* objc */, Tcl_Obj *const objv[]) /* Argument objects. */ { const char *word = Tcl_GetString(objv[0]); if (!strcmp(word, "Error")) { @@ -1360,11 +1610,11 @@ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " option\"", NULL); + " option\"", (void *)NULL); return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { Tcl_CreateCommand(interp, "test_ns_basic::createdcommand", CreatedCommandProc, NULL, NULL); @@ -1375,11 +1625,11 @@ 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); + "\": must be create, delete, create2, or delete2", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -1395,15 +1645,15 @@ 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); + (void *)NULL); return TCL_ERROR; } Tcl_AppendResult(interp, "CreatedCommandProc in ", - info.namespacePtr->fullName, NULL); + info.namespacePtr->fullName, (void *)NULL); return TCL_OK; } static int CreatedCommandProc2( @@ -1416,15 +1666,15 @@ 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); + (void *)NULL); return TCL_ERROR; } Tcl_AppendResult(interp, "CreatedCommandProc2 in ", - info.namespacePtr->fullName, NULL); + info.namespacePtr->fullName, (void *)NULL); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -1516,11 +1766,11 @@ { DelCmd *dPtr; Tcl_Interp *child; if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args", NULL); + Tcl_AppendResult(interp, "wrong # args", (void *)NULL); return TCL_ERROR; } child = Tcl_GetChild(interp, argv[1]); if (child == NULL) { @@ -1544,11 +1794,11 @@ TCL_UNUSED(int) /*argc*/, TCL_UNUSED(const char **) /*argv*/) { DelCmd *dPtr = (DelCmd *) clientData; - Tcl_AppendResult(interp, dPtr->deleteCmd, NULL); + Tcl_AppendResult(interp, dPtr->deleteCmd, (void *)NULL); Tcl_Free(dPtr->deleteCmd); Tcl_Free(dPtr); return TCL_OK; } @@ -1556,11 +1806,11 @@ DelDeleteProc( void *clientData) /* String command to evaluate. */ { DelCmd *dPtr = (DelCmd *)clientData; - Tcl_EvalEx(dPtr->interp, dPtr->deleteCmd, -1, 0); + Tcl_EvalEx(dPtr->interp, dPtr->deleteCmd, TCL_INDEX_NONE, 0); Tcl_ResetResult(dPtr->interp); Tcl_Free(dPtr->deleteCmd); Tcl_Free(dPtr); } @@ -1589,11 +1839,11 @@ 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); + " data_key\"", (void *)NULL); return TCL_ERROR; } Tcl_DeleteAssocData(interp, argv[1]); return TCL_OK; } @@ -1624,11 +1874,11 @@ TCL_UNUSED(void *), Tcl_Interp* interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj* const objv[]) /* Parameter vector */ { - static const char* options[] = { + static const char *options[] = { "shortest", "e", "f", NULL }; @@ -1643,12 +1893,12 @@ int status; int ndigits; int type; int decpt; int signum; - char* str; - char* endPtr; + char *str; + char *endPtr; Tcl_Obj* strObj; Tcl_Obj* retval; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "fpval ndigits type ?shorten?"); @@ -1655,12 +1905,12 @@ return TCL_ERROR; } status = Tcl_GetDoubleFromObj(interp, objv[1], &d); if (status != TCL_OK) { doubleType = Tcl_GetObjType("double"); - if (Tcl_FetchIntRep(objv[1], doubleType) - && TclIsNaN(objv[1]->internalRep.doubleValue)) { + if (Tcl_FetchInternalRep(objv[1], doubleType) + && isnan(objv[1]->internalRep.doubleValue)) { status = TCL_OK; memcpy(&d, &(objv[1]->internalRep.doubleValue), sizeof(double)); } } if (status != TCL_OK @@ -1680,11 +1930,11 @@ } str = TclDoubleDigits(d, ndigits, type, &decpt, &signum, &endPtr); strObj = Tcl_NewStringObj(str, endPtr-str); Tcl_Free(str); retval = Tcl_NewListObj(1, &strObj); - Tcl_ListObjAppendElement(NULL, retval, Tcl_NewIntObj(decpt)); + Tcl_ListObjAppendElement(NULL, retval, Tcl_NewWideIntObj(decpt)); strObj = Tcl_NewStringObj(signum ? "-" : "+", 1); Tcl_ListObjAppendElement(NULL, retval, strObj); Tcl_SetObjResult(interp, retval); return TCL_OK; } @@ -1715,11 +1965,11 @@ { int count; if (argc < 2) { wrongNumArgs: - Tcl_AppendResult(interp, "wrong # args", NULL); + Tcl_AppendResult(interp, "wrong # args", (void *)NULL); return TCL_ERROR; } if (strcmp(argv[1], "append") == 0) { if (argc != 4) { goto wrongNumArgs; @@ -1751,13 +2001,13 @@ } else if (strcmp(argv[1], "gresult") == 0) { if (argc != 3) { goto wrongNumArgs; } if (strcmp(argv[2], "staticsmall") == 0) { - Tcl_AppendResult(interp, "short", NULL); + Tcl_AppendResult(interp, "short", (void *)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); + 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", (void *)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) { @@ -1765,25 +2015,30 @@ 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); + (void *)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))); + 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) { @@ -1795,12 +2050,12 @@ 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); + "\": must be append, element, end, free, get, gresult, length, " + "result, start, toobj, or trunc", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -1808,14 +2063,249 @@ * 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}, + {"stoponerror", TCL_ENCODING_STOPONERROR}, + {"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 -- @@ -1838,33 +2328,39 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Encoding encoding; - int index, length; + Tcl_Size length; const char *string; TclEncoding *encodingPtr; static const char *const optionStrings[] = { - "create", "delete", NULL + "create", "delete", "nullength", "Tcl_ExternalToUtf", "Tcl_UtfToExternal", NULL }; enum options { - ENC_CREATE, ENC_DELETE - }; + ENC_CREATE, ENC_DELETE, ENC_NULLENGTH, ENC_EXTTOUTF, ENC_UTFTOEXT + } index; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "command ?args?"); + return TCL_ERROR; + } if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum options) index) { + switch (index) { case ENC_CREATE: { Tcl_EncodingType type; if (objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "name toutfcmd fromutfcmd"); return TCL_ERROR; } - encodingPtr = (TclEncoding*)Tcl_Alloc(sizeof(TclEncoding)); + encodingPtr = (TclEncoding *)Tcl_Alloc(sizeof(TclEncoding)); encodingPtr->interp = interp; string = Tcl_GetStringFromObj(objv[3], &length); encodingPtr->toUtfCmd = (char *)Tcl_Alloc(length + 1); memcpy(encodingPtr->toUtfCmd, string, length + 1); @@ -1892,12 +2388,31 @@ if (TCL_OK != Tcl_GetEncodingFromObj(interp, objv[2], &encoding)) { return TCL_ERROR; } Tcl_FreeEncoding(encoding); /* Free returned reference */ Tcl_FreeEncoding(encoding); /* Free to match CREATE */ - TclFreeIntRep(objv[2]); /* Free the cached ref */ + TclFreeInternalRep(objv[2]); /* Free the cached ref */ break; + + case ENC_NULLENGTH: + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?encoding?"); + return TCL_ERROR; + } + encoding = + Tcl_GetEncoding(interp, objc == 2 ? NULL : Tcl_GetString(objv[2])); + if (encoding == NULL) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, + Tcl_NewIntObj(Tcl_GetEncodingNulLength(encoding))); + Tcl_FreeEncoding(encoding); + break; + case ENC_EXTTOUTF: + return UtfExtWrapper(interp,Tcl_ExternalToUtf,objc,objv); + case ENC_UTFTOEXT: + return UtfExtWrapper(interp,Tcl_UtfToExternal,objc,objv); } return TCL_OK; } static int @@ -1915,11 +2430,11 @@ { int len; TclEncoding *encodingPtr; encodingPtr = (TclEncoding *) clientData; - Tcl_EvalEx(encodingPtr->interp, encodingPtr->toUtfCmd, -1, TCL_EVAL_GLOBAL); + Tcl_EvalEx(encodingPtr->interp, encodingPtr->toUtfCmd, TCL_INDEX_NONE, TCL_EVAL_GLOBAL); len = strlen(Tcl_GetStringResult(encodingPtr->interp)); if (len > dstLen) { len = dstLen; } @@ -1947,11 +2462,11 @@ { int len; TclEncoding *encodingPtr; encodingPtr = (TclEncoding *) clientData; - Tcl_EvalEx(encodingPtr->interp, encodingPtr->fromUtfCmd, -1, TCL_EVAL_GLOBAL); + Tcl_EvalEx(encodingPtr->interp, encodingPtr->fromUtfCmd, TCL_INDEX_NONE, TCL_EVAL_GLOBAL); len = strlen(Tcl_GetStringResult(encodingPtr->interp)); if (len > dstLen) { len = dstLen; } @@ -1997,19 +2512,20 @@ TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int length, flags; + int flags; + Tcl_Size length; const char *script; flags = 0; if (objc == 3) { const char *global = Tcl_GetString(objv[2]); if (strcmp(global, "global") != 0) { Tcl_AppendResult(interp, "bad value \"", global, - "\": must be global", NULL); + "\": must be global", (void *)NULL); return TCL_ERROR; } flags = TCL_EVAL_GLOBAL; } else if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "script ?global?"); @@ -2099,11 +2615,11 @@ int subCmdIndex; /* Index of the chosen subcommand */ static const char *const positions[] = { /* Possible queue positions */ "head", "tail", "mark", NULL }; int posIndex; /* Index of the chosen position */ - static const Tcl_QueuePosition posNum[] = { + static const int posNum[] = { /* Interpretation of the chosen position */ TCL_QUEUE_HEAD, TCL_QUEUE_TAIL, TCL_QUEUE_MARK }; @@ -2274,11 +2790,11 @@ { int value; if (argc != 3) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], - " create|delete value\"", NULL); + " create|delete value\"", (void *)NULL); return TCL_ERROR; } if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) { return TCL_ERROR; } @@ -2288,11 +2804,11 @@ } 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); + "\": must be create or delete", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -2301,11 +2817,11 @@ void *clientData) /* Integer value to print. */ { char buf[16 + TCL_INTEGER_SPACE]; int len; - sprintf(buf, "odd %d\n", (int)PTR2INT(clientData)); + snprintf(buf, sizeof(buf), "odd %d\n", (int)PTR2INT(clientData)); len = strlen(buf); if (len != (int) write(1, buf, len)) { Tcl_Panic("ExitProcOdd: unable to write to stdout"); } } @@ -2315,11 +2831,11 @@ void *clientData) /* Integer value to print. */ { char buf[16 + TCL_INTEGER_SPACE]; int len; - sprintf(buf, "even %d\n", (int)PTR2INT(clientData)); + snprintf(buf, sizeof(buf), "even %d\n", (int)PTR2INT(clientData)); len = strlen(buf); if (len != (int) write(1, buf, len)) { Tcl_Panic("ExitProcEven: unable to write to stdout"); } } @@ -2352,20 +2868,20 @@ char buf[4 + TCL_INTEGER_SPACE]; int result; if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], - " expression\"", NULL); + " expression\"", (void *)NULL); return TCL_ERROR; } - Tcl_AppendResult(interp, "This is a result", NULL); + Tcl_AppendResult(interp, "This is a result", (void *)NULL); result = Tcl_ExprLong(interp, argv[1], &exprResult); if (result != TCL_OK) { return result; } - sprintf(buf, ": %ld", exprResult); - Tcl_AppendResult(interp, buf, NULL); + snprintf(buf, sizeof(buf), ": %ld", exprResult); + Tcl_AppendResult(interp, buf, (void *)NULL); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2397,17 +2913,17 @@ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "expression"); return TCL_ERROR; } - Tcl_AppendResult(interp, "This is a result", NULL); + Tcl_AppendResult(interp, "This is a result", (void *)NULL); result = Tcl_ExprLongObj(interp, objv[1], &exprResult); if (result != TCL_OK) { return result; } - sprintf(buf, ": %ld", exprResult); - Tcl_AppendResult(interp, buf, NULL); + snprintf(buf, sizeof(buf), ": %ld", exprResult); + Tcl_AppendResult(interp, buf, (void *)NULL); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2437,21 +2953,21 @@ char buf[4 + TCL_DOUBLE_SPACE]; int result; if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], - " expression\"", NULL); + " expression\"", (void *)NULL); return TCL_ERROR; } - Tcl_AppendResult(interp, "This is a result", NULL); + Tcl_AppendResult(interp, "This is a result", (void *)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); + Tcl_AppendResult(interp, buf, (void *)NULL); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2483,18 +2999,18 @@ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "expression"); return TCL_ERROR; } - Tcl_AppendResult(interp, "This is a result", NULL); + Tcl_AppendResult(interp, "This is a result", (void *)NULL); result = Tcl_ExprDoubleObj(interp, objv[1], &exprResult); if (result != TCL_OK) { return result; } strcpy(buf, ": "); Tcl_PrintDouble(interp, exprResult, buf+2); - Tcl_AppendResult(interp, buf, NULL); + Tcl_AppendResult(interp, buf, (void *)NULL); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2519,11 +3035,11 @@ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], - " expression\"", NULL); + " expression\"", (void *)NULL); return TCL_ERROR; } return Tcl_ExprString(interp, argv[1]); } @@ -2568,20 +3084,20 @@ TCL_CREATE_SYMBOLIC_LINK|TCL_CREATE_HARD_LINK); if (contents == NULL) { Tcl_AppendResult(interp, "could not create link from \"", Tcl_GetString(objv[1]), "\" to \"", Tcl_GetString(objv[2]), "\": ", - Tcl_PosixError(interp), NULL); + Tcl_PosixError(interp), (void *)NULL); return TCL_ERROR; } } else { /* Read link */ contents = Tcl_FSLink(objv[1], NULL, 0); if (contents == NULL) { Tcl_AppendResult(interp, "could not read link \"", Tcl_GetString(objv[1]), "\": ", - Tcl_PosixError(interp), NULL); + Tcl_PosixError(interp), (void *)NULL); return TCL_ERROR; } } Tcl_SetObjResult(interp, contents); if (objc == 2) { @@ -2620,16 +3136,16 @@ { char *res; if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], - " data_key\"", NULL); + " data_key\"", (void *)NULL); return TCL_ERROR; } res = (char *) Tcl_GetAssocData(interp, argv[1], NULL); if (res != NULL) { - Tcl_AppendResult(interp, res, NULL); + Tcl_AppendResult(interp, res, (void *)NULL); } return TCL_OK; } /* @@ -2636,11 +3152,11 @@ *---------------------------------------------------------------------- * * TestgetplatformCmd -- * * This procedure implements the "testgetplatform" command. It is - * used to retrievel the value of the tclPlatform global variable. + * used to retrieve the value of the tclPlatform global variable. * * Results: * A standard Tcl result. * * Side effects: @@ -2661,15 +3177,15 @@ platform = TclGetPlatform(); if (argc != 1) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], - NULL); + (void *)NULL); return TCL_ERROR; } - Tcl_AppendResult(interp, platformStrings[*platform], NULL); + Tcl_AppendResult(interp, platformStrings[*platform], (void *)NULL); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2698,11 +3214,11 @@ { Tcl_Interp *childToDelete; if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " path\"", NULL); + " path\"", (void *)NULL); return TCL_ERROR; } childToDelete = Tcl_GetChild(interp, argv[1]); if (childToDelete == NULL) { return TCL_ERROR; @@ -2756,19 +3272,19 @@ 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); + " arg arg?\"", (void *)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); + " ushortRO uintRO longRO ulongRO floatRO uwideRO\"", (void *)NULL); return TCL_ERROR; } if (created) { Tcl_UnlinkVar(interp, "int"); Tcl_UnlinkVar(interp, "real"); @@ -2787,115 +3303,115 @@ } created = 1; if (Tcl_GetBoolean(interp, argv[2], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "int", &intVar, TCL_LINK_INT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[3], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "real", &realVar, TCL_LINK_DOUBLE | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[4], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "bool", &boolVar, TCL_LINK_BOOLEAN | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[5], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "string", &stringVar, TCL_LINK_STRING | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[6], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "wide", &wideVar, TCL_LINK_WIDE_INT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[7], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "char", &charVar, TCL_LINK_CHAR | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[8], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "uchar", &ucharVar, TCL_LINK_UCHAR | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[9], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "short", &shortVar, TCL_LINK_SHORT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[10], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "ushort", &ushortVar, TCL_LINK_USHORT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[11], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "uint", &uintVar, TCL_LINK_UINT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[12], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "long", &longVar, TCL_LINK_LONG | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[13], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "ulong", &ulongVar, TCL_LINK_ULONG | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[14], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "float", &floatVar, TCL_LINK_FLOAT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[15], &writable) != TCL_OK) { return TCL_ERROR; } - flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; + flag = writable ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "uwide", &uwideVar, TCL_LINK_WIDE_UINT | flag) != TCL_OK) { return TCL_ERROR; } @@ -2940,16 +3456,33 @@ 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); +#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); - tmp = Tcl_NewWideIntObj((Tcl_WideInt)uwideVar); + 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; @@ -2956,11 +3489,11 @@ 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); + " longValue ulongValue floatValue uwideValue\"", (void *)NULL); return TCL_ERROR; } if (argv[2][0] != 0) { if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) { return TCL_ERROR; @@ -3060,11 +3593,11 @@ 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); + " longValue ulongValue floatValue uwideValue\"", (void *)NULL); return TCL_ERROR; } if (argv[2][0] != 0) { if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) { return TCL_ERROR; @@ -3172,11 +3705,11 @@ 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); + "\": should be create, delete, get, set, or update", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -3205,11 +3738,11 @@ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *LinkOption[] = { "update", "remove", "create", NULL }; - enum LinkOptionEnum { LINK_UPDATE, LINK_REMOVE, LINK_CREATE }; + enum LinkOptionEnum { LINK_UPDATE, LINK_REMOVE, LINK_CREATE } optionIndex; static const char *LinkType[] = { "char", "uchar", "short", "ushort", "int", "uint", "long", "ulong", "wide", "uwide", "float", "double", "string", "char*", "binary", NULL }; /* all values after TCL_LINK_CHARS_ARRAY are used as arrays (see below) */ @@ -3218,11 +3751,12 @@ TCL_LINK_SHORT, TCL_LINK_USHORT, TCL_LINK_INT, TCL_LINK_UINT, TCL_LINK_LONG, TCL_LINK_ULONG, TCL_LINK_WIDE_INT, TCL_LINK_WIDE_UINT, TCL_LINK_FLOAT, TCL_LINK_DOUBLE, TCL_LINK_STRING, TCL_LINK_CHARS, TCL_LINK_BINARY }; - int optionIndex, typeIndex, readonly, i, size, length; + int typeIndex, readonly, i, size; + Tcl_Size length; char *name, *arg; Tcl_WideInt addr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option args"); @@ -3230,11 +3764,11 @@ } if (Tcl_GetIndexFromObj(interp, objv[1], LinkOption, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } - switch ((enum LinkOptionEnum) optionIndex) { + switch (optionIndex) { case LINK_UPDATE: for (i=2; i 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", (void *)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 -- @@ -3385,10 +4075,57 @@ } /* *---------------------------------------------------------------------- * + * TestmsbObjCmd -- + * + * This procedure implements the "testmsb" command. It is + * used for testing the TclMSB() routine. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TestmsbObjCmd( + ClientData clientData, /* Not used. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* The argument objects. */ +{ + Tcl_WideInt w = 0; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "integer"); + return TCL_ERROR; + } + if (sizeof(Tcl_WideUInt) <= sizeof(size_t)) { + if (TCL_OK != Tcl_GetWideIntFromObj(interp, objv[1], &w)) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(TclMSB(w))); + } else { + int i; + if (TCL_OK != Tcl_GetIntFromObj(interp, objv[1], &i)) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(TclMSB(i))); + } + return TCL_OK; + + (void)clientData; +} + +/* + *---------------------------------------------------------------------- + * * TestparserObjCmd -- * * This procedure implements the "testparser" command. It is * used for testing the new Tcl script parser in Tcl 8.1. * @@ -3407,11 +4144,12 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { const char *script; - int length, dummy; + Tcl_Size dummy; + int length; Tcl_Parse parse; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "script length"); return TCL_ERROR; @@ -3463,11 +4201,12 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { const char *script; - int length, dummy; + Tcl_Size dummy; + int length; Tcl_Parse parse; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "expr length"); return TCL_ERROR; @@ -3525,11 +4264,11 @@ Tcl_Parse *parsePtr) /* Parse structure to print out. */ { Tcl_Obj *objPtr; const char *typeString; Tcl_Token *tokenPtr; - int i; + Tcl_Size i; objPtr = Tcl_GetObjResult(interp); if (parsePtr->commentSize > 0) { Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(parsePtr->commentStart, @@ -3538,11 +4277,11 @@ Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj("-", 1)); } Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(parsePtr->commandStart, parsePtr->commandSize)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(parsePtr->numWords)); + Tcl_NewWideIntObj(parsePtr->numWords)); for (i = 0; i < parsePtr->numTokens; i++) { tokenPtr = &parsePtr->tokenPtr[i]; switch (tokenPtr->type) { case TCL_TOKEN_EXPAND_WORD: typeString = "expand"; @@ -3578,15 +4317,16 @@ Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(typeString, -1)); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(tokenPtr->start, tokenPtr->size)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(tokenPtr->numComponents)); + Tcl_NewWideIntObj(tokenPtr->numComponents)); } Tcl_ListObjAppendElement(NULL, objPtr, + parsePtr->commandStart ? Tcl_NewStringObj(parsePtr->commandStart + parsePtr->commandSize, - -1)); + TCL_INDEX_NONE) : Tcl_NewObj()); } /* *---------------------------------------------------------------------- * @@ -3651,11 +4391,12 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { const char *script; - int append, length, dummy; + int length, append; + Tcl_Size dummy; Tcl_Parse parse; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "script length append"); return TCL_ERROR; @@ -3784,12 +4525,12 @@ 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 i, indices, match, about; + Tcl_Size stringLength, ii; int hasxflags, cflags, eflags; Tcl_RegExp regExpr; const char *string; Tcl_Obj *objPtr; Tcl_RegExpInfo info; @@ -3802,31 +4543,30 @@ enum optionsEnum { REGEXP_INDICES, REGEXP_NOCASE, REGEXP_ABOUT, REGEXP_EXPANDED, REGEXP_MULTI, REGEXP_NOCROSS, REGEXP_NEWL, REGEXP_XFLAGS, REGEXP_LAST - }; + } index; indices = 0; about = 0; cflags = REG_ADVANCED; eflags = 0; hasxflags = 0; for (i = 1; i < objc; i++) { const char *name; - int index; name = Tcl_GetString(objv[i]); if (name[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum optionsEnum) index) { + switch (index) { case REGEXP_INDICES: indices = 1; break; case REGEXP_NOCASE: cflags |= REG_ICASE; @@ -3894,38 +4634,38 @@ /* * Set the interpreter's object result to an integer object w/ * value 0. */ - Tcl_SetIntObj(Tcl_GetObjResult(interp), 0); + Tcl_SetWideIntObj(Tcl_GetObjResult(interp), 0); if (objc > 2 && (cflags®_EXPECT) && indices) { const char *varName; const char *value; - size_t start, end; + Tcl_Size start, end; char resinfo[TCL_INTEGER_SPACE * 2]; varName = Tcl_GetString(objv[2]); - TclRegExpRangeUniChar(regExpr, -1, &start, &end); - sprintf(resinfo, "%d %d", (int)start, (int)(end-1)); + TclRegExpRangeUniChar(regExpr, TCL_INDEX_NONE, &start, &end); + snprintf(resinfo, sizeof(resinfo), "%" TCL_Z_MODIFIER "d %" TCL_Z_MODIFIER "d", start, end-1); value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0); if (value == NULL) { Tcl_AppendResult(interp, "couldn't set variable \"", - varName, "\"", NULL); + varName, "\"", (void *)NULL); return TCL_ERROR; } } else if (cflags & TCL_REG_CANMATCH) { const char *varName; const char *value; char resinfo[TCL_INTEGER_SPACE * 2]; Tcl_RegExpGetInfo(regExpr, &info); varName = Tcl_GetString(objv[2]); - sprintf(resinfo, "%d", (int)info.extendStart); + snprintf(resinfo, sizeof(resinfo), "%" TCL_Z_MODIFIER "d", info.extendStart); value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0); if (value == NULL) { Tcl_AppendResult(interp, "couldn't set variable \"", - varName, "\"", NULL); + varName, "\"", (void *)NULL); return TCL_ERROR; } } return TCL_OK; } @@ -3938,15 +4678,15 @@ objc -= 2; objv += 2; Tcl_RegExpGetInfo(regExpr, &info); for (i = 0; i < objc; i++) { - size_t start, end; + Tcl_Size start, end; Tcl_Obj *newPtr, *varPtr, *valuePtr; varPtr = objv[i]; - ii = ((cflags®_EXPECT) && i == objc-1) ? TCL_INDEX_NONE : (size_t)i; + ii = ((cflags®_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); @@ -3965,19 +4705,19 @@ if (end != TCL_INDEX_NONE) { end--; } - objs[0] = Tcl_NewIntObj(start); - objs[1] = Tcl_NewIntObj(end); + objs[0] = Tcl_NewWideIntObj(start); + objs[1] = Tcl_NewWideIntObj(end); newPtr = Tcl_NewListObj(2, objs); } else { if (ii == TCL_INDEX_NONE) { TclRegExpRangeUniChar(regExpr, ii, &start, &end); newPtr = Tcl_GetRange(objPtr, start, end); - } else if (ii > info.nsubs) { + } else if (ii > info.nsubs || info.matches[ii].end <= 0) { newPtr = Tcl_NewObj(); } else { newPtr = Tcl_GetRange(objPtr, info.matches[ii].start, info.matches[ii].end - 1); } @@ -3990,11 +4730,11 @@ /* * Set the interpreter's object result to an integer object w/ value 1. */ - Tcl_SetIntObj(Tcl_GetObjResult(interp), 1); + Tcl_SetWideIntObj(Tcl_GetObjResult(interp), 1); return TCL_OK; } /* *--------------------------------------------------------------------------- @@ -4142,11 +4882,11 @@ char *buf, *oldData; Tcl_InterpDeleteProc *procPtr; if (argc != 3) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], - " data_key data_item\"", NULL); + " data_key data_item\"", (void *)NULL); return TCL_ERROR; } buf = (char *)Tcl_Alloc(strlen(argv[2]) + 1); strcpy(buf, argv[2]); @@ -4195,11 +4935,11 @@ platform = TclGetPlatform(); if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], - " platform\"", NULL); + " platform\"", (void *)NULL); return TCL_ERROR; } length = strlen(argv[1]); if (strncmp(argv[1], "unix", length) == 0) { @@ -4206,55 +4946,55 @@ *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); + "unix, or windows", (void *)NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * - * TeststaticpkgCmd -- + * TeststaticlibraryCmd -- * - * This procedure implements the "teststaticpkg" command. - * It is used to test the procedure Tcl_StaticPackage. + * This procedure implements the "teststaticlibrary" command. + * It is used to test the procedure Tcl_StaticLibrary. * * Results: * A standard Tcl result. * * Side effects: - * When the packge given by argv[1] is loaded into an interpeter, + * When the package given by argv[1] is loaded into an interpreter, * variable "x" in that interpreter is set to "loaded". * *---------------------------------------------------------------------- */ static int -TeststaticpkgCmd( +TeststaticlibraryCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { int safe, loaded; if (argc != 4) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", - argv[0], " pkgName safe loaded\"", NULL); + argv[0], " prefix safe loaded\"", (void *)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], + Tcl_StaticLibrary((loaded) ? interp : NULL, argv[1], StaticInitProc, (safe) ? StaticInitProc : NULL); return TCL_OK; } static int @@ -4293,18 +5033,18 @@ Tcl_DString buffer; const char *result; if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", - argv[0], " path\"", NULL); + argv[0], " path\"", (void *)NULL); return TCL_ERROR; } result = Tcl_TranslateFileName(interp, argv[1], &buffer); if (result == NULL) { return TCL_ERROR; } - Tcl_AppendResult(interp, result, NULL); + Tcl_AppendResult(interp, result, (void *)NULL); Tcl_DStringFree(&buffer); return TCL_OK; } /* @@ -4333,11 +5073,11 @@ { int flags = 0; if ((argc != 5) && (argc != 6)) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", - argv[0], " level name ?name2? dest global\"", NULL); + argv[0], " level name ?name2? dest global\"", (void *)NULL); return TCL_ERROR; } if (argc == 5) { if (strcmp(argv[4], "global") == 0) { @@ -4382,32 +5122,32 @@ 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); + Tcl_AppendResult(interp, "too many args", (void *)NULL); return TCL_ERROR; } switch (argc) { case 1: - Tcl_SetErrorCode(interp, "NONE", NULL); + Tcl_SetErrorCode(interp, "NONE", (void *)NULL); break; case 2: - Tcl_SetErrorCode(interp, argv[1], NULL); + Tcl_SetErrorCode(interp, argv[1], (void *)NULL); break; case 3: - Tcl_SetErrorCode(interp, argv[1], argv[2], NULL); + Tcl_SetErrorCode(interp, argv[1], argv[2], (void *)NULL); break; case 4: - Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], NULL); + Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], (void *)NULL); break; case 5: - Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], NULL); + Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], (void *)NULL); break; case 6: Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], - argv[5], NULL); + argv[5], (void *)NULL); } return TCL_ERROR; } /* @@ -4467,27 +5207,27 @@ int code; Tcl_Channel chan; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " option ?arg ...?", NULL); + " option ?arg ...?", (void *)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); + " cmd script", (void *)NULL); return TCL_ERROR; } if (interp2 != NULL) { - code = Tcl_EvalEx(interp2, argv[2], -1, TCL_EVAL_GLOBAL); + 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\"", - NULL); + (void *)NULL); return TCL_ERROR; } } else if (strcmp(argv[1], "create") == 0) { if (interp2 != NULL) { Tcl_DeleteInterp(interp2); @@ -4599,15 +5339,15 @@ } if (result != TCL_OK) { if (error != NULL) { if (Tcl_GetString(error)[0] != '\0') { - Tcl_AppendResult(interp, Tcl_GetString(error), " ", NULL); + Tcl_AppendResult(interp, Tcl_GetString(error), " ", (void *)NULL); } Tcl_DecrRefCount(error); } - Tcl_AppendResult(interp, Tcl_ErrnoId(), NULL); + Tcl_AppendResult(interp, Tcl_ErrnoId(), (void *)NULL); } end: return result; } @@ -4690,11 +5430,11 @@ * * 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. + * variables, allocating memory, snprintf, converting variables, etc. * * Results: * A standard Tcl result. * * Side effects: @@ -4771,19 +5511,19 @@ timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per Tcl_DecrRefCount\n", timePer/5000); Tcl_Free(objv); /* TclGetString 100000 times */ - fprintf(stderr, "TclGetStringFromObj of \"12345\" 100000 times\n"); + fprintf(stderr, "Tcl_GetStringFromObj of \"12345\" 100000 times\n"); objPtr = Tcl_NewStringObj("12345", -1); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { (void) TclGetString(objPtr); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); - fprintf(stderr, " %.3f usec per TclGetStringFromObj of \"12345\"\n", + fprintf(stderr, " %.3f usec per Tcl_GetStringFromObj of \"12345\"\n", timePer/100000); /* Tcl_GetIntFromObj 100000 times */ fprintf(stderr, "Tcl_GetIntFromObj of \"12345\" 100000 times\n"); Tcl_GetTime(&start); @@ -4809,19 +5549,19 @@ Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per Tcl_GetInt of \"12345\"\n", timePer/100000); - /* sprintf 100000 times */ - fprintf(stderr, "sprintf of 12345 100000 times\n"); + /* snprintf 100000 times */ + fprintf(stderr, "snprintf of 12345 100000 times\n"); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { - sprintf(newString, "%d", 12345); + snprintf(newString, sizeof(newString), "%d", 12345); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); - fprintf(stderr, " %.3f usec per sprintf of 12345\n", + fprintf(stderr, " %.3f usec per snprintf of 12345\n", timePer/100000); /* hashtable lookup 100000 times */ fprintf(stderr, "hashtable lookup of \"gettimes\" 100000 times\n"); Tcl_GetTime(&start); @@ -4939,11 +5679,11 @@ TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { - int n; + Tcl_Size n; const unsigned char *p; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "value"); return TCL_ERROR; @@ -5036,16 +5776,21 @@ 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]; + obj = objv[1]; + if (Tcl_IsShared(obj)) { + obj = Tcl_DuplicateObj(obj); } - Tcl_SetByteArrayLength(obj, n); + if (Tcl_SetByteArrayLength(obj, n) == NULL) { + if (obj != objv[1]) { + Tcl_DecrRefCount(obj); + } + Tcl_AppendResult(interp, "expected bytes", (void *)NULL); + return TCL_ERROR; + } Tcl_SetObjResult(interp, obj); return TCL_OK; } /* @@ -5070,23 +5815,44 @@ TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { - size_t n = 0; + struct { +#if !defined(TCL_NO_DEPRECATED) +# if defined(_MSC_VER) && !defined(NDEBUG) +# pragma warning(disable:4133) +# elif defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wincompatible-pointer-types" +# endif + 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 *)TclGetBytesFromObj(interp, objv[1], &n); + p = (const char *)Tcl_GetBytesFromObj(interp, objv[1], &x.n); if (p == NULL) { return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n)); +#if !defined(TCL_NO_DEPRECATED) && defined(__clang__) +# pragma clang diagnostic pop +#endif + + if (x.m != 1) { + Tcl_AppendResult(interp, "Tcl_GetBytesFromObj() overwrites variable", (void *)NULL); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(p, x.n)); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -5114,28 +5880,28 @@ { int flags = PTR2INT(data); const char *value; if (argc == 2) { - Tcl_AppendResult(interp, "before get", NULL); + Tcl_AppendResult(interp, "before get", (void *)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); + Tcl_AppendResult(interp, "before set", (void *)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); + argv[0], " varName ?newValue?\"", (void *)NULL); return TCL_ERROR; } } static int Testset2Cmd( @@ -5146,157 +5912,30 @@ { int flags = PTR2INT(data); const char *value; if (argc == 3) { - Tcl_AppendResult(interp, "before get", NULL); + Tcl_AppendResult(interp, "before get", (void *)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); + Tcl_AppendResult(interp, "before set", (void *)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++; + argv[0], " varName elemName ?newValue?\"", (void *)NULL); + return TCL_ERROR; + } } /* *---------------------------------------------------------------------- * @@ -5325,11 +5964,11 @@ Tcl_Obj *idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)Tcl_GetCurrentThread()); Tcl_SetObjResult(interp, idObj); return TCL_OK; } else { - Tcl_AppendResult(interp, "wrong # args", NULL); + Tcl_AppendResult(interp, "wrong # args", (void *)NULL); return TCL_ERROR; } } /* @@ -5446,16 +6085,16 @@ 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. */ + 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..?\"", NULL); + " subcommand ?additional args..?\"", (void *)NULL); return TCL_ERROR; } cmdName = argv[1]; len = strlen(cmdName); @@ -5497,11 +6136,11 @@ chan = NULL; } if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerror", len) == 0)) { - Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1); + Tcl_Obj *msg = Tcl_NewStringObj(argv[3], -1); Tcl_IncrRefCount(msg); Tcl_SetChannelError(chan, msg); Tcl_DecrRefCount(msg); @@ -5510,11 +6149,11 @@ Tcl_DecrRefCount(msg); return TCL_OK; } if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerrorinterp", len) == 0)) { - Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1); + Tcl_Obj *msg = Tcl_NewStringObj(argv[3], -1); Tcl_IncrRefCount(msg); Tcl_SetChannelErrorInterp(interp, msg); Tcl_DecrRefCount(msg); @@ -5534,11 +6173,11 @@ 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); + " cut channelName\"", (void *)NULL); return TCL_ERROR; } Tcl_RegisterChannel(NULL, chan); /* prevent closing */ Tcl_UnregisterChannel(interp, chan); @@ -5557,21 +6196,21 @@ if ((cmdName[0] == 'c') && (strncmp(cmdName, "clearchannelhandlers", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " clearchannelhandlers channelName\"", NULL); + " clearchannelhandlers channelName\"", (void *)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); + " info channelName\"", (void *)NULL); return TCL_ERROR; } Tcl_AppendElement(interp, argv[2]); Tcl_AppendElement(interp, Tcl_ChannelName(chanPtr->typePtr)); if (statePtr->flags & TCL_READABLE) { @@ -5659,44 +6298,44 @@ } if ((cmdName[0] == 'i') && (strncmp(cmdName, "inputbuffered", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } IOQueued = Tcl_InputBuffered(chan); TclFormatInt(buf, IOQueued); - Tcl_AppendResult(interp, buf, NULL); + Tcl_AppendResult(interp, buf, (void *)NULL); return TCL_OK; } if ((cmdName[0] == 'i') && (strncmp(cmdName, "isshared", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } TclFormatInt(buf, Tcl_IsChannelShared(chan)); - Tcl_AppendResult(interp, buf, NULL); + Tcl_AppendResult(interp, buf, (void *)NULL); return TCL_OK; } if ((cmdName[0] == 'i') && (strncmp(cmdName, "isstandard", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } TclFormatInt(buf, Tcl_IsStandardChannel(chan)); - Tcl_AppendResult(interp, buf, NULL); + Tcl_AppendResult(interp, buf, (void *)NULL); return TCL_OK; } if ((cmdName[0] == 'm') && (strncmp(cmdName, "mode", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } if (statePtr->flags & TCL_READABLE) { Tcl_AppendElement(interp, "read"); @@ -5708,14 +6347,51 @@ } 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", (void *)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", (void *)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", (void *)NULL); + return TCL_ERROR; + } + + return Tcl_RemoveChannelMode(interp, chan, TCL_WRITABLE); + } if ((cmdName[0] == 'm') && (strncmp(cmdName, "mthread", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj( (Tcl_WideInt) (size_t) Tcl_GetChannelThread(chan))); @@ -5722,14 +6398,14 @@ return TCL_OK; } if ((cmdName[0] == 'n') && (strncmp(cmdName, "name", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } - Tcl_AppendResult(interp, statePtr->channelName, NULL); + Tcl_AppendResult(interp, statePtr->channelName, (void *)NULL); return TCL_OK; } if ((cmdName[0] == 'o') && (strncmp(cmdName, "open", len) == 0)) { hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL); @@ -5745,29 +6421,29 @@ } if ((cmdName[0] == 'o') && (strncmp(cmdName, "outputbuffered", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } IOQueued = Tcl_OutputBuffered(chan); TclFormatInt(buf, IOQueued); - Tcl_AppendResult(interp, buf, NULL); + Tcl_AppendResult(interp, buf, (void *)NULL); return TCL_OK; } if ((cmdName[0] == 'q') && (strncmp(cmdName, "queuedcr", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } Tcl_AppendResult(interp, - (statePtr->flags & INPUT_SAW_CR) ? "1" : "0", NULL); + (statePtr->flags & INPUT_SAW_CR) ? "1" : "0", (void *)NULL); return TCL_OK; } if ((cmdName[0] == 'r') && (strncmp(cmdName, "readable", len) == 0)) { hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL); @@ -5786,16 +6462,16 @@ return TCL_OK; } if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } TclFormatInt(buf, statePtr->refCount); - Tcl_AppendResult(interp, buf, NULL); + Tcl_AppendResult(interp, buf, (void *)NULL); return TCL_OK; } /* * "splice" is actually more a simplified attach facility as provided by @@ -5804,11 +6480,11 @@ * 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); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } Tcl_SpliceChannel(chan); @@ -5818,14 +6494,14 @@ return TCL_OK; } if ((cmdName[0] == 't') && (strncmp(cmdName, "type", len) == 0)) { if (argc != 3) { - Tcl_AppendResult(interp, "channel name required", NULL); + Tcl_AppendResult(interp, "channel name required", (void *)NULL); return TCL_ERROR; } - Tcl_AppendResult(interp, Tcl_ChannelName(chanPtr->typePtr), NULL); + Tcl_AppendResult(interp, Tcl_ChannelName(chanPtr->typePtr), (void *)NULL); return TCL_OK; } if ((cmdName[0] == 'w') && (strncmp(cmdName, "writable", len) == 0)) { hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL); @@ -5848,16 +6524,16 @@ * Syntax: transform channel -command command */ if (argc != 5) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " transform channelId -command cmd\"", NULL); + " transform channelId -command cmd\"", (void *)NULL); return TCL_ERROR; } if (strcmp(argv[3], "-command") != 0) { Tcl_AppendResult(interp, "bad argument \"", argv[3], - "\": should be \"-command\"", NULL); + "\": should be \"-command\"", (void *)NULL); return TCL_ERROR; } return TclChannelTransform(interp, chan, Tcl_NewStringObj(argv[4], -1)); @@ -5868,19 +6544,19 @@ * Syntax: unstack channel */ if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " unstack channel\"", NULL); + " unstack channel\"", (void *)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); + "readable, splice, writable, transform, unstack", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -5913,11 +6589,11 @@ 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); + " channelName cmd ?arg1? ?arg2?\"", (void *)NULL); return TCL_ERROR; } chanPtr = (Channel *) Tcl_GetChannel(interp, argv[1], NULL); if (chanPtr == NULL) { return TCL_ERROR; @@ -5927,11 +6603,11 @@ 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); + " channelName add eventSpec script\"", (void *)NULL); return TCL_ERROR; } if (strcmp(argv[3], "readable") == 0) { mask = TCL_READABLE; } else if (strcmp(argv[3], "writable") == 0) { @@ -5938,11 +6614,11 @@ 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); + "\": must be readable, writable, or none", (void *)NULL); return TCL_ERROR; } esPtr = (EventScriptRecord *)Tcl_Alloc(sizeof(EventScriptRecord)); esPtr->nextPtr = statePtr->scriptRecordPtr; @@ -5961,29 +6637,29 @@ } 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); + " channelName delete index\"", (void *)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); + ": must be nonnegative", (void *)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); + ": out of range", (void *)NULL); return TCL_ERROR; } if (esPtr == statePtr->scriptRecordPtr) { statePtr->scriptRecordPtr = esPtr->nextPtr; } else { @@ -6007,11 +6683,11 @@ } if ((cmd[0] == 'l') && (strncmp(cmd, "list", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " channelName list\"", NULL); + " channelName list\"", (void *)NULL); return TCL_ERROR; } resultListPtr = Tcl_GetObjResult(interp); for (esPtr = statePtr->scriptRecordPtr; esPtr != NULL; @@ -6030,11 +6706,11 @@ } if ((cmd[0] == 'r') && (strncmp(cmd, "removeall", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " channelName removeall\"", NULL); + " channelName removeall\"", (void *)NULL); return TCL_ERROR; } for (esPtr = statePtr->scriptRecordPtr; esPtr != NULL; esPtr = nextEsPtr) { @@ -6049,29 +6725,29 @@ } 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); + " channelName delete index event\"", (void *)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); + ": must be nonnegative", (void *)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); + ": out of range", (void *)NULL); return TCL_ERROR; } if (strcmp(argv[4], "readable") == 0) { mask = TCL_READABLE; @@ -6079,20 +6755,20 @@ 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); + "\": must be readable, writable, or none", (void *)NULL); return TCL_ERROR; } esPtr->mask = mask; Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask, TclChannelEventScriptInvoker, esPtr); return TCL_OK; } Tcl_AppendResult(interp, "bad command ", cmd, ", must be one of " - "add, delete, list, set, or removeall", NULL); + "add, delete, list, set, or removeall", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -6109,10 +6785,14 @@ * 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. */ @@ -6121,46 +6801,54 @@ 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); + " subcommand ?additional args..?\"", (void *)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\"", NULL); + " testflags channel flags\"", (void *)NULL); return TCL_ERROR; } hChannel = Tcl_GetChannel(interp, argv[2], &modePtr); if ( NULL == hChannel ) { - Tcl_AppendResult(interp, "unknown channel:", argv[2], NULL); + Tcl_AppendResult(interp, "unknown channel:", argv[2], (void *)NULL); return TCL_ERROR; } statePtr = (TcpState *)Tcl_GetChannelInstanceData(hChannel); if ( NULL == statePtr) { Tcl_AppendResult(interp, "No channel instance data:", argv[2], - NULL); + (void *)NULL); + return TCL_ERROR; + } + if (Tcl_GetBoolean(interp, argv[3], &testMode) != TCL_OK) { return TCL_ERROR; } - statePtr->testFlags = atoi(argv[3]); + if (testMode) { + statePtr->flags |= TCP_ASYNC_TEST_MODE; + } else { + statePtr->flags &= ~TCP_ASYNC_TEST_MODE; + } return TCL_OK; } Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be " - "testflags", NULL); + "testflags", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -6190,11 +6878,11 @@ const char **argv) /* Argument strings. */ { int newmode, oldmode; if (argc > 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ?newmode?\"", NULL); + " ?newmode?\"", (void *)NULL); return TCL_ERROR; } oldmode = (Tcl_GetServiceMode() != TCL_SERVICE_NONE); if (argc == 2) { if (Tcl_GetInt(interp, argv[1], &newmode) == TCL_ERROR) { @@ -6204,11 +6892,11 @@ Tcl_SetServiceMode(TCL_SERVICE_NONE); } else { Tcl_SetServiceMode(TCL_SERVICE_ALL); } } - Tcl_SetObjResult(interp, Tcl_NewIntObj(oldmode)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(oldmode)); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -6228,26 +6916,21 @@ static int TestWrongNumArgsObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int i, length; + Tcl_Size i, length; const char *msg; if (objc < 3) { - /* - * Don't use Tcl_WrongNumArgs here, as that is the function - * we want to test! - */ - Tcl_AppendResult(interp, "insufficient arguments", NULL); - return TCL_ERROR; + goto insufArgs; } - if (Tcl_GetIntFromObj(interp, objv[1], &i) != TCL_OK) { + if (Tcl_GetIntForIndex(interp, objv[1], TCL_INDEX_NONE, &i) != TCL_OK) { return TCL_ERROR; } msg = Tcl_GetStringFromObj(objv[2], &length); if (length == 0) { @@ -6256,11 +6939,12 @@ if (i > objc - 3) { /* * Asked for more arguments than were given. */ - Tcl_AppendResult(interp, "insufficient arguments", NULL); + insufArgs: + Tcl_AppendResult(interp, "insufficient arguments", (void *)NULL); return TCL_ERROR; } Tcl_WrongNumArgs(interp, i, &(objv[3]), msg); return TCL_OK; @@ -6288,35 +6972,43 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *const ary[] = { - "a", "b", "c", "d", "e", "f", NULL, NULL + "a", "b", "c", "d", "ee", "ff", NULL, NULL }; - int idx,target; - - 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) { + 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 (idx != target) { + 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", (void *)NULL); + return TCL_ERROR; + } else if (idx[1] != target) { char buffer[64]; - sprintf(buffer, "%d", idx); + snprintf(buffer, sizeof(buffer), "%d", idx[1]); Tcl_AppendResult(interp, "index value comparison failed: got ", - buffer, NULL); - sprintf(buffer, "%d", target); - Tcl_AppendResult(interp, " when ", buffer, " expected", NULL); + buffer, (void *)NULL); + snprintf(buffer, sizeof(buffer), "%d", target); + Tcl_AppendResult(interp, " when ", buffer, " expected", (void *)NULL); return TCL_ERROR; } - Tcl_WrongNumArgs(interp, 3, objv, NULL); + Tcl_WrongNumArgs(interp, objc, objv, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -6453,11 +7145,11 @@ } Tcl_DStringEndSublist(&ds); savedResult = Tcl_GetObjResult(interp); Tcl_IncrRefCount(savedResult); Tcl_SetObjResult(interp, Tcl_NewObj()); - Tcl_EvalEx(interp, Tcl_DStringValue(&ds), -1, 0); + Tcl_EvalEx(interp, Tcl_DStringValue(&ds), TCL_INDEX_NONE, 0); Tcl_DStringFree(&ds); Tcl_ResetResult(interp); Tcl_SetObjResult(interp, savedResult); Tcl_DecrRefCount(savedResult); } @@ -6742,11 +7434,11 @@ static Tcl_Obj * SimpleRedirect( Tcl_Obj *pathPtr) /* Name of file to copy. */ { - int len; + Tcl_Size len; const char *str; Tcl_Obj *origPtr; /* * We assume the same name in the current directory is ok. @@ -6756,11 +7448,11 @@ if (len < 10 || strncmp(str, "simplefs:/", 10)) { /* Probably shouldn't ever reach here */ Tcl_IncrRefCount(pathPtr); return pathPtr; } - origPtr = Tcl_NewStringObj(str+10,-1); + origPtr = Tcl_NewStringObj(str+10, -1); Tcl_IncrRefCount(origPtr); return origPtr; } static int @@ -6788,11 +7480,11 @@ resPtr = Tcl_NewObj(); Tcl_IncrRefCount(resPtr); origPtr = SimpleRedirect(dirPtr); res = Tcl_FSMatchInDirectory(interp, resPtr, origPtr, pattern, types); if (res == TCL_OK) { - int gLength, j; + Tcl_Size gLength, j; Tcl_ListObjLength(NULL, resPtr, &gLength); for (j = 0; j < gLength; j++) { Tcl_Obj *gElt, *nElt; Tcl_ListObjIndex(NULL, resPtr, j, &gElt); nElt = Tcl_NewStringObj("simplefs:/",10); @@ -6816,11 +7508,11 @@ { Tcl_Obj *tempPtr; Tcl_Channel chan; if ((mode != 0) && !(mode & O_RDONLY)) { - Tcl_AppendResult(interp, "read-only", NULL); + Tcl_AppendResult(interp, "read-only", (void *)NULL); return NULL; } tempPtr = SimpleRedirect(pathPtr); chan = Tcl_FSOpenFileChannel(interp, tempPtr, "r", permissions); @@ -6874,11 +7566,11 @@ TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - size_t numBytes; + Tcl_Size numBytes; char *bytes; const char *result, *first; char buffer[32]; static const char tobetested[] = "A\xA0\xC0\xC1\xC2\xD0\xE0\xE8\xF2\xF7\xF8\xFE\xFF"; const char *p = tobetested; @@ -6885,17 +7577,16 @@ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "?-bytestring? bytes"); return TCL_ERROR; } - bytes = Tcl_GetString(objv[1]); - numBytes = objv[1]->length; + bytes = Tcl_GetStringFromObj(objv[1], &numBytes); - if (numBytes > (int)sizeof(buffer) - 4) { + if ((size_t)numBytes > sizeof(buffer) - 4) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "\"testutfnext\" can only handle %d bytes", - (int)sizeof(buffer) - 4)); + "\"testutfnext\" can only handle %" TCL_Z_MODIFIER "u bytes", + sizeof(buffer) - 4)); return TCL_ERROR; } memcpy(buffer + 1, bytes, numBytes); buffer[0] = buffer[numBytes + 1] = buffer[numBytes + 2] = buffer[numBytes + 3] = '\xA0'; @@ -6903,25 +7594,27 @@ first = result = Tcl_UtfNext(buffer + 1); while ((buffer[0] = *p++) != '\0') { /* Run Tcl_UtfNext with many more possible bytes at src[-1], all should give the same result */ result = Tcl_UtfNext(buffer + 1); if (first != result) { - Tcl_AppendResult(interp, "Tcl_UtfNext is not supposed to read src[-1]", NULL); + Tcl_AppendResult(interp, "Tcl_UtfNext is not supposed to read src[-1]", (void *)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_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_NewIntObj(first - buffer - 1)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(first - buffer - 1)); return TCL_OK; } /* * Used to check operations of Tcl_UtfPrev. @@ -6934,21 +7627,20 @@ TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - size_t numBytes, offset; + Tcl_Size numBytes, offset; char *bytes; const char *result; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "bytes ?offset?"); return TCL_ERROR; } - bytes = Tcl_GetString(objv[1]); - numBytes = objv[1]->length; + bytes = Tcl_GetStringFromObj(objv[1], &numBytes); if (objc == 3) { if (TCL_OK != Tcl_GetIntForIndex(interp, objv[2], numBytes, &offset)) { return TCL_ERROR; } @@ -6959,11 +7651,11 @@ offset = numBytes; } } else { offset = numBytes; } - result = TclUtfPrev(bytes + offset, bytes); + result = Tcl_UtfPrev(bytes + offset, bytes); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(result - bytes)); return TCL_OK; } /* @@ -6976,13 +7668,12 @@ 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; + 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; } @@ -6991,10 +7682,38 @@ } } 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 @@ -7038,11 +7757,38 @@ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_UtfFindLast(Tcl_GetString(objv[1]), len), -1)); } return TCL_OK; } -#if defined(HAVE_CPUID) || defined(_WIN32) +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 -- * @@ -7087,11 +7833,11 @@ Tcl_SetObjResult(interp, Tcl_NewStringObj("operation not available", -1)); return status; } for (i=0 ; i<4 ; ++i) { - regsObjs[i] = Tcl_NewIntObj(regs[i]); + regsObjs[i] = Tcl_NewWideIntObj(regs[i]); } Tcl_SetObjResult(interp, Tcl_NewListObj(4, regsObjs)); return TCL_OK; } #endif @@ -7120,57 +7866,57 @@ } Tcl_InitCustomHashTable(&hash, TCL_CUSTOM_TYPE_KEYS, &hkType); if (hash.numEntries != 0) { - Tcl_AppendResult(interp, "non-zero initial size", NULL); + Tcl_AppendResult(interp, "non-zero initial size", (void *)NULL); Tcl_DeleteHashTable(&hash); return TCL_ERROR; } for (i=0 ; iexecEnvPtr->callbackPtr; if (refDepth == NULL) { - refDepth = &depth; + refDepth = (ptrdiff_t *)TclGetCStackPtr(); } - depth = (refDepth - &depth); + depth = (refDepth - (ptrdiff_t *)TclGetCStackPtr()); - levels[0] = Tcl_NewIntObj(depth); - levels[1] = Tcl_NewIntObj(iPtr->numLevels); - levels[2] = Tcl_NewIntObj(iPtr->cmdFramePtr->level); - levels[3] = Tcl_NewIntObj(iPtr->varFramePtr->level); - levels[4] = Tcl_NewIntObj(iPtr->execEnvPtr->execStackPtr->tosPtr + levels[0] = Tcl_NewWideIntObj(depth); + levels[1] = Tcl_NewWideIntObj(iPtr->numLevels); + levels[2] = Tcl_NewWideIntObj(iPtr->cmdFramePtr->level); + levels[3] = Tcl_NewWideIntObj(iPtr->varFramePtr->level); + levels[4] = Tcl_NewWideIntObj(iPtr->execEnvPtr->execStackPtr->tosPtr - iPtr->execEnvPtr->execStackPtr->stackWords); while (cbPtr) { i++; cbPtr = cbPtr->nextPtr; } - levels[5] = Tcl_NewIntObj(i); + levels[5] = Tcl_NewWideIntObj(i); Tcl_SetObjResult(interp, Tcl_NewListObj(6, levels)); return TCL_OK; } @@ -7305,11 +8051,11 @@ * * TestconcatobjCmd -- * * This procedure implements the "testconcatobj" command. It is used * to test that Tcl_ConcatObj does indeed return a fresh Tcl_Obj in all - * cases and thet it never corrupts its arguments. In other words, that + * cases and that it never corrupts its arguments. In other words, that * [Bug 1447328] was fixed properly. * * Results: * A standard Tcl result. * @@ -7325,11 +8071,12 @@ 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; + 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. @@ -7359,25 +8106,25 @@ objv[1] = emptyPtr; concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, - "\n\t* (a) concatObj does not have refCount 0", NULL); + "\n\t* (a) concatObj does not have refCount 0", (void *)NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (a) concatObj is not a new obj ", - NULL); + (void *)NULL); switch (tmpPtr->refCount) { case 0: - Tcl_AppendResult(interp, "(no new refCount)", NULL); + Tcl_AppendResult(interp, "(no new refCount)", (void *)NULL); break; case 1: - Tcl_AppendResult(interp, "(refCount added)", NULL); + Tcl_AppendResult(interp, "(refCount added)", (void *)NULL); break; default: - Tcl_AppendResult(interp, "(more than one refCount added!)", NULL); + Tcl_AppendResult(interp, "(more than one refCount added!)", (void *)NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[0] = tmpPtr; } @@ -7386,30 +8133,30 @@ Tcl_IncrRefCount(tmpPtr); concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, - "\n\t* (b) concatObj does not have refCount 0", NULL); + "\n\t* (b) concatObj does not have refCount 0", (void *)NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (b) concatObj is not a new obj ", - NULL); + (void *)NULL); switch (tmpPtr->refCount) { case 0: - Tcl_AppendResult(interp, "(refCount removed?)", NULL); + Tcl_AppendResult(interp, "(refCount removed?)", (void *)NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); break; case 1: - Tcl_AppendResult(interp, "(no new refCount)", NULL); + Tcl_AppendResult(interp, "(no new refCount)", (void *)NULL); break; case 2: - Tcl_AppendResult(interp, "(refCount added)", NULL); + Tcl_AppendResult(interp, "(refCount added)", (void *)NULL); Tcl_DecrRefCount(tmpPtr); break; default: - Tcl_AppendResult(interp, "(more than one refCount added!)", NULL); + Tcl_AppendResult(interp, "(more than one refCount added!)", (void *)NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[0] = tmpPtr; } @@ -7420,25 +8167,25 @@ objv[2] = emptyPtr; concatPtr = Tcl_ConcatObj(3, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, - "\n\t* (c) concatObj does not have refCount 0", NULL); + "\n\t* (c) concatObj does not have refCount 0", (void *)NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (c) concatObj is not a new obj ", - NULL); + (void *)NULL); switch (tmpPtr->refCount) { case 0: - Tcl_AppendResult(interp, "(no new refCount)", NULL); + Tcl_AppendResult(interp, "(no new refCount)", (void *)NULL); break; case 1: - Tcl_AppendResult(interp, "(refCount added)", NULL); + Tcl_AppendResult(interp, "(refCount added)", (void *)NULL); break; default: - Tcl_AppendResult(interp, "(more than one refCount added!)", NULL); + Tcl_AppendResult(interp, "(more than one refCount added!)", (void *)NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[1] = tmpPtr; } @@ -7447,30 +8194,30 @@ Tcl_IncrRefCount(tmpPtr); concatPtr = Tcl_ConcatObj(3, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, - "\n\t* (d) concatObj does not have refCount 0", NULL); + "\n\t* (d) concatObj does not have refCount 0", (void *)NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (d) concatObj is not a new obj ", - NULL); + (void *)NULL); switch (tmpPtr->refCount) { case 0: - Tcl_AppendResult(interp, "(refCount removed?)", NULL); + Tcl_AppendResult(interp, "(refCount removed?)", (void *)NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); break; case 1: - Tcl_AppendResult(interp, "(no new refCount)", NULL); + Tcl_AppendResult(interp, "(no new refCount)", (void *)NULL); break; case 2: - Tcl_AppendResult(interp, "(refCount added)", NULL); + Tcl_AppendResult(interp, "(refCount added)", (void *)NULL); Tcl_DecrRefCount(tmpPtr); break; default: - Tcl_AppendResult(interp, "(more than one refCount added!)", NULL); + Tcl_AppendResult(interp, "(more than one refCount added!)", (void *)NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[1] = tmpPtr; } @@ -7485,24 +8232,24 @@ objv[1] = list2Ptr; concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, - "\n\t* (e) concatObj does not have refCount 0", NULL); + "\n\t* (e) concatObj does not have refCount 0", (void *)NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (e) concatObj is not a new obj ", - NULL); + (void *)NULL); (void) Tcl_ListObjLength(NULL, concatPtr, &len); switch (tmpPtr->refCount) { case 3: - Tcl_AppendResult(interp, "(failed to concat)", NULL); + Tcl_AppendResult(interp, "(failed to concat)", (void *)NULL); break; default: - Tcl_AppendResult(interp, "(corrupted input!)", NULL); + Tcl_AppendResult(interp, "(corrupted input!)", (void *)NULL); } if (Tcl_IsShared(tmpPtr)) { Tcl_DecrRefCount(tmpPtr); } tmpPtr = Tcl_DuplicateObj(list1Ptr); @@ -7515,24 +8262,24 @@ Tcl_IncrRefCount(tmpPtr); concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, - "\n\t* (f) concatObj does not have refCount 0", NULL); + "\n\t* (f) concatObj does not have refCount 0", (void *)NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (f) concatObj is not a new obj ", - NULL); + (void *)NULL); (void) Tcl_ListObjLength(NULL, concatPtr, &len); switch (tmpPtr->refCount) { case 3: - Tcl_AppendResult(interp, "(failed to concat)", NULL); + Tcl_AppendResult(interp, "(failed to concat)", (void *)NULL); break; default: - Tcl_AppendResult(interp, "(corrupted input!)", NULL); + Tcl_AppendResult(interp, "(corrupted input!)", (void *)NULL); } if (Tcl_IsShared(tmpPtr)) { Tcl_DecrRefCount(tmpPtr); } tmpPtr = Tcl_DuplicateObj(list1Ptr); @@ -7546,24 +8293,24 @@ Tcl_IncrRefCount(tmpPtr); concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, - "\n\t* (g) concatObj does not have refCount 0", NULL); + "\n\t* (g) concatObj does not have refCount 0", (void *)NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (g) concatObj is not a new obj ", - NULL); + (void *)NULL); (void) Tcl_ListObjLength(NULL, concatPtr, &len); switch (tmpPtr->refCount) { case 3: - Tcl_AppendResult(interp, "(failed to concat)", NULL); + Tcl_AppendResult(interp, "(failed to concat)", (void *)NULL); break; default: - Tcl_AppendResult(interp, "(corrupted input!)", NULL); + Tcl_AppendResult(interp, "(corrupted input!)", (void *)NULL); } Tcl_DecrRefCount(tmpPtr); if (Tcl_IsShared(tmpPtr)) { Tcl_DecrRefCount(tmpPtr); } @@ -7682,11 +8429,11 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Arguments. */ { static int foo = 0; - int count = objc; + Tcl_Size 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 }; @@ -7693,12 +8440,12 @@ 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[0] = Tcl_NewWideIntObj(foo); + result[1] = Tcl_NewWideIntObj(count); result[2] = Tcl_NewListObj(count, remObjv); Tcl_SetObjResult(interp, Tcl_NewListObj(3, result)); Tcl_Free(remObjv); return TCL_OK; } @@ -7710,11 +8457,11 @@ static int InterpCmdResolver( Tcl_Interp *interp, const char *name, TCL_UNUSED(Tcl_Namespace *), - TCL_UNUSED(int) /*flags*/, + TCL_UNUSED(int) /* flags */, Tcl_Command *rPtr) { Interp *iPtr = (Interp *) interp; CallFrame *varFramePtr = iPtr->varFramePtr; Proc *procPtr = (varFramePtr->isProcCallFrame & FRAME_IS_PROC) ? @@ -7874,11 +8621,11 @@ HashVarFree(var); } hPtr = Tcl_CreateHashEntry((Tcl_HashTable *) &iPtr->globalNsPtr->varTable, - (char *) resVarInfo->nameObj, &isNewVar); + resVarInfo->nameObj, &isNewVar); if (hPtr) { var = (Tcl_Var) TclVarHashGetValue(hPtr); } else { var = NULL; } @@ -7895,11 +8642,11 @@ static int InterpCompiledVarResolver( TCL_UNUSED(Tcl_Interp *), const char *name, - TCL_UNUSED(int) /*length*/, + TCL_UNUSED(Tcl_Size) /* length */, TCL_UNUSED(Tcl_Namespace *), Tcl_ResolvedVarInfo **rPtr) { if (*name == 'T') { MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *)Tcl_Alloc(sizeof(MyResolvedVarInfo)); @@ -7933,11 +8680,11 @@ return TCL_ERROR; } if (objc == 3) { interp = Tcl_GetChild(interp, Tcl_GetString(objv[2])); if (interp == NULL) { - Tcl_AppendResult(interp, "provided interpreter not found", NULL); + Tcl_AppendResult(interp, "provided interpreter not found", (void *)NULL); return TCL_ERROR; } } if (Tcl_GetIndexFromObj(interp, objv[1], table, "operation", TCL_EXACT, &idx) != TCL_OK) { @@ -7949,21 +8696,195 @@ InterpVarResolver, InterpCompiledVarResolver); break; case 0: /*down*/ if (!Tcl_RemoveInterpResolvers(interp, RESOLVER_KEY)) { Tcl_AppendResult(interp, "could not remove the resolver scheme", - NULL); + (void *)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 Index: generic/tclTestABSList.c ================================================================== --- /dev/null +++ generic/tclTestABSList.c @@ -0,0 +1,1254 @@ +// Tcl Abstract List test command: "lstring" + +#ifndef USE_TCL_STUBS +# define USE_TCL_STUBS +#endif +#include +#include +#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; xstrlen && xstring = 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 (istrlen = 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; ilen; 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 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; +} Index: generic/tclTestObj.c ================================================================== --- generic/tclTestObj.c +++ generic/tclTestObj.c @@ -4,13 +4,13 @@ * This file contains C command functions for the additional Tcl commands * that are used for testing implementations of the Tcl object types. * These commands are not normally included in Tcl applications; they're * only used for testing. * - * Copyright (c) 1995-1998 Sun Microsystems, Inc. - * Copyright (c) 1999 by Scriptics Corporation. - * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. + * Copyright © 1995-1998 Sun Microsystems, Inc. + * Copyright © 1999 Scriptics Corporation. + * Copyright © 2005 Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -23,39 +23,40 @@ #else # include "tclTomMath.h" #endif #include "tclStringRep.h" +#include /* * Forward declarations for functions defined later in this file: */ -static int CheckIfVarUnset(Tcl_Interp *interp, Tcl_Obj **varPtr, int varIndex); +static int CheckIfVarUnset(Tcl_Interp *interp, Tcl_Obj **varPtr, Tcl_Size varIndex); static int GetVariableIndex(Tcl_Interp *interp, - const char *string, int *indexPtr); -static void SetVarToObj(Tcl_Obj **varPtr, int varIndex, Tcl_Obj *objPtr); + Tcl_Obj *obj, Tcl_Size *indexPtr); +static void SetVarToObj(Tcl_Obj **varPtr, Tcl_Size varIndex, Tcl_Obj *objPtr); static Tcl_ObjCmdProc TestbignumobjCmd; static Tcl_ObjCmdProc TestbooleanobjCmd; static Tcl_ObjCmdProc TestdoubleobjCmd; static Tcl_ObjCmdProc TestindexobjCmd; static Tcl_ObjCmdProc TestintobjCmd; static Tcl_ObjCmdProc TestlistobjCmd; static Tcl_ObjCmdProc TestobjCmd; static Tcl_ObjCmdProc TeststringobjCmd; +static Tcl_ObjCmdProc TestbigdataCmd; #define VARPTR_KEY "TCLOBJTEST_VARPTR" #define NUMBER_OF_OBJECT_VARS 20 -static void VarPtrDeleteProc(void *clientData, Tcl_Interp *interp) +static void VarPtrDeleteProc(void *clientData, TCL_UNUSED(Tcl_Interp *)) { int i; Tcl_Obj **varPtr = (Tcl_Obj **) clientData; for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { if (varPtr[i]) Tcl_DecrRefCount(varPtr[i]); } - Tcl_DeleteAssocData(interp, VARPTR_KEY); Tcl_Free(varPtr); } static Tcl_Obj **GetVarPtr(Tcl_Interp *interp) { @@ -116,10 +117,14 @@ 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; } /* *---------------------------------------------------------------------- @@ -150,31 +155,31 @@ "set", "get", "mult10", "div10", "iseven", "radixsize", NULL }; enum options { BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10, BIGNUM_ISEVEN, BIGNUM_RADIXSIZE - }; - int index, varIndex; + } idx; + int index; + Tcl_Size varIndex; const char *string; mp_int bignumValue; Tcl_Obj **varPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0, - &index) != TCL_OK) { + &idx) != TCL_OK) { return TCL_ERROR; } - string = Tcl_GetString(objv[2]); - if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) { + if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { return TCL_ERROR; } varPtr = GetVarPtr(interp); - switch (index) { + switch (idx) { case BIGNUM_SET: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "var value"); return TCL_ERROR; } @@ -283,13 +288,13 @@ Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_mod_2d", -1)); return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetIntObj(varPtr[varIndex], mp_iszero(&bignumValue)); + Tcl_SetBooleanObj(varPtr[varIndex], mp_iszero(&bignumValue)); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(mp_iszero(&bignumValue))); + SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(mp_iszero(&bignumValue))); } mp_clear(&bignumValue); break; case BIGNUM_RADIXSIZE: @@ -306,13 +311,13 @@ } if (mp_radix_size(&bignumValue, 10, &index) != MP_OKAY) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetIntObj(varPtr[varIndex], index); + Tcl_SetWideIntObj(varPtr[varIndex], index); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(index)); + SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(index)); } mp_clear(&bignumValue); break; } @@ -343,22 +348,22 @@ 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_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; } - index = Tcl_GetString(objv[2]); - if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { return TCL_ERROR; } varPtr = GetVarPtr(interp); @@ -378,13 +383,13 @@ * we must create a new object to modify/set and decrement the old * formerly-shared object's ref count. This is "copy on write". */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], boolValue != 0); + Tcl_SetBooleanObj(varPtr[varIndex], boolValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(boolValue != 0)); + SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(boolValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "get") == 0) { if (objc != 3) { goto wrongNumArgs; @@ -403,19 +408,19 @@ if (Tcl_GetBooleanFromObj(interp, varPtr[varIndex], &boolValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], boolValue == 0); + Tcl_SetBooleanObj(varPtr[varIndex], !boolValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(boolValue == 0)); + SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(!boolValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), - "\": must be set, get, or not", NULL); + "\": must be set, get, or not", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -443,13 +448,13 @@ TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int varIndex; + Tcl_Size varIndex; double doubleValue; - const char *index, *subCmd, *string; + const char *subCmd; Tcl_Obj **varPtr; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); @@ -456,22 +461,20 @@ return TCL_ERROR; } varPtr = GetVarPtr(interp); - index = Tcl_GetString(objv[2]); - if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { return TCL_ERROR; } subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { goto wrongNumArgs; } - string = Tcl_GetString(objv[3]); - if (Tcl_GetDouble(interp, string, &doubleValue) != TCL_OK) { + 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 @@ -530,11 +533,11 @@ } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), - "\": must be set, get, mult10, or div10", NULL); + "\": must be set, get, mult10, or div10", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -561,43 +564,43 @@ TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int allowAbbrev, index, index2, setError, i, result; + int allowAbbrev, index, setError, i, result; + Tcl_Size index2; const char **argv; static const char *const tablePtr[] = {"a", "b", "check", NULL}; /* * Keep this structure declaration in sync with tclIndexObj.c */ struct IndexRep { void *tablePtr; /* Pointer to the table of strings. */ - size_t offset; /* Offset between table entries. */ - size_t index; /* Selected index into table. */ - }; - struct IndexRep *indexRep; + 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_GetIntFromObj(interp, objv[2], &index2) != TCL_OK) { + if (Tcl_GetIntForIndex(interp, objv[2], TCL_INDEX_NONE, &index2) != TCL_OK) { return TCL_ERROR; } Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index); indexRep = (struct IndexRep *)objv[1]->internalRep.twoPtrValue.ptr1; indexRep->index = index2; result = Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index); if (result == TCL_OK) { - Tcl_SetIntObj(Tcl_GetObjResult(interp), index); + Tcl_SetWideIntObj(Tcl_GetObjResult(interp), index); } return result; } if (objc < 5) { @@ -621,11 +624,11 @@ result = Tcl_GetIndexFromObj((setError? interp : NULL), objv[3], argv, "token", TCL_INDEX_TEMP_TABLE|(allowAbbrev? 0 : TCL_EXACT), &index); Tcl_Free((void *)argv); if (result == TCL_OK) { - Tcl_SetIntObj(Tcl_GetObjResult(interp), index); + Tcl_SetWideIntObj(Tcl_GetObjResult(interp), index); } return result; } /* @@ -651,37 +654,37 @@ TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int intValue, varIndex, i; + Tcl_Size varIndex; +#if (INT_MAX != LONG_MAX) /* int is not the same size as long */ + int i; +#endif Tcl_WideInt wideValue; - const char *index, *subCmd, *string; + const char *subCmd; Tcl_Obj **varPtr; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } varPtr = GetVarPtr(interp); - index = Tcl_GetString(objv[2]); - if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { return TCL_ERROR; } subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { goto wrongNumArgs; } - string = Tcl_GetString(objv[3]); - if (Tcl_GetInt(interp, string, &i) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) { return TCL_ERROR; } - intValue = i; /* * If the object currently bound to the variable with index varIndex * has ref count 1 (i.e. the object is unshared) we can modify that * object directly. Otherwise, if RC>1 (i.e. the object is shared), we @@ -688,42 +691,38 @@ * must create a new object to modify/set and decrement the old * formerly-shared object's ref count. This is "copy on write". */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetIntObj(varPtr[varIndex], intValue); + Tcl_SetWideIntObj(varPtr[varIndex], wideValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue)); + SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "set2") == 0) { /* doesn't set result */ if (objc != 4) { goto wrongNumArgs; } - string = Tcl_GetString(objv[3]); - if (Tcl_GetInt(interp, string, &i) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) { return TCL_ERROR; } - intValue = i; if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetIntObj(varPtr[varIndex], intValue); + Tcl_SetWideIntObj(varPtr[varIndex], wideValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue)); + SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue)); } } else if (strcmp(subCmd, "setint") == 0) { if (objc != 4) { goto wrongNumArgs; } - string = Tcl_GetString(objv[3]); - if (Tcl_GetInt(interp, string, &i) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) { return TCL_ERROR; } - intValue = i; if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], intValue); + Tcl_SetWideIntObj(varPtr[varIndex], wideValue); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(intValue)); + SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "setmax") == 0) { Tcl_WideInt maxWide = WIDE_MAX; if (objc != 3) { @@ -759,12 +758,11 @@ goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } - string = Tcl_GetString(varPtr[varIndex]); - Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); + Tcl_AppendToObj(Tcl_GetObjResult(interp), Tcl_GetString(varPtr[varIndex]), -1); } else if (strcmp(subCmd, "inttoobigtest") == 0) { /* * If long ints have more bits than ints on this platform, verify that * Tcl_GetIntFromObj returns an error if the long int held in an * integer object's internal representation is too large to fit in an @@ -794,41 +792,41 @@ goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } - if (Tcl_GetIntFromObj(interp, varPtr[varIndex], - &intValue) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, varPtr[varIndex], + &wideValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetIntObj(varPtr[varIndex], intValue * 10); + Tcl_SetWideIntObj(varPtr[varIndex], wideValue * 10); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue * 10)); + SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue * 10)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "div10") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } - if (Tcl_GetIntFromObj(interp, varPtr[varIndex], - &intValue) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, varPtr[varIndex], + &wideValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetIntObj(varPtr[varIndex], intValue / 10); + Tcl_SetWideIntObj(varPtr[varIndex], wideValue / 10); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue / 10)); + SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue / 10)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), - "\": must be set, get, get2, mult10, or div10", NULL); + "\": must be set, get, get2, mult10, or div10", (void *)NULL); return TCL_ERROR; } return TCL_OK; } @@ -838,10 +836,39 @@ * 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 + * testobj set VARINDEX [list a b c] (or lseq etc.) + * testlistobj indexnoop VARINDEX + * testobj unset VARINDEX + * set after + * 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: @@ -856,35 +883,40 @@ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Number of arguments */ Tcl_Obj *const objv[]) /* Argument objects */ { /* Subcommands supported by this command */ - const char* subcommands[] = { + const char* const subcommands[] = { "set", "get", - "replace" + "replace", + "indexmemcheck", + "getelementsmemcheck", + "index", + NULL }; 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 */ + 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); - index = Tcl_GetString(objv[2]); - if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "command", 0, &cmdIndex) != TCL_OK) { return TCL_ERROR; @@ -914,20 +946,91 @@ 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) { + 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; } /* @@ -944,175 +1047,230 @@ * Side effects: * Creates and frees objects. * *---------------------------------------------------------------------- */ + +static Tcl_Size V1TestListObjLength(TCL_UNUSED(Tcl_Obj *)) { + return 100; +} + +static int V1TestListObjIndex( + TCL_UNUSED(Tcl_Interp *), + TCL_UNUSED(Tcl_Obj *), + TCL_UNUSED(Tcl_Size), + Tcl_Obj **objPtr) +{ + *objPtr = Tcl_NewStringObj("This indexProc should never be accessed (bug: e58d7e19e9)", -1); + return TCL_OK; +} + +static const Tcl_ObjType v1TestListType = { + "testlist", /* name */ + NULL, /* freeIntRepProc */ + NULL, /* dupIntRepProc */ + NULL, /* updateStringProc */ + NULL, /* setFromAnyProc */ + offsetof(Tcl_ObjType, indexProc), /* This is a V1 objType, which doesn't have an indexProc */ + V1TestListObjLength, /* always return 100, doesn't really matter */ + V1TestListObjIndex, /* should never be accessed, because this objType = V1*/ + NULL, NULL, NULL, NULL, NULL, NULL +}; + static int TestobjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int varIndex, destIndex, i; - const char *index, *subCmd, *string; + Tcl_Size varIndex, destIndex; + int i; const Tcl_ObjType *targetType; Tcl_Obj **varPtr; + const char *subcommands[] = { + "freeallvars", "bug3598580", "buge58d7e19e9", + "types", "objtype", "newobj", "set", + "assign", "convert", "duplicate", + "invalidateStringRep", "refcount", "type", + NULL + }; + enum testobjCmdIndex { + TESTOBJ_FREEALLVARS, TESTOBJ_BUG3598580, TESTOBJ_BUGE58D7E19E9, + TESTOBJ_TYPES, TESTOBJ_OBJTYPE, TESTOBJ_NEWOBJ, TESTOBJ_SET, + TESTOBJ_ASSIGN, TESTOBJ_CONVERT, TESTOBJ_DUPLICATE, + TESTOBJ_INVALIDATESTRINGREP, TESTOBJ_REFCOUNT, TESTOBJ_TYPE, + } cmdIndex; if (objc < 2) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } varPtr = GetVarPtr(interp); - subCmd = Tcl_GetString(objv[1]); - if (strcmp(subCmd, "assign") == 0) { - if (objc != 4) { - goto wrongNumArgs; - } - index = Tcl_GetString(objv[2]); - if (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 (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; } } - } 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 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; - } - 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; + } 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")) { @@ -1121,25 +1279,15 @@ #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; - } + break; + default: + break; + } + return TCL_OK; } /* *---------------------------------------------------------------------- @@ -1165,30 +1313,31 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_UniChar *unicode; - int varIndex, option, i, length; + Tcl_Size size, varIndex; + int option, i; + Tcl_Size length; #define MAX_STRINGS 11 - const char *index, *string, *strings[MAX_STRINGS+1]; + const char *string, *strings[MAX_STRINGS+1]; String *strPtr; Tcl_Obj **varPtr; static const char *const options[] = { "append", "appendstrings", "get", "get2", "length", "length2", - "set", "set2", "setlength", "maxchars", "appendself", - "appendself2", NULL + "set", "set2", "setlength", "maxchars", "range", "appendself", + "appendself2", "newunicode", NULL }; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } varPtr = GetVarPtr(interp); - index = Tcl_GetString(objv[2]); - if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { + if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &option) != TCL_OK) { @@ -1197,11 +1346,11 @@ switch (option) { case 0: /* append */ if (objc != 5) { goto wrongNumArgs; } - if (Tcl_GetIntFromObj(interp, objv[4], &length) != TCL_OK) { + if (Tcl_GetIntForIndex(interp, objv[4], TCL_INDEX_NONE, &length) != TCL_OK) { return TCL_ERROR; } if (varPtr[varIndex] == NULL) { SetVarToObj(varPtr, varIndex, Tcl_NewObj()); } @@ -1212,12 +1361,11 @@ */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } - string = Tcl_GetString(objv[3]); - Tcl_AppendToObj(varPtr[varIndex], string, length); + Tcl_AppendToObj(varPtr[varIndex], Tcl_GetString(objv[3]), length); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 1: /* appendstrings */ if (objc > (MAX_STRINGS+3)) { goto wrongNumArgs; @@ -1241,11 +1389,11 @@ strings[i - 3] = NULL; } Tcl_AppendStringsToObj(varPtr[varIndex], strings[0], strings[1], strings[2], strings[3], strings[4], strings[5], strings[6], strings[7], strings[8], strings[9], - strings[10], strings[11]); + strings[10], strings[11], (void *)NULL); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 2: /* get */ if (objc != 3) { goto wrongNumArgs; @@ -1260,12 +1408,11 @@ goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr, varIndex)) { return TCL_ERROR; } - string = Tcl_GetString(varPtr[varIndex]); - Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); + Tcl_AppendToObj(Tcl_GetObjResult(interp), Tcl_GetString(varPtr[varIndex]), -1); break; case 4: /* length */ if (objc != 3) { goto wrongNumArgs; } @@ -1278,15 +1425,15 @@ } if (varPtr[varIndex] != NULL) { Tcl_ConvertToType(NULL, varPtr[varIndex], Tcl_GetObjType("string")); strPtr = (String *)varPtr[varIndex]->internalRep.twoPtrValue.ptr1; - length = (int) strPtr->allocated; + length = strPtr->allocated; } else { - length = -1; + length = TCL_INDEX_NONE; } - Tcl_SetIntObj(Tcl_GetObjResult(interp), length); + Tcl_SetWideIntObj(Tcl_GetObjResult(interp), (Tcl_WideInt)((Tcl_WideUInt)(length + 1U)) - 1); break; case 6: /* set */ if (objc != 4) { goto wrongNumArgs; } @@ -1298,16 +1445,16 @@ * object is shared), we must create a new object to modify/set * and decrement the old formerly-shared object's ref count. This * is "copy on write". */ - string = Tcl_GetStringFromObj(objv[3], &length); + string = Tcl_GetStringFromObj(objv[3], &size); if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetStringObj(varPtr[varIndex], string, length); + Tcl_SetStringObj(varPtr[varIndex], string, size); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewStringObj(string, length)); + SetVarToObj(varPtr, varIndex, Tcl_NewStringObj(string, size)); } Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 7: /* set2 */ if (objc != 4) { @@ -1317,11 +1464,11 @@ break; case 8: /* setlength */ if (objc != 4) { goto wrongNumArgs; } - if (Tcl_GetIntFromObj(interp, objv[3], &length) != TCL_OK) { + if (Tcl_GetIntForIndex(interp, objv[3], TCL_INDEX_NONE, &length) != TCL_OK) { return TCL_ERROR; } if (varPtr[varIndex] != NULL) { Tcl_SetObjLength(varPtr[varIndex], length); } @@ -1334,15 +1481,27 @@ Tcl_ConvertToType(NULL, varPtr[varIndex], Tcl_GetObjType("string")); strPtr = (String *)varPtr[varIndex]->internalRep.twoPtrValue.ptr1; length = strPtr->maxChars; } else { - length = -1; + length = TCL_INDEX_NONE; + } + Tcl_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_SetIntObj(Tcl_GetObjResult(interp), length); + Tcl_SetObjResult(interp, Tcl_GetRange(varPtr[varIndex], first, last)); break; - case 10: /* appendself */ + } + case 11: /* appendself */ if (objc != 4) { goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { SetVarToObj(varPtr, varIndex, Tcl_NewObj()); @@ -1355,25 +1514,25 @@ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } - string = Tcl_GetStringFromObj(varPtr[varIndex], &length); + string = Tcl_GetStringFromObj(varPtr[varIndex], &size); - if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { + if (Tcl_GetIntForIndex(interp, objv[3], size-1, &length) != TCL_OK) { return TCL_ERROR; } - if ((i < 0) || (i > length)) { + if (length == TCL_INDEX_NONE) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "index value out of range", -1)); return TCL_ERROR; } - Tcl_AppendToObj(varPtr[varIndex], string + i, length - i); + Tcl_AppendToObj(varPtr[varIndex], string + length, size - length); Tcl_SetObjResult(interp, varPtr[varIndex]); break; - case 11: /* appendself2 */ + case 12: /* appendself2 */ if (objc != 4) { goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { SetVarToObj(varPtr, varIndex, Tcl_NewObj()); @@ -1386,29 +1545,184 @@ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } - unicode = Tcl_GetUnicodeFromObj(varPtr[varIndex], &length); + unicode = Tcl_GetUnicodeFromObj(varPtr[varIndex], &size); - if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { + if (Tcl_GetIntForIndex(interp, objv[3], size-1, &length) != TCL_OK) { return TCL_ERROR; } - if ((i < 0) || (i > length)) { + if (length == TCL_INDEX_NONE) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "index value out of range", -1)); return TCL_ERROR; } - TclAppendUnicodeToObj(varPtr[varIndex], unicode + i, length - i); + Tcl_AppendUnicodeToObj(varPtr[varIndex], unicode + length, size - length); + Tcl_SetObjResult(interp, varPtr[varIndex]); + break; + case 13: /* newunicode*/ + unicode = (Tcl_UniChar *)Tcl_Alloc((objc - 3) * sizeof(Tcl_UniChar)); + for (i = 0; i < (objc - 3); ++i) { + int val; + if (Tcl_GetIntFromObj(interp, objv[i + 3], &val) != TCL_OK) { + break; + } + unicode[i] = (Tcl_UniChar)val; + } + if (i < (objc-3)) { + Tcl_Free(unicode); + return TCL_ERROR; + } + SetVarToObj(varPtr, varIndex, Tcl_NewUnicodeObj(unicode, objc - 3)); Tcl_SetObjResult(interp, varPtr[varIndex]); + Tcl_Free(unicode); break; } return TCL_OK; } +/* + *------------------------------------------------------------------------ + * + * TestbigdataCmd -- + * + * Implements the Tcl command testbigdata + * testbigdata string ?LEN? ?SPLIT? - returns 01234567890123... + * testbigdata bytearray ?LEN? ?SPLIT? - returns {0 1 2 3 4 5 6 7 8 9 0 1 ...} + * testbigdata dict ?SIZE? - returns dict mapping integers to themselves + * If no arguments given, returns the pattern used to generate strings. + * If SPLIT is specified, the character at that position is set to "X". + * + * Results: + * TCL_OK - Success. + * TCL_ERROR - Error. + * + * Side effects: + * Interpreter result holds result or error message. + * + *------------------------------------------------------------------------ + */ +static int +TestbigdataCmd ( + TCL_UNUSED(void *), + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + static const char *const subcmds[] = { + "string", "bytearray", "list", "dict", NULL + }; + enum options { + BIGDATA_STRING, BIGDATA_BYTEARRAY, BIGDATA_LIST, BIGDATA_DICT + } idx; + char *s; + unsigned char *p; + Tcl_WideInt 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_GetWideIntFromObj(interp, objv[2], &len) != TCL_OK) { + return TCL_ERROR; + } + if (objc == 4) { + if (Tcl_GetWideIntFromObj(interp, objv[3], &split) != TCL_OK) { + return TCL_ERROR; + } + if (split >= len) { + split = len - 1; /* Last position */ + } + } + } + /* Need one byte for nul terminator */ + Tcl_WideInt limit = + sizeof(Tcl_Size) == sizeof(Tcl_WideInt) ? WIDE_MAX-1 : INT_MAX-1; + if (len < 0 || len > limit) { + Tcl_SetObjResult( + interp, + Tcl_ObjPrintf( + "%s is greater than max permitted length %" TCL_LL_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 -- * @@ -1427,11 +1741,11 @@ */ static void SetVarToObj( Tcl_Obj **varPtr, - int varIndex, /* Designates the assignment variable. */ + Tcl_Size varIndex, /* Designates the assignment variable. */ Tcl_Obj *objPtr) /* Points to object to assign to var. */ { if (varPtr[varIndex] != NULL) { Tcl_DecrRefCount(varPtr[varIndex]); } @@ -1458,21 +1772,21 @@ */ static int GetVariableIndex( Tcl_Interp *interp, /* Interpreter for error reporting. */ - const char *string, /* String containing a variable index + Tcl_Obj *obj, /* The variable index * specified as a nonnegative number less than * NUMBER_OF_OBJECT_VARS. */ - int *indexPtr) /* Place to store converted result. */ + Tcl_Size *indexPtr) /* Place to store converted result. */ { - int index; + Tcl_Size index; - if (Tcl_GetInt(interp, string, &index) != TCL_OK) { + if (Tcl_GetIntForIndex(interp, obj, NUMBER_OF_OBJECT_VARS - 1, &index) != TCL_OK) { return TCL_ERROR; } - if (index < 0 || index >= NUMBER_OF_OBJECT_VARS) { + if (index == TCL_INDEX_NONE) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "bad variable index", -1); return TCL_ERROR; } @@ -1500,16 +1814,16 @@ static int CheckIfVarUnset( Tcl_Interp *interp, /* Interpreter for error reporting. */ Tcl_Obj ** varPtr, - int varIndex) /* Index of the test variable to check. */ + Tcl_Size varIndex) /* Index of the test variable to check. */ { - if (varPtr[varIndex] == NULL) { + if (varIndex < 0 || varPtr[varIndex] == NULL) { char buf[32 + TCL_INTEGER_SPACE]; - sprintf(buf, "variable %d is unset (NULL)", varIndex); + snprintf(buf, sizeof(buf), "variable %" TCL_SIZE_MODIFIER "d is unset (NULL)", varIndex); Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); return 1; } return 0; Index: generic/tclTestProcBodyObj.c ================================================================== --- generic/tclTestProcBodyObj.c +++ generic/tclTestProcBodyObj.c @@ -3,11 +3,11 @@ * * Implements the "procbodytest" package, which contains commands to test * creation of Tcl procedures whose body argument is a Tcl_Obj of type * "procbody" rather than a string. * - * Copyright (c) 1998 by Scriptics Corporation. + * Copyright © 1998 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -18,11 +18,11 @@ /* * name and version of this package */ -static const char packageName[] = "procbodytest"; +static const char packageName[] = "tcl::procbodytest"; static const char packageVersion[] = "1.1"; /* * Name of the commands exported by this package */ @@ -43,14 +43,12 @@ /* * 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 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); /* @@ -73,11 +71,11 @@ /* *---------------------------------------------------------------------- * * Procbodytest_Init -- * - * This function initializes the "procbodytest" package. + * This function initializes the "tcl::procbodytest" package. * * Results: * A standard Tcl result. * * Side effects: @@ -97,11 +95,11 @@ /* *---------------------------------------------------------------------- * * Procbodytest_SafeInit -- * - * This function initializes the "procbodytest" package. + * This function initializes the "tcl::procbodytest" package. * * Results: * A standard Tcl result. * * Side effects: @@ -144,18 +142,18 @@ const CmdTable *cmdTablePtr)/* the command to register */ { char buf[128]; if (cmdTablePtr->exportIt) { - sprintf(buf, "namespace eval %s { namespace export %s }", + snprintf(buf, sizeof(buf), "namespace eval %s { namespace export %s }", namesp, cmdTablePtr->cmdName); - if (Tcl_EvalEx(interp, buf, -1, 0) != TCL_OK) { + if (Tcl_EvalEx(interp, buf, TCL_INDEX_NONE, 0) != TCL_OK) { return TCL_ERROR; } } - sprintf(buf, "%s::%s", namesp, cmdTablePtr->cmdName); + snprintf(buf, sizeof(buf), "%s::%s", namesp, cmdTablePtr->cmdName); Tcl_CreateObjCommand(interp, buf, cmdTablePtr->proc, 0, 0); return TCL_OK; } /* @@ -263,11 +261,11 @@ * If a procedure, cmdPtr->objClientData is TclIsProc(cmdPtr). */ if (cmdPtr->objClientData != TclIsProc(cmdPtr)) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "command \"", fullName, "\" is not a Tcl procedure", NULL); + "command \"", fullName, "\" is not a Tcl procedure", (void *)NULL); return TCL_ERROR; } /* * it is a Tcl procedure: the client data is the Proc structure @@ -274,11 +272,11 @@ */ procPtr = (Proc *) cmdPtr->objClientData; if (procPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "procedure \"", - fullName, "\" does not have a Proc struct!", NULL); + fullName, "\" does not have a Proc struct!", (void *)NULL); return TCL_ERROR; } /* * create a new object, initialize our argument vector, call into Tcl @@ -286,11 +284,11 @@ bodyObjPtr = TclNewProcBodyObj(procPtr); if (bodyObjPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "failed to create a procbody object for procedure \"", - fullName, "\"", NULL); + fullName, "\"", (void *)NULL); return TCL_ERROR; } Tcl_IncrRefCount(bodyObjPtr); myobjv[0] = objv[0]; @@ -313,11 +311,11 @@ * Implements the "procbodytest::check" command. Here is the command * description: * procbodytest::check * * Performs an internal check that the Tcl_PkgPresent() command returns - * the same version number as was registered when the procbodytest package + * the same version number as was registered when the tcl::procbodytest package * was provided. Places a boolean in the interp result indicating the * test outcome. * * Results: * Returns a standard Tcl code. @@ -338,11 +336,11 @@ Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; } version = Tcl_PkgPresentEx(interp, packageName, packageVersion, 1, NULL); - Tcl_SetObjResult(interp, Tcl_NewWideIntObj( + Tcl_SetObjResult(interp, Tcl_NewBooleanObj( strcmp(version, packageVersion) == 0)); return TCL_OK; } /* Index: generic/tclThread.c ================================================================== --- generic/tclThread.c +++ generic/tclThread.c @@ -2,12 +2,12 @@ * tclThread.c -- * * This file implements Platform independent thread operations. Most of * the real work is done in the platform dependent files. * - * Copyright (c) 1998 by Sun Microsystems, Inc. - * Copyright (c) 2008 by George Peter Staplin + * Copyright © 1998 Sun Microsystems, Inc. + * Copyright © 2008 George Peter Staplin * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -59,11 +59,11 @@ */ void * Tcl_GetThreadData( Tcl_ThreadDataKey *keyPtr, /* Identifier for the data chunk */ - size_t size) /* Size of storage block */ + Tcl_Size size) /* Size of storage block */ { void *result; #if TCL_THREADS /* * Initialize the key for this thread. @@ -78,11 +78,11 @@ } #else /* TCL_THREADS */ if (*keyPtr == NULL) { result = Tcl_Alloc(size); memset(result, 0, size); - *keyPtr = result; + *keyPtr = (Tcl_ThreadDataKey)result; RememberSyncObject(keyPtr, &keyRecord); } else { result = *keyPtr; } #endif /* TCL_THREADS */ @@ -486,34 +486,34 @@ */ #undef Tcl_ConditionWait void Tcl_ConditionWait( - Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */ - Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */ - const Tcl_Time *timePtr) /* Timeout on waiting period */ + TCL_UNUSED(Tcl_Condition *), /* Really (pthread_cond_t **) */ + TCL_UNUSED(Tcl_Mutex *), /* Really (pthread_mutex_t **) */ + TCL_UNUSED(const Tcl_Time *)) /* Timeout on waiting period */ { } #undef Tcl_ConditionNotify void Tcl_ConditionNotify( - Tcl_Condition *condPtr) + TCL_UNUSED(Tcl_Condition *)) { } #undef Tcl_MutexLock void Tcl_MutexLock( - Tcl_Mutex *mutexPtr) + TCL_UNUSED(Tcl_Mutex *)) { } #undef Tcl_MutexUnlock void Tcl_MutexUnlock( - Tcl_Mutex *mutexPtr) + TCL_UNUSED(Tcl_Mutex *)) { } #endif /* !TCL_THREADS */ /* Index: generic/tclThreadAlloc.c ================================================================== --- generic/tclThreadAlloc.c +++ generic/tclThreadAlloc.c @@ -4,11 +4,11 @@ * This is a very fast storage allocator for used with threads (designed * avoid lock contention). The basic strategy is to allocate memory in * fixed size blocks from block caches. * * The Initial Developer of the Original Code is America Online, Inc. - * Portions created by AOL are Copyright (C) 1999 America Online, Inc. + * Portions created by AOL are Copyright © 1999 America Online, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -89,13 +89,12 @@ /* All fields below for accounting only */ size_t numRemoves; /* Number of removes from bucket */ size_t numInserts; /* Number of inserts into bucket */ - size_t numWaits; /* Number of waits to acquire a lock */ size_t numLocks; /* Number of locks acquired */ - size_t totalAssigned; /* Total space assigned to bucket */ + size_t totalAssigned; /* Total space assigned to bucket */ } Bucket; /* * The following structure defines a cache of buckets and objs, of which there * will be (at most) one per thread. Any changes need to be reflected in the @@ -105,13 +104,13 @@ typedef struct Cache { struct Cache *nextPtr; /* Linked list of cache entries */ Tcl_ThreadId owner; /* Which thread's cache is this? */ Tcl_Obj *firstObjPtr; /* List of free objects for thread */ - int numObjects; /* Number of objects for thread */ + size_t numObjects; /* Number of objects for thread */ Tcl_Obj *lastPtr; /* Last object in this cache */ - int totalAssigned; /* Total space assigned to thread */ + size_t totalAssigned; /* Total space assigned to thread */ Bucket buckets[NBUCKETS]; /* The buckets for this thread */ } Cache; /* * The following array specifies various per-bucket limits and locks. The @@ -130,16 +129,16 @@ */ static Cache * GetCache(void); static void LockBucket(Cache *cachePtr, int bucket); static void UnlockBucket(Cache *cachePtr, int bucket); -static void PutBlocks(Cache *cachePtr, int bucket, int numMove); +static void PutBlocks(Cache *cachePtr, int bucket, size_t numMove); static int GetBlocks(Cache *cachePtr, int bucket); static Block * Ptr2Block(void *ptr); -static void * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize); -static void MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove); -static void PutObjs(Cache *fromPtr, int numMove); +static void * Block2Ptr(Block *blockPtr, int bucket, size_t reqSize); +static void MoveObjs(Cache *fromPtr, Cache *toPtr, size_t numMove); +static void PutObjs(Cache *fromPtr, size_t numMove); /* * Local variables defined in this file and initialized at startup. */ @@ -520,11 +519,11 @@ * Get this thread's obj list structure and move or allocate new objs if * necessary. */ if (cachePtr->numObjects == 0) { - int numMove; + size_t numMove; Tcl_MutexLock(objLockPtr); numMove = sharedPtr->numObjects; if (numMove > 0) { if (numMove > NOBJALLOC) { @@ -537,15 +536,15 @@ Tcl_Obj *newObjsPtr; cachePtr->numObjects = numMove = NOBJALLOC; newObjsPtr = (Tcl_Obj *)TclpSysAlloc(sizeof(Tcl_Obj) * numMove); if (newObjsPtr == NULL) { - Tcl_Panic("alloc: could not allocate %d new objects", numMove); + Tcl_Panic("alloc: could not allocate %" TCL_Z_MODIFIER "u new objects", numMove); } cachePtr->lastPtr = newObjsPtr + numMove - 1; objPtr = cachePtr->firstObjPtr; /* NULL */ - while (--numMove >= 0) { + while (numMove-- > 0) { newObjsPtr[numMove].internalRep.twoPtrValue.ptr1 = objPtr; objPtr = newObjsPtr + numMove; } cachePtr->firstObjPtr = newObjsPtr; } @@ -639,22 +638,22 @@ while (cachePtr != NULL) { Tcl_DStringStartSublist(dsPtr); if (cachePtr == sharedPtr) { Tcl_DStringAppendElement(dsPtr, "shared"); } else { - sprintf(buf, "thread%p", cachePtr->owner); + snprintf(buf, sizeof(buf), "thread%p", cachePtr->owner); Tcl_DStringAppendElement(dsPtr, buf); } for (n = 0; n < NBUCKETS; ++n) { - 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", + 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, - cachePtr->buckets[n].numWaits); + cachePtr->buckets[n].numLocks); Tcl_DStringAppendElement(dsPtr, buf); } Tcl_DStringEndSublist(dsPtr); cachePtr = cachePtr->nextPtr; } @@ -679,11 +678,11 @@ static void MoveObjs( Cache *fromPtr, Cache *toPtr, - int numMove) + size_t numMove) { Tcl_Obj *objPtr = fromPtr->firstObjPtr; Tcl_Obj *fromFirstObjPtr = objPtr; toPtr->numObjects += numMove; @@ -692,11 +691,11 @@ /* * Find the last object to be moved; set the next one (the first one not * to be moved) as the first object in the 'from' cache. */ - while (--numMove) { + while (numMove-- > 1) { objPtr = (Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr1; } fromPtr->firstObjPtr = (Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr1; /* @@ -726,13 +725,13 @@ */ static void PutObjs( Cache *fromPtr, - int numMove) + size_t numMove) { - int keep = fromPtr->numObjects - numMove; + size_t keep = fromPtr->numObjects - numMove; Tcl_Obj *firstPtr, *lastPtr = NULL; fromPtr->numObjects = keep; firstPtr = fromPtr->firstObjPtr; if (keep == 0) { @@ -739,11 +738,11 @@ fromPtr->firstObjPtr = NULL; } else { do { lastPtr = firstPtr; firstPtr = (Tcl_Obj *)firstPtr->internalRep.twoPtrValue.ptr1; - } while (--keep > 0); + } while (keep-- > 1); lastPtr->internalRep.twoPtrValue.ptr1 = NULL; } /* * Move all objects as a block - they are already linked to each other, we @@ -780,11 +779,11 @@ static void * Block2Ptr( Block *blockPtr, int bucket, - unsigned int reqSize) + size_t reqSize) { void *ptr; blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC; blockPtr->sourceBucket = bucket; @@ -870,18 +869,18 @@ static void PutBlocks( Cache *cachePtr, int bucket, - int numMove) + size_t numMove) { /* * We have numFree. Want to shed numMove. So compute how many * Blocks to keep. */ - int keep = cachePtr->buckets[bucket].numFree - numMove; + size_t keep = cachePtr->buckets[bucket].numFree - numMove; Block *lastPtr = NULL, *firstPtr; cachePtr->buckets[bucket].numFree = keep; firstPtr = cachePtr->buckets[bucket].firstPtr; if (keep == 0) { @@ -888,11 +887,11 @@ cachePtr->buckets[bucket].firstPtr = NULL; } else { do { lastPtr = firstPtr; firstPtr = firstPtr->nextBlock; - } while (--keep > 0); + } while (keep-- > 1); lastPtr->nextBlock = NULL; } /* * Aquire the lock and place the list of blocks at the front of the shared @@ -936,11 +935,11 @@ { Block *blockPtr; size_t n; /* - * First, atttempt to move blocks from the shared cache. Note the + * First, attempt to move blocks from the shared cache. Note the * potentially dirty read of numFree before acquiring the lock which is a * slight performance enhancement. The value is verified after the lock is * actually acquired. */ @@ -966,11 +965,11 @@ } else { blockPtr = sharedPtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; sharedPtr->buckets[bucket].numFree -= n; cachePtr->buckets[bucket].numFree = n; - while (--n > 0) { + while (n-- > 1) { blockPtr = blockPtr->nextBlock; } sharedPtr->buckets[bucket].firstPtr = blockPtr->nextBlock; cachePtr->buckets[bucket].lastPtr = blockPtr; blockPtr->nextBlock = NULL; @@ -988,11 +987,11 @@ */ blockPtr = NULL; n = NBUCKETS; size = 0; - while (--n > (size_t)bucket) { + while (n-- > (size_t)bucket + 1) { if (cachePtr->buckets[n].numFree > 0) { size = bucketInfo[n].blockSize; blockPtr = cachePtr->buckets[n].firstPtr; cachePtr->buckets[n].firstPtr = blockPtr->nextBlock; cachePtr->buckets[n].numFree--; @@ -1017,11 +1016,11 @@ */ n = size / bucketInfo[bucket].blockSize; cachePtr->buckets[bucket].numFree = n; cachePtr->buckets[bucket].firstPtr = blockPtr; - while (--n > 0) { + while (n-- > 1) { blockPtr->nextBlock = (Block *) ((char *) blockPtr + bucketInfo[bucket].blockSize); blockPtr = blockPtr->nextBlock; } cachePtr->buckets[bucket].lastPtr = blockPtr; @@ -1056,11 +1055,11 @@ objLockPtr = TclpNewAllocMutex(); for (i = 0; i < NBUCKETS; ++i) { bucketInfo[i].blockSize = MINALLOC << i; bucketInfo[i].maxBlocks = ((size_t)1) << (NBUCKETS - 1 - i); bucketInfo[i].numMove = i < NBUCKETS - 1 ? - 1 << (NBUCKETS - 2 - i) : 1; + (size_t)1 << (NBUCKETS - 2 - i) : 1; bucketInfo[i].lockPtr = TclpNewAllocMutex(); } TclpInitAllocCache(); } Index: generic/tclThreadJoin.c ================================================================== --- generic/tclThreadJoin.c +++ generic/tclThreadJoin.c @@ -4,11 +4,11 @@ * This file implements a platform independent emulation layer for the * handling of joinable threads. The Windows platform uses this code to * provide the functionality of joining threads. This code is currently * not necessary on Unix. * - * Copyright (c) 2000 by Scriptics Corporation + * Copyright © 2000 Scriptics Corporation * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -209,12 +209,12 @@ /* *---------------------------------------------------------------------- * * TclRememberJoinableThread -- * - * This procedure remebers a thread as joinable. Only a call to - * TclJoinThread will remove the structre created (and initialized) here. + * This procedure remembers a thread as joinable. Only a call to + * TclJoinThread will remove the structure created (and initialized) here. * IOW, not waiting upon a joinable thread will cause memory leaks. * * Results: * None. * @@ -303,14 +303,16 @@ 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: */ Index: generic/tclThreadStorage.c ================================================================== --- generic/tclThreadStorage.c +++ generic/tclThreadStorage.c @@ -2,12 +2,12 @@ * tclThreadStorage.c -- * * This file implements platform independent thread storage operations to * work around system limits on the number of thread-specific variables. * - * Copyright (c) 2003-2004 by Joe Mistachkin - * Copyright (c) 2008 by George Peter Staplin + * Copyright © 2003-2004 Joe Mistachkin + * Copyright © 2008 George Peter Staplin * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -46,11 +46,11 @@ /* * The type of the data held per thread in a system TSD. */ typedef struct { - ClientData *tablePtr; /* The table of Tcl TSDs. */ + void **tablePtr; /* The table of Tcl TSDs. */ sig_atomic_t allocated; /* The size of the table in the current * thread. */ } TSDTable; /* @@ -188,11 +188,11 @@ void * TclThreadStorageKeyGet( Tcl_ThreadDataKey *dataKeyPtr) { TSDTable *tsdTablePtr = (TSDTable *)TclpThreadGetGlobalTSD(tsdGlobal.key); - ClientData resultPtr = NULL; + void *resultPtr = NULL; TSDUnion *keyPtr = (TSDUnion *) dataKeyPtr; sig_atomic_t offset = keyPtr->offset; if ((tsdTablePtr != NULL) && (offset > 0) && (offset < tsdTablePtr->allocated)) { Index: generic/tclThreadTest.c ================================================================== --- generic/tclThreadTest.c +++ generic/tclThreadTest.c @@ -4,12 +4,12 @@ * This file implements the testthread command. Eventually this should be * tclThreadCmd.c * Some of this code is based on work done by Richard Hipp on behalf of * Conservation Through Innovation, Limited, with their permission. * - * Copyright (c) 1998 by Sun Microsystems, Inc. - * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. + * Copyright © 1998 Sun Microsystems, Inc. + * Copyright © 2006-2008 Joe Mistachkin. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -117,13 +117,11 @@ * this mutex. */ TCL_DECLARE_MUTEX(threadMutex) -static int ThreadObjCmd(void *clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); +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); @@ -209,21 +207,20 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - int option; static const char *const threadOptions[] = { "cancel", "create", "event", "exit", "id", "join", "names", "send", "wait", "errorproc", NULL }; enum options { THREAD_CANCEL, THREAD_CREATE, THREAD_EVENT, THREAD_EXIT, THREAD_ID, THREAD_JOIN, THREAD_NAMES, THREAD_SEND, THREAD_WAIT, THREAD_ERRORPROC - }; + } option; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } @@ -242,11 +239,11 @@ ListUpdateInner(tsdPtr); Tcl_CreateThreadExitHandler(ThreadExitProc, NULL); Tcl_MutexUnlock(&threadMutex); } - switch ((enum options)option) { + switch (option) { case THREAD_CANCEL: { Tcl_WideInt id; const char *result; int flags, arg; @@ -269,15 +266,16 @@ if (arg < objc) { result = Tcl_GetString(objv[arg]); } else { result = NULL; } - return ThreadCancel(interp, (Tcl_ThreadId) (size_t) id, result, flags); + return ThreadCancel(interp, (Tcl_ThreadId) INT2PTR(id), result, flags); } case THREAD_CREATE: { const char *script; - int joinable, len; + int joinable; + Tcl_Size len; if (objc == 2) { /* * Neither joinable nor special script */ @@ -333,15 +331,15 @@ /* * Check if they want the main thread id or the current thread id. */ if (objc == 2) { - idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)Tcl_GetCurrentThread()); + idObj = Tcl_NewWideIntObj((Tcl_WideInt)PTR2INT(Tcl_GetCurrentThread())); } else if (objc == 3 && strcmp("-main", Tcl_GetString(objv[2])) == 0) { Tcl_MutexLock(&threadMutex); - idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)mainThreadId); + idObj = Tcl_NewWideIntObj((Tcl_WideInt)PTR2INT(mainThreadId)); Tcl_MutexUnlock(&threadMutex); } else { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } @@ -362,18 +360,18 @@ } if (Tcl_GetWideIntFromObj(interp, objv[2], &id) != TCL_OK) { return TCL_ERROR; } - result = Tcl_JoinThread((Tcl_ThreadId)(size_t)id, &status); + result = Tcl_JoinThread((Tcl_ThreadId)INT2PTR(id), &status); if (result == TCL_OK) { Tcl_SetIntObj(Tcl_GetObjResult(interp), status); } else { - char buf[20]; + char buf[TCL_INTEGER_SPACE]; - sprintf(buf, "%" TCL_LL_MODIFIER "d", id); - Tcl_AppendResult(interp, "cannot join thread ", buf, NULL); + snprintf(buf, sizeof(buf), "%" TCL_LL_MODIFIER "d", (long long)id); + Tcl_AppendResult(interp, "cannot join thread ", buf, (void *)NULL); } return result; } case THREAD_NAMES: if (objc > 2) { @@ -404,11 +402,11 @@ if (Tcl_GetWideIntFromObj(interp, objv[arg], &id) != TCL_OK) { return TCL_ERROR; } arg++; script = Tcl_GetString(objv[arg]); - return ThreadSend(interp, (Tcl_ThreadId)(size_t)id, script, wait); + return ThreadSend(interp, (Tcl_ThreadId)INT2PTR(id), script, wait); } case THREAD_EVENT: { if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; @@ -507,11 +505,11 @@ Tcl_MutexLock(&threadMutex); if (Tcl_CreateThread(&id, NewTestThread, &ctrl, TCL_THREAD_STACK_DEFAULT, joinable) != TCL_OK) { Tcl_MutexUnlock(&threadMutex); - Tcl_AppendResult(interp, "can't create a new thread", NULL); + Tcl_AppendResult(interp, "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! @@ -608,11 +606,11 @@ /* * Run the script. */ Tcl_Preserve(tsdPtr->interp); - result = Tcl_EvalEx(tsdPtr->interp, threadEvalScript, -1, 0); + result = Tcl_EvalEx(tsdPtr->interp, threadEvalScript, TCL_INDEX_NONE, 0); if (result != TCL_OK) { ThreadErrorProc(tsdPtr->interp); } /* @@ -650,11 +648,11 @@ Tcl_Channel errChannel; const char *errorInfo, *argv[3]; char *script; char buf[TCL_DOUBLE_SPACE+1]; - sprintf(buf, "%p", Tcl_GetCurrentThread()); + snprintf(buf, sizeof(buf), "%p", Tcl_GetCurrentThread()); errorInfo = Tcl_GetVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY); if (errorProcString == NULL) { errChannel = Tcl_GetStdChannel(TCL_STDERR); Tcl_WriteChars(errChannel, "Error from thread ", -1); @@ -818,16 +816,16 @@ break; } } if (!found) { Tcl_MutexUnlock(&threadMutex); - Tcl_AppendResult(interp, "invalid thread id", NULL); + Tcl_AppendResult(interp, "invalid thread id", (void *)NULL); return TCL_ERROR; } /* - * Short circut sends to ourself. Ought to do something with -async, like + * Short circuit sends to ourself. Ought to do something with -async, like * run in an idle handler. */ if (threadId == Tcl_GetCurrentThread()) { Tcl_MutexUnlock(&threadMutex); @@ -876,12 +874,11 @@ * 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); + TCL_QUEUE_TAIL|TCL_QUEUE_ALERT_IF_EMPTY); if (!wait) { Tcl_MutexUnlock(&threadMutex); return TCL_OK; } @@ -913,19 +910,19 @@ Tcl_MutexUnlock(&threadMutex); if (resultPtr->code != TCL_OK) { if (resultPtr->errorCode) { - Tcl_SetErrorCode(interp, resultPtr->errorCode, NULL); + 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, NULL); + Tcl_AppendResult(interp, resultPtr->result, (void *)NULL); Tcl_ConditionFinalize(&resultPtr->done); code = resultPtr->code; Tcl_Free(resultPtr->result); Tcl_Free(resultPtr); @@ -972,11 +969,11 @@ break; } } if (!found) { Tcl_MutexUnlock(&threadMutex); - Tcl_AppendResult(interp, "invalid thread id", NULL); + Tcl_AppendResult(interp, "invalid thread id", (void *)NULL); return TCL_ERROR; } /* * Since Tcl_CancelEval can be safely called from any thread, Index: generic/tclTimer.c ================================================================== --- generic/tclTimer.c +++ generic/tclTimer.c @@ -2,11 +2,11 @@ * tclTimer.c -- * * This file provides timer event management facilities for Tcl, * including the "after" command. * - * Copyright (c) 1997 by Sun Microsystems, Inc. + * Copyright © 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -19,11 +19,11 @@ */ typedef struct TimerHandler { Tcl_Time time; /* When timer is to fire. */ Tcl_TimerProc *proc; /* Function to call. */ - ClientData clientData; /* Argument to pass to proc. */ + void *clientData; /* Argument to pass to proc. */ Tcl_TimerToken token; /* Identifies handler so it can be deleted. */ struct TimerHandler *nextPtr; /* Next event in queue, or NULL for end of * queue. */ } TimerHandler; @@ -71,11 +71,11 @@ * linked together into a list. */ typedef struct IdleHandler { Tcl_IdleProc *proc; /* Function to call. */ - ClientData clientData; /* Value to pass to proc. */ + void *clientData; /* Value to pass to proc. */ int generation; /* Used to distinguish older handlers from * recently-created ones. */ struct IdleHandler *nextPtr;/* Next in list of active handlers. */ } IdleHandler; @@ -115,23 +115,23 @@ * the number of milliseconds difference between two times. Both macros use * both of their arguments multiple times, so make sure they are cheap and * side-effect free. The "prototypes" for these macros are: * * static int TCL_TIME_BEFORE(Tcl_Time t1, Tcl_Time t2); - * static long TCL_TIME_DIFF_MS(Tcl_Time t1, Tcl_Time t2); + * static Tcl_WideInt TCL_TIME_DIFF_MS(Tcl_Time t1, Tcl_Time t2); */ #define TCL_TIME_BEFORE(t1, t2) \ (((t1).sec<(t2).sec) || ((t1).sec==(t2).sec && (t1).usec<(t2).usec)) #define TCL_TIME_DIFF_MS(t1, t2) \ (1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \ - ((long)(t1).usec - (long)(t2).usec)/1000) + ((t1).usec - (t2).usec)/1000) #define TCL_TIME_DIFF_MS_CEILING(t1, t2) \ (1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \ - ((long)(t1).usec - (long)(t2).usec + 999)/1000) + ((t1).usec - (t2).usec + 999)/1000) /* * Sleeps under that number of milliseconds don't get double-checked * and are done in exactly one Tcl_Sleep(). This to limit gettimeofday()s. */ @@ -148,22 +148,22 @@ /* * Prototypes for functions referenced only in this file: */ -static void AfterCleanupProc(ClientData clientData, +static void AfterCleanupProc(void *clientData, Tcl_Interp *interp); static int AfterDelay(Tcl_Interp *interp, Tcl_WideInt ms); -static void AfterProc(ClientData clientData); +static void AfterProc(void *clientData); static void FreeAfterPtr(AfterInfo *afterPtr); static AfterInfo * GetAfterEvent(AfterAssocData *assocPtr, Tcl_Obj *commandPtr); static ThreadSpecificData *InitTimer(void); -static void TimerExitProc(ClientData clientData); +static void TimerExitProc(void *clientData); static int TimerHandlerEventProc(Tcl_Event *evPtr, int flags); -static void TimerCheckProc(ClientData clientData, int flags); -static void TimerSetupProc(ClientData clientData, int flags); +static void TimerCheckProc(void *clientData, int flags); +static void TimerSetupProc(void *clientData, int flags); /* *---------------------------------------------------------------------- * * InitTimer -- @@ -209,11 +209,11 @@ *---------------------------------------------------------------------- */ static void TimerExitProc( - TCL_UNUSED(ClientData)) + TCL_UNUSED(void *)) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); Tcl_DeleteEventSource(TimerSetupProc, TimerCheckProc, NULL); if (tsdPtr != NULL) { @@ -249,11 +249,11 @@ Tcl_TimerToken Tcl_CreateTimerHandler( int milliseconds, /* How many milliseconds to wait before * invoking proc. */ Tcl_TimerProc *proc, /* Function to invoke. */ - ClientData clientData) /* Arbitrary data to pass to proc. */ + void *clientData) /* Arbitrary data to pass to proc. */ { Tcl_Time time; /* * Compute when the event should fire. @@ -290,11 +290,11 @@ Tcl_TimerToken TclCreateAbsoluteTimerHandler( Tcl_Time *timePtr, Tcl_TimerProc *proc, - ClientData clientData) + void *clientData) { TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr; ThreadSpecificData *tsdPtr = InitTimer(); timerHandlerPtr = (TimerHandler *)Tcl_Alloc(sizeof(TimerHandler)); @@ -396,11 +396,11 @@ *---------------------------------------------------------------------- */ static void TimerSetupProc( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); @@ -454,11 +454,11 @@ *---------------------------------------------------------------------- */ static void TimerCheckProc( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { Tcl_Event *timerEvPtr; Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); @@ -617,11 +617,11 @@ */ void Tcl_DoWhenIdle( Tcl_IdleProc *proc, /* Function to invoke. */ - ClientData clientData) /* Arbitrary value to pass to proc. */ + void *clientData) /* Arbitrary value to pass to proc. */ { IdleHandler *idlePtr; Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); @@ -661,11 +661,11 @@ */ void Tcl_CancelIdleCall( Tcl_IdleProc *proc, /* Function that was previously registered. */ - ClientData clientData) /* Arbitrary value to pass to proc. */ + void *clientData) /* Arbitrary value to pass to proc. */ { IdleHandler *idlePtr, *prevPtr; IdleHandler *nextPtr; ThreadSpecificData *tsdPtr = InitTimer(); @@ -776,20 +776,20 @@ *---------------------------------------------------------------------- */ int Tcl_AfterObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_WideInt ms = 0; /* Number of milliseconds to wait */ Tcl_Time wakeup; AfterInfo *afterPtr; AfterAssocData *assocPtr; - size_t length; + Tcl_Size length; int index = -1; static const char *const afterSubCmds[] = { "cancel", "idle", "info", NULL }; enum afterSubCmdsEnum {AFTER_CANCEL, AFTER_IDLE, AFTER_INFO}; @@ -818,17 +818,17 @@ */ 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]); + 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); + arg, (void *)NULL); return TCL_ERROR; } } /* @@ -864,12 +864,12 @@ */ afterPtr->id = tsdPtr->afterId; tsdPtr->afterId += 1; Tcl_GetTime(&wakeup); - wakeup.sec += (long)(ms / 1000); - wakeup.usec += ((long)(ms % 1000)) * 1000; + wakeup.sec += ms / 1000; + wakeup.usec += ms % 1000 * 1000; if (wakeup.usec > 1000000) { wakeup.sec++; wakeup.usec -= 1000000; } afterPtr->token = TclCreateAbsoluteTimerHandler(&wakeup, @@ -880,11 +880,11 @@ return TCL_OK; } case AFTER_CANCEL: { Tcl_Obj *commandPtr; const char *command, *tempCommand; - size_t tempLength; + Tcl_Size tempLength; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "id|command"); return TCL_ERROR; } @@ -891,14 +891,14 @@ if (objc == 3) { commandPtr = objv[2]; } else { commandPtr = Tcl_ConcatObj(objc-2, objv+2); } - command = TclGetStringFromObj(commandPtr, &length); + command = Tcl_GetStringFromObj(commandPtr, &length); for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL; afterPtr = afterPtr->nextPtr) { - tempCommand = TclGetStringFromObj(afterPtr->commandPtr, + tempCommand = Tcl_GetStringFromObj(afterPtr->commandPtr, &tempLength); if ((length == tempLength) && !memcmp(command, tempCommand, length)) { break; } @@ -946,12 +946,12 @@ TclNewObj(resultObj); for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL; afterPtr = afterPtr->nextPtr) { if (assocPtr->interp == interp) { - Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf( - "after#%d", afterPtr->id)); + Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf( + "after#%d", afterPtr->id)); } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } @@ -963,22 +963,22 @@ 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); + Tcl_SetErrorCode(interp, "TCL","LOOKUP","EVENT", eventStr, (void *)NULL); return TCL_ERROR; } else { - Tcl_Obj *resultListPtr; + Tcl_Obj *resultListPtr; - TclNewObj(resultListPtr); - Tcl_ListObjAppendElement(interp, resultListPtr, - afterPtr->commandPtr); - Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj( + TclNewObj(resultListPtr); + Tcl_ListObjAppendElement(interp, resultListPtr, + afterPtr->commandPtr); + Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj( (afterPtr->token == NULL) ? "idle" : "timer", -1)); Tcl_SetObjResult(interp, resultListPtr); - } + } break; default: Tcl_Panic("Tcl_AfterObjCmd: bad subcommand index to afterSubCmds"); } return TCL_OK; @@ -1012,12 +1012,12 @@ Tcl_Time endTime, now; Tcl_WideInt diff; Tcl_GetTime(&now); endTime = now; - endTime.sec += (long)(ms / 1000); - endTime.usec += ((int)(ms % 1000)) * 1000; + endTime.sec += (ms / 1000); + endTime.usec += (ms % 1000) * 1000; if (endTime.usec >= 1000000) { endTime.sec++; endTime.usec -= 1000000; } @@ -1045,11 +1045,11 @@ } if (diff == 0 && TCL_TIME_BEFORE(now, endTime)) { diff = 1; } if (diff > 0) { - Tcl_Sleep((long) diff); + Tcl_Sleep((int) diff); if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) { break; } } else { break; @@ -1147,11 +1147,11 @@ *---------------------------------------------------------------------- */ static void AfterProc( - ClientData clientData) /* Describes command to execute. */ + void *clientData) /* Describes command to execute. */ { AfterInfo *afterPtr = (AfterInfo *)clientData; AfterAssocData *assocPtr = afterPtr->assocPtr; AfterInfo *prevPtr; int result; @@ -1249,11 +1249,11 @@ *---------------------------------------------------------------------- */ static void AfterCleanupProc( - ClientData clientData, /* Points to AfterAssocData for the + void *clientData, /* Points to AfterAssocData for the * interpreter. */ TCL_UNUSED(Tcl_Interp *)) { AfterAssocData *assocPtr = (AfterAssocData *)clientData; AfterInfo *afterPtr; Index: generic/tclTomMath.decls ================================================================== --- generic/tclTomMath.decls +++ generic/tclTomMath.decls @@ -5,21 +5,20 @@ # generate the 'tclTomMathDecls.h' and 'tclStubInit.c' files. # # If you edit this file, advance the revision number (and the epoch # if the new stubs are not backward compatible) in tclTomMathDecls.h # -# Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. +# Copyright © 2005 Kevin B. Kenny. All rights reserved. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. library tcl # Define the unsupported generic interfaces. interface tclTomMath -# hooks {tclTomMathInt} scspec EXTERN # Declare each of the functions in the Tcl tommath interface declare 0 { @@ -73,11 +72,11 @@ } 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}} { +#declare 17 { # 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) } @@ -140,11 +139,11 @@ } declare 38 { mp_err MP_WUR TclBN_mp_shrink(mp_int *a) } # Removed in 9.0 -#declare 39 {deprecated {macro calling mp_set_u64}} { +#declare 39 { # 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) @@ -179,22 +178,22 @@ } declare 49 { void TclBN_mp_zero(mp_int *a) } # Removed in 9.0 -#declare 61 {deprecated {macro calling mp_init_u64}} { +#declare 61 { # mp_err TclBN_mp_init_ul(mp_int *a, unsigned long i) #} # Removed in 9.0 -#declare 62 {deprecated {macro calling mp_set_u64}} { +#declare 62 { # 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}} { +#declare 64 { # 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) } @@ -214,10 +213,18 @@ 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) +} # 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) @@ -231,10 +238,13 @@ # int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) #} declare 76 { mp_err MP_WUR TclBN_mp_signed_rsh(const mp_int *a, int b, mp_int *c) } +declare 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) } Index: generic/tclTomMath.h ================================================================== --- generic/tclTomMath.h +++ generic/tclTomMath.h @@ -1,15 +1,9 @@ #ifndef BN_TCL_H_ #define BN_TCL_H_ -#ifdef MP_NO_STDINT -# ifdef HAVE_STDINT_H -# include -#else -# include "../compat/stdint.h" -# endif -#endif +#include #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 */ @@ -22,10 +16,18 @@ # 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 */ Index: generic/tclTomMathDecls.h ================================================================== --- generic/tclTomMathDecls.h +++ generic/tclTomMathDecls.h @@ -33,36 +33,56 @@ TCLTOMMATH_EPOCH,TCLTOMMATH_REVISION)) /* Define custom memory allocation for libtommath */ /* MODULE_SCOPE void* TclBNAlloc( size_t ); */ -#define TclBNAlloc(s) ((void*)Tcl_Alloc(s)) +#define TclBNAlloc(s) Tcl_AttemptAlloc((size_t)(s)) /* MODULE_SCOPE void* TclBNCalloc( size_t, size_t ); */ -#define TclBNCalloc(m,s) memset(Tcl_Alloc((size_t)(m)*(size_t)(s)),0,(size_t)(m)*(size_t)(s)) +#define TclBNCalloc(m,s) memset(Tcl_AttemptAlloc((size_t)(m)*(size_t)(s)),0,(size_t)(m)*(size_t)(s)) /* MODULE_SCOPE void* TclBNRealloc( void*, size_t ); */ -#define TclBNRealloc(x,s) ((void*)Tcl_Realloc((char*)(x),(size_t)(s))) +#define TclBNRealloc(x,s) Tcl_AttemptRealloc((x),(size_t)(s)) /* MODULE_SCOPE void TclBNFree( void* ); */ -#define TclBNFree(x) (Tcl_Free((char*)(x))) +#define TclBNFree(x) Tcl_Free(x) #undef MP_MALLOC #undef MP_CALLOC #undef MP_REALLOC #undef MP_FREE #define MP_MALLOC(size) TclBNAlloc(size) -#define MP_CALLOC(nmemb, size) TclBNCalloc(nmemb, size) -#define MP_REALLOC(mem, oldsize, newsize) TclBNRealloc(mem, newsize) -#define MP_FREE(mem, size) TclBNFree(mem) +#define MP_CALLOC(nmemb, size) TclBNCalloc((nmemb), (size)) +#define MP_REALLOC(mem, oldsize, newsize) TclBNRealloc((mem), ((void)(oldsize), (newsize))) +#define MP_FREE(mem, size) TclBNFree(((void)(size), (mem))) #ifndef MODULE_SCOPE -# define MODULE_SCOPE extern +# 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_div_3(const mp_int *a, mp_int *q, mp_digit *r); +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_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_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs); +MODULE_SCOPE mp_err TclBN_s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs); +MODULE_SCOPE void TclBN_s_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_s_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 */ @@ -106,10 +126,12 @@ #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 @@ -131,10 +153,11 @@ #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_karatsuba_mul TclBN_mp_karatsuba_mul @@ -311,19 +334,29 @@ EXTERN void TclBN_mp_set_u64(mp_int *a, uint64_t i); /* 69 */ EXTERN uint64_t TclBN_mp_get_mag_u64(const mp_int *a) MP_WUR; /* 70 */ EXTERN void TclBN_mp_set_i64(mp_int *a, int64_t i); -/* Slot 71 is reserved */ -/* Slot 72 is reserved */ +/* 71 */ +EXTERN mp_err TclBN_mp_unpack(mp_int *rop, size_t count, + mp_order order, size_t size, + mp_endian endian, size_t nails, + const void *op) MP_WUR; +/* 72 */ +EXTERN mp_err TclBN_mp_pack(void *rop, size_t maxcount, + size_t *written, mp_order order, size_t size, + mp_endian endian, size_t nails, + const mp_int *op) MP_WUR; /* Slot 73 is reserved */ /* Slot 74 is reserved */ /* Slot 75 is reserved */ /* 76 */ EXTERN mp_err TclBN_mp_signed_rsh(const mp_int *a, int b, mp_int *c) MP_WUR; -/* Slot 77 is reserved */ +/* 77 */ +EXTERN size_t TclBN_mp_pack_count(const mp_int *a, size_t nails, + size_t size) MP_WUR; /* 78 */ EXTERN int TclBN_mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) MP_WUR; /* Slot 79 is reserved */ /* 80 */ @@ -403,17 +436,17 @@ int (*tclBN_mp_init_u64) (mp_int *bignum, uint64_t initVal) MP_WUR; /* 66 */ void (*reserved67)(void); void (*tclBN_mp_set_u64) (mp_int *a, uint64_t i); /* 68 */ uint64_t (*tclBN_mp_get_mag_u64) (const mp_int *a) MP_WUR; /* 69 */ void (*tclBN_mp_set_i64) (mp_int *a, int64_t i); /* 70 */ - void (*reserved71)(void); - void (*reserved72)(void); + mp_err (*tclBN_mp_unpack) (mp_int *rop, size_t count, mp_order order, size_t size, mp_endian endian, size_t nails, const void *op) MP_WUR; /* 71 */ + mp_err (*tclBN_mp_pack) (void *rop, size_t maxcount, size_t *written, mp_order order, size_t size, mp_endian endian, size_t nails, const mp_int *op) MP_WUR; /* 72 */ void (*reserved73)(void); void (*reserved74)(void); void (*reserved75)(void); mp_err (*tclBN_mp_signed_rsh) (const mp_int *a, int b, mp_int *c) MP_WUR; /* 76 */ - void (*reserved77)(void); + size_t (*tclBN_mp_pack_count) (const mp_int *a, size_t nails, size_t size) MP_WUR; /* 77 */ int (*tclBN_mp_to_ubin) (const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) MP_WUR; /* 78 */ void (*reserved79)(void); int (*tclBN_mp_to_radix) (const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) MP_WUR; /* 80 */ } TclTomMathStubs; @@ -548,18 +581,21 @@ (tclTomMathStubsPtr->tclBN_mp_set_u64) /* 68 */ #define TclBN_mp_get_mag_u64 \ (tclTomMathStubsPtr->tclBN_mp_get_mag_u64) /* 69 */ #define TclBN_mp_set_i64 \ (tclTomMathStubsPtr->tclBN_mp_set_i64) /* 70 */ -/* Slot 71 is reserved */ -/* Slot 72 is reserved */ +#define TclBN_mp_unpack \ + (tclTomMathStubsPtr->tclBN_mp_unpack) /* 71 */ +#define TclBN_mp_pack \ + (tclTomMathStubsPtr->tclBN_mp_pack) /* 72 */ /* Slot 73 is reserved */ /* Slot 74 is reserved */ /* Slot 75 is reserved */ #define TclBN_mp_signed_rsh \ (tclTomMathStubsPtr->tclBN_mp_signed_rsh) /* 76 */ -/* Slot 77 is reserved */ +#define TclBN_mp_pack_count \ + (tclTomMathStubsPtr->tclBN_mp_pack_count) /* 77 */ #define TclBN_mp_to_ubin \ (tclTomMathStubsPtr->tclBN_mp_to_ubin) /* 78 */ /* Slot 79 is reserved */ #define TclBN_mp_to_radix \ (tclTomMathStubsPtr->tclBN_mp_to_radix) /* 80 */ Index: generic/tclTomMathInterface.c ================================================================== --- generic/tclTomMathInterface.c +++ generic/tclTomMathInterface.c @@ -4,11 +4,11 @@ * tclTomMathInterface.c -- * * This file contains procedures that are used as a 'glue' layer between * Tcl and libtommath. * - * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. + * Copyright © 2005 Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tclTomMathStubLib.c ================================================================== --- generic/tclTomMathStubLib.c +++ generic/tclTomMathStubLib.c @@ -2,12 +2,12 @@ * tclTomMathStubLib.c -- * * Stub object that will be statically linked into extensions that want * to access Tcl. * - * Copyright (c) 1998-1999 by Scriptics Corporation. - * Copyright (c) 1998 Paul Duffin. + * Copyright © 1998-1999 Scriptics Corporation. + * Copyright © 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tclTrace.c ================================================================== --- generic/tclTrace.c +++ generic/tclTrace.c @@ -1,14 +1,14 @@ /* * tclTrace.c -- * * This file contains code to handle most trace management. * - * Copyright (c) 1987-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 Scriptics Corporation. - * Copyright (c) 2002 ActiveState Corporation. + * Copyright © 1987-1993 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Scriptics Corporation. + * Copyright © 2002 ActiveState Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -19,12 +19,12 @@ */ typedef struct { int flags; /* Operations for which Tcl command is to be * invoked. */ - size_t length; /* Number of non-NUL chars. in command. */ - char command[1]; /* Space for Tcl command to invoke. Actual + Tcl_Size length; /* Number of non-NUL chars. in command. */ + char command[TCLFLEXARRAY]; /* Space for Tcl command to invoke. Actual * size will be as large as necessary to hold * command. This field must be the last in the * structure, so that it can be larger than 1 * byte. */ } TraceVarInfo; @@ -39,14 +39,14 @@ */ typedef struct { int flags; /* Operations for which Tcl command is to be * invoked. */ - size_t length; /* Number of non-NUL chars. in command. */ + Tcl_Size length; /* Number of non-NUL chars. in command. */ Tcl_Trace stepTrace; /* Used for execution traces, when tracing * inside the given command */ - int startLevel; /* Used for bookkeeping with step execution + Tcl_Size startLevel; /* Used for bookkeeping with step execution * traces, store the level at which the step * trace was invoked */ char *startCmd; /* Used for bookkeeping with step execution * traces, store the command name which * invoked step trace */ @@ -54,11 +54,11 @@ int curCode; /* Return code for the current command */ size_t refCount; /* Used to ensure this structure is not * deleted too early. Keeps track of how many * pieces of code have a pointer to this * structure. */ - char command[1]; /* Space for Tcl command to invoke. Actual + char command[TCLFLEXARRAY]; /* Space for Tcl command to invoke. Actual * size will be as large as necessary to hold * command. This field must be the last in the * structure, so that it can be larger than 1 * byte. */ } TraceCommandInfo; @@ -90,12 +90,15 @@ /* * Forward declarations for functions defined in this file: */ -typedef int (Tcl_TraceTypeObjCmd)(Tcl_Interp *interp, int optionIndex, - int objc, Tcl_Obj *const objv[]); +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; @@ -118,23 +121,23 @@ /* * Declarations for local functions to this file: */ static int CallTraceFunction(Tcl_Interp *interp, Trace *tracePtr, - Command *cmdPtr, const char *command, size_t numChars, - int objc, Tcl_Obj *const objv[]); -static char * TraceVarProc(ClientData clientData, Tcl_Interp *interp, + Command *cmdPtr, const char *command, Tcl_Size numChars, + Tcl_Size objc, Tcl_Obj *const objv[]); +static char * TraceVarProc(void *clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); -static void TraceCommandProc(ClientData clientData, +static void TraceCommandProc(void *clientData, Tcl_Interp *interp, const char *oldName, const char *newName, int flags); -static Tcl_CmdObjTraceProc TraceExecutionProc; -static int StringTraceProc(ClientData clientData, - Tcl_Interp *interp, int level, +static Tcl_CmdObjTraceProc2 TraceExecutionProc; +static int StringTraceProc(void *clientData, + Tcl_Interp *interp, Tcl_Size level, const char *command, Tcl_Command commandInfo, - int objc, Tcl_Obj *const objv[]); -static void StringTraceDeleteProc(ClientData clientData); + Tcl_Size objc, Tcl_Obj *const objv[]); +static void StringTraceDeleteProc(void *clientData); static void DisposeTraceResult(int flags, char *result); static int TraceVarEx(Tcl_Interp *interp, const char *part1, const char *part2, VarTrace *tracePtr); /* @@ -141,11 +144,11 @@ * The following structure holds the client data for string-based * trace procs */ typedef struct { - ClientData clientData; /* Client data from Tcl_CreateTrace */ + void *clientData; /* Client data from Tcl_CreateTrace */ Tcl_CmdTraceProc *proc; /* Trace function from Tcl_CreateTrace */ } StringTraceData; /* * Convenience macros for iterating over the list of traces. Note that each of @@ -157,12 +160,12 @@ while (((clientData) = Tcl_VarTraceInfo2((interp), (name), NULL, \ 0, TraceVarProc, (clientData))) != NULL) #define FOREACH_COMMAND_TRACE(interp, name, clientData) \ (clientData) = NULL; \ - while ((clientData = Tcl_CommandTraceInfo(interp, name, 0, \ - TraceCommandProc, clientData)) != NULL) + while (((clientData) = Tcl_CommandTraceInfo((interp), (name), 0, \ + TraceCommandProc, (clientData))) != NULL) /* *---------------------------------------------------------------------- * * Tcl_TraceObjCmd -- @@ -186,30 +189,16 @@ 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 - }; + enum traceOptionsEnum optionIndex; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } @@ -216,11 +205,11 @@ if (Tcl_GetIndexFromObj(interp, objv[1], traceOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } - switch ((enum traceOptionsEnum) optionIndex) { + switch (optionIndex) { case TRACE_ADD: case TRACE_REMOVE: { /* * All sub commands of trace add/remove must take at least one more * argument. Beyond that we let the subcommand itself control the @@ -262,120 +251,12 @@ } 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 } /* *---------------------------------------------------------------------- * @@ -396,33 +277,29 @@ */ static int TraceExecutionObjCmd( Tcl_Interp *interp, /* Current interpreter. */ - int optionIndex, /* Add, info or remove */ - int objc, /* Number of arguments. */ + enum traceOptionsEnum optionIndex, /* Add, info or remove */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int index; const char *name, *command; - size_t commandLength, length; - enum traceOptions { - TRACE_ADD, TRACE_INFO, TRACE_REMOVE - }; + 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 ((enum traceOptions) optionIndex) { + switch (optionIndex) { case TRACE_ADD: case TRACE_REMOVE: { - int flags = 0; - int i, listLen, result; + int flags = 0, result; + Tcl_Size i, listLen; Tcl_Obj **elemPtrs; if (objc != 6) { Tcl_WrongNumArgs(interp, 3, objv, "name opList command"); return TCL_ERROR; @@ -431,28 +308,32 @@ /* * Make sure the ops argument is a list object; get its length and a * pointer to its array of element pointers. */ - result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs); + result = TclListObjLengthM(interp, objv[4], &listLen); if (result != TCL_OK) { return result; } if (listLen == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad operation list \"\": must be one or more of" " enter, leave, enterstep, or leavestep", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "NOOPS", - NULL); + (void *)NULL); return TCL_ERROR; + } + result = TclListObjGetElementsM(interp, objv[4], &listLen, &elemPtrs); + if (result != TCL_OK) { + return result; } for (i = 0; i < listLen; i++) { if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings, "operation", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum operations) index) { + switch (index) { case TRACE_EXEC_ENTER: flags |= TCL_TRACE_ENTER_EXEC; break; case TRACE_EXEC_LEAVE: flags |= TCL_TRACE_LEAVE_EXEC; @@ -463,13 +344,12 @@ 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) { + command = Tcl_GetStringFromObj(objv[5], &length); + if (optionIndex == TRACE_ADD) { TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)Tcl_Alloc( offsetof(TraceCommandInfo, command) + 1 + length); tcmdPtr->flags = flags; tcmdPtr->stepTrace = NULL; @@ -494,11 +374,11 @@ * Search through all of our traces on this command to see if * there's one with the given command. If so, then delete the * first one that matches. */ - ClientData clientData; + void *clientData; /* * First ensure the name given is valid. */ @@ -553,11 +433,11 @@ } } break; } case TRACE_INFO: { - ClientData clientData; + void *clientData; Tcl_Obj *resultListPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "name"); return TCL_ERROR; @@ -573,11 +453,11 @@ return TCL_ERROR; } resultListPtr = Tcl_NewListObj(0, NULL); FOREACH_COMMAND_TRACE(interp, name, clientData) { - int numOps = 0; + Tcl_Size numOps = 0; Tcl_Obj *opObj, *eachTraceObjPtr, *elemObjPtr; TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)clientData; /* * Build a list with the ops list as the first obj element and the @@ -601,11 +481,11 @@ } if (tcmdPtr->flags & TCL_TRACE_LEAVE_DURING_EXEC) { TclNewLiteralStringObj(opObj, "leavestep"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj); } - Tcl_ListObjLength(NULL, elemObjPtr, &numOps); + TclListObjLengthM(NULL, elemObjPtr, &numOps); if (0 == numOps) { Tcl_DecrRefCount(elemObjPtr); continue; } eachTraceObjPtr = Tcl_NewListObj(0, NULL); @@ -644,26 +524,24 @@ */ static int TraceCommandObjCmd( Tcl_Interp *interp, /* Current interpreter. */ - int optionIndex, /* Add, info or remove */ - int objc, /* Number of arguments. */ + enum traceOptionsEnum optionIndex, /* Add, info or remove */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int index; const char *name, *command; - size_t commandLength, length; - enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE }; + Tcl_Size length; static const char *const opStrings[] = { "delete", "rename", NULL }; - enum operations { TRACE_CMD_DELETE, TRACE_CMD_RENAME }; + enum operations { TRACE_CMD_DELETE, TRACE_CMD_RENAME } index; - switch ((enum traceOptions) optionIndex) { + switch (optionIndex) { case TRACE_ADD: case TRACE_REMOVE: { - int flags = 0; - int i, listLen, result; + int flags = 0, result; + Tcl_Size i, listLen; Tcl_Obj **elemPtrs; if (objc != 6) { Tcl_WrongNumArgs(interp, 3, objv, "name opList command"); return TCL_ERROR; @@ -672,41 +550,43 @@ /* * Make sure the ops argument is a list object; get its length and a * pointer to its array of element pointers. */ - result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs); + result = TclListObjLengthM(interp, objv[4], &listLen); if (result != TCL_OK) { return result; } if (listLen == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad operation list \"\": must be one or more of" " delete or rename", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "NOOPS", - NULL); + (void *)NULL); return TCL_ERROR; } - + result = TclListObjGetElementsM(interp, objv[4], &listLen, &elemPtrs); + if (result != TCL_OK) { + return result; + } for (i = 0; i < listLen; i++) { if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings, "operation", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum operations) index) { + switch (index) { case TRACE_CMD_RENAME: flags |= TCL_TRACE_RENAME; break; case TRACE_CMD_DELETE: flags |= TCL_TRACE_DELETE; break; } } - command = TclGetStringFromObj(objv[5], &commandLength); - length = commandLength; - if ((enum traceOptions) optionIndex == TRACE_ADD) { + command = Tcl_GetStringFromObj(objv[5], &length); + if (optionIndex == TRACE_ADD) { TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)Tcl_Alloc( offsetof(TraceCommandInfo, command) + 1 + length); tcmdPtr->flags = flags; tcmdPtr->stepTrace = NULL; @@ -727,11 +607,11 @@ * Search through all of our traces on this command to see if * there's one with the given command. If so, then delete the * first one that matches. */ - ClientData clientData; + void *clientData; /* * First ensure the name given is valid. */ @@ -757,11 +637,11 @@ } } break; } case TRACE_INFO: { - ClientData clientData; + void *clientData; Tcl_Obj *resultListPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "name"); return TCL_ERROR; @@ -776,11 +656,11 @@ return TCL_ERROR; } resultListPtr = Tcl_NewListObj(0, NULL); FOREACH_COMMAND_TRACE(interp, name, clientData) { - int numOps = 0; + Tcl_Size numOps = 0; Tcl_Obj *opObj, *eachTraceObjPtr, *elemObjPtr; TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)clientData; /* * Build a list with the ops list as the first obj element and the @@ -796,11 +676,11 @@ } if (tcmdPtr->flags & TCL_TRACE_DELETE) { TclNewLiteralStringObj(opObj, "delete"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj); } - Tcl_ListObjLength(NULL, elemObjPtr, &numOps); + TclListObjLengthM(NULL, elemObjPtr, &numOps); if (0 == numOps) { Tcl_DecrRefCount(elemObjPtr); continue; } eachTraceObjPtr = Tcl_NewListObj(0, NULL); @@ -838,31 +718,29 @@ */ static int TraceVariableObjCmd( Tcl_Interp *interp, /* Current interpreter. */ - int optionIndex, /* Add, info or remove */ - int objc, /* Number of arguments. */ + enum traceOptionsEnum optionIndex, /* Add, info or remove */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int index; const char *name, *command; - size_t commandLength, length; - ClientData clientData; - enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE }; + 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 ((enum traceOptions) optionIndex) { + switch (optionIndex) { case TRACE_ADD: case TRACE_REMOVE: { - int flags = 0; - int i, listLen, result; + int flags = 0, result; + Tcl_Size i, listLen; Tcl_Obj **elemPtrs; if (objc != 6) { Tcl_WrongNumArgs(interp, 3, objv, "name opList command"); return TCL_ERROR; @@ -871,28 +749,32 @@ /* * Make sure the ops argument is a list object; get its length and a * pointer to its array of element pointers. */ - result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs); + result = TclListObjLengthM(interp, objv[4], &listLen); if (result != TCL_OK) { return result; } if (listLen == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad operation list \"\": must be one or more of" " array, read, unset, or write", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "NOOPS", - NULL); + (void *)NULL); return TCL_ERROR; + } + result = TclListObjGetElementsM(interp, objv[4], &listLen, &elemPtrs); + if (result != TCL_OK) { + return result; } for (i = 0; i < listLen ; i++) { if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings, "operation", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } - switch ((enum operations) index) { + switch (index) { case TRACE_VAR_ARRAY: flags |= TCL_TRACE_ARRAY; break; case TRACE_VAR_READ: flags |= TCL_TRACE_READS; @@ -903,23 +785,17 @@ case TRACE_VAR_WRITE: flags |= TCL_TRACE_WRITES; break; } } - command = TclGetStringFromObj(objv[5], &commandLength); - length = commandLength; - if ((enum traceOptions) optionIndex == TRACE_ADD) { + command = Tcl_GetStringFromObj(objv[5], &length); + if (optionIndex == TRACE_ADD) { CombinedTraceVarInfo *ctvarPtr = (CombinedTraceVarInfo *)Tcl_Alloc( offsetof(CombinedTraceVarInfo, traceCmdInfo.command) + 1 + length); ctvarPtr->traceCmdInfo.flags = flags; -#ifndef TCL_REMOVE_OBSOLETE_TRACES - if (objv[0] == NULL) { - ctvarPtr->traceCmdInfo.flags |= TCL_TRACE_OLD_STYLE; - } -#endif ctvarPtr->traceCmdInfo.length = length; flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT; memcpy(ctvarPtr->traceCmdInfo.command, command, length+1); ctvarPtr->traceInfo.traceProc = TraceVarProc; ctvarPtr->traceInfo.clientData = &ctvarPtr->traceCmdInfo; @@ -940,15 +816,11 @@ 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) + && ((tvarPtr->flags)==flags) && (strncmp(command, tvarPtr->command, length) == 0)) { Tcl_UntraceVar2(interp, name, NULL, flags | TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT, TraceVarProc, clientData); @@ -1033,17 +905,17 @@ * None. * *---------------------------------------------------------------------- */ -ClientData +void * Tcl_CommandTraceInfo( Tcl_Interp *interp, /* Interpreter containing command. */ const char *cmdName, /* Name of command. */ TCL_UNUSED(int) /*flags*/, Tcl_CommandTraceProc *proc, /* Function assocated with trace. */ - ClientData prevClientData) /* If non-NULL, gives last value returned by + void *prevClientData) /* If non-NULL, gives last value returned by * this function, so this call will return the * next trace after that one. If NULL, this * call will return the first trace. */ { Command *cmdPtr; @@ -1091,11 +963,11 @@ * Results: * A standard Tcl return value. * * Side effects: * A trace is set up on the command given by cmdName, such that future - * changes to the command will be intermediated by proc. See the manual + * changes to the command will be mediated by proc. See the manual * entry for complete details on the calling sequence for proc. * *---------------------------------------------------------------------- */ @@ -1107,11 +979,11 @@ int flags, /* OR-ed collection of bits, including any of * TCL_TRACE_RENAME, TCL_TRACE_DELETE, and any * of the TRACE_*_EXEC flags */ Tcl_CommandTraceProc *proc, /* Function to call when specified ops are * invoked upon cmdName. */ - ClientData clientData) /* Arbitrary argument to pass to proc. */ + void *clientData) /* Arbitrary argument to pass to proc. */ { Command *cmdPtr; CommandTrace *tracePtr; cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL, @@ -1171,11 +1043,11 @@ const char *cmdName, /* Name of command. */ int flags, /* OR-ed collection of bits, including any of * TCL_TRACE_RENAME, TCL_TRACE_DELETE, and any * of the TRACE_*_EXEC flags */ Tcl_CommandTraceProc *proc, /* Function assocated with trace. */ - ClientData clientData) /* Arbitrary argument to pass to proc. */ + void *clientData) /* Arbitrary argument to pass to proc. */ { CommandTrace *tracePtr; CommandTrace *prevPtr; Command *cmdPtr; Interp *iPtr = (Interp *)interp; @@ -1276,11 +1148,11 @@ *---------------------------------------------------------------------- */ static void TraceCommandProc( - ClientData clientData, /* Information about the command trace. */ + void *clientData, /* Information about the command trace. */ Tcl_Interp *interp, /* Interpreter containing command. */ const char *oldName, /* Name of command being changed. */ const char *newName, /* New name of command. Empty string or NULL * means command is being deleted (renamed to * ""). */ @@ -1417,21 +1289,21 @@ int TclCheckExecutionTraces( Tcl_Interp *interp, /* The current interpreter. */ const char *command, /* Pointer to beginning of the current command * string. */ - TCL_UNUSED(size_t) /*numChars*/, + TCL_UNUSED(Tcl_Size) /*numChars*/, Command *cmdPtr, /* Points to command's Command struct. */ int code, /* The current result code. */ int traceFlags, /* Current tracing situation. */ - int objc, /* Number of arguments for the command. */ + Tcl_Size objc, /* Number of arguments for the command. */ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */ { Interp *iPtr = (Interp *) interp; CommandTrace *tracePtr, *lastTracePtr; ActiveCommandTrace active; - int curLevel; + Tcl_Size curLevel; int traceCode = TCL_OK; Tcl_InterpState state = NULL; if (cmdPtr->tracePtr == NULL) { return traceCode; @@ -1522,22 +1394,22 @@ int TclCheckInterpTraces( Tcl_Interp *interp, /* The current interpreter. */ const char *command, /* Pointer to beginning of the current command * string. */ - size_t numChars, /* The number of characters in 'command' which + Tcl_Size numChars, /* The number of characters in 'command' which * are part of the command string. */ Command *cmdPtr, /* Points to command's Command struct. */ int code, /* The current result code. */ int traceFlags, /* Current tracing situation. */ - int objc, /* Number of arguments for the command. */ + Tcl_Size objc, /* Number of arguments for the command. */ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */ { Interp *iPtr = (Interp *) interp; Trace *tracePtr, *lastTracePtr; ActiveInterpTrace active; - int curLevel; + Tcl_Size curLevel; int traceCode = TCL_OK; Tcl_InterpState state = NULL; if ((iPtr->tracePtr == NULL) || (iPtr->flags & INTERP_TRACE_IN_PROGRESS)) { @@ -1669,13 +1541,13 @@ Tcl_Interp *interp, /* The current interpreter. */ Trace *tracePtr, /* Describes the trace function to call. */ Command *cmdPtr, /* Points to command's Command struct. */ const char *command, /* Points to the first character of the * command's source before substitutions. */ - size_t numChars, /* The number of characters in the command's + Tcl_Size numChars, /* The number of characters in the command's * source. */ - int objc, /* Number of arguments for the command. */ + Tcl_Size objc, /* Number of arguments for the command. */ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */ { Interp *iPtr = (Interp *) interp; char *commandCopy; int traceCode; @@ -1716,11 +1588,11 @@ *---------------------------------------------------------------------- */ static void CommandObjTraceDeleted( - ClientData clientData) + void *clientData) { TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)clientData; if (tcmdPtr->refCount-- <= 1) { Tcl_Free(tcmdPtr); @@ -1752,17 +1624,17 @@ *---------------------------------------------------------------------- */ static int TraceExecutionProc( - ClientData clientData, + void *clientData, Tcl_Interp *interp, - int level, + Tcl_Size level, const char *command, TCL_UNUSED(Tcl_Command), - int objc, - struct Tcl_Obj *const objv[]) + Tcl_Size objc, + Tcl_Obj *const objv[]) { int call = 0; Interp *iPtr = (Interp *) interp; TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)clientData; int flags = tcmdPtr->curFlags; @@ -1812,11 +1684,12 @@ * Second, create the tcl callback, if required. */ if (call) { Tcl_DString cmd, sub; - int i, saveInterpFlags; + Tcl_Size i; + int saveInterpFlags; Tcl_DStringInit(&cmd); Tcl_DStringAppend(&cmd, tcmdPtr->command, tcmdPtr->length); /* @@ -1919,11 +1792,11 @@ tcmdPtr->startLevel = level; tcmdPtr->startCmd = (char *)Tcl_Alloc(len); memcpy(tcmdPtr->startCmd, command, len); tcmdPtr->refCount++; - tcmdPtr->stepTrace = Tcl_CreateObjTrace(interp, 0, + tcmdPtr->stepTrace = Tcl_CreateObjTrace2(interp, 0, (tcmdPtr->flags & TCL_TRACE_ANY_EXEC) >> 2, TraceExecutionProc, tcmdPtr, CommandObjTraceDeleted); } } if (flags & TCL_TRACE_DESTROYED) { @@ -1959,11 +1832,11 @@ *---------------------------------------------------------------------- */ static char * TraceVarProc( - ClientData clientData, /* Information about the variable trace. */ + void *clientData, /* Information about the variable trace. */ Tcl_Interp *interp, /* Interpreter containing variable. */ const char *name1, /* Name of variable or array. */ const char *name2, /* Name of element within array; NULL means * scalar variable is being referenced. */ int flags) /* OR-ed bits giving operation and other @@ -1974,14 +1847,14 @@ int code, destroy = 0; Tcl_DString cmd; int rewind = ((Interp *)interp)->execEnvPtr->rewind; /* - * We might call Tcl_EvalEx() below, and that might evaluate [trace vdelete] - * which might try to free tvarPtr. We want to use tvarPtr until the end - * of this function, so we use Tcl_Preserve() and Tcl_Release() to be sure - * it is not freed while we still need it. + * We might call Tcl_EvalEx() below, and that might evaluate + * [trace remove variable] which might try to free tvarPtr. We want to + * use tvarPtr until the end of this function, so we use Tcl_Preserve() + * and Tcl_Release() to be sure it is not freed while we still need it. */ result = NULL; if ((tvarPtr->flags & flags) && !Tcl_InterpDeleted(interp) && !Tcl_LimitExceeded(interp)) { @@ -1993,35 +1866,19 @@ 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. * @@ -2068,11 +1925,11 @@ } /* *---------------------------------------------------------------------- * - * Tcl_CreateObjTrace -- + * Tcl_CreateObjTrace/Tcl_CreateObjTrace2 -- * * Arrange for a function to be called to trace command execution. * * Results: * The return value is a token for the trace, which may be passed to @@ -2081,11 +1938,11 @@ * Side effects: * From now on, proc will be called just before a command function is * called to execute a Tcl command. Calls to proc will have the following * form: * - * void proc(ClientData clientData, + * void proc(void * clientData, * Tcl_Interp * interp, * int level, * const char * command, * Tcl_Command commandInfo, * int objc, @@ -2098,14 +1955,10 @@ * 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, @@ -2123,18 +1976,69 @@ * When the trace is deleted, the 'delProc' function will be invoked, * passing it the original client data. * *---------------------------------------------------------------------- */ + +typedef struct { + Tcl_CmdObjTraceProc *proc; + Tcl_CmdObjTraceDeleteProc *delProc; + void *clientData; +} TraceWrapperInfo; + +static int traceWrapperProc( + void *clientData, + Tcl_Interp *interp, + Tcl_Size level, + const char *command, + Tcl_Command commandInfo, + Tcl_Size objc, + Tcl_Obj *const objv[]) +{ + TraceWrapperInfo *info = (TraceWrapperInfo *)clientData; + if (objc > INT_MAX) { + objc = -1; /* Signal Tcl_CmdObjTraceProc that objc is out of range */ + } + return info->proc(info->clientData, interp, (int)level, command, commandInfo, objc, objv); +} + +static void traceWrapperDelProc(void *clientData) +{ + TraceWrapperInfo *info = (TraceWrapperInfo *)clientData; + clientData = info->clientData; + if (info->delProc) { + info->delProc(clientData); + } + Tcl_Free(info); +} Tcl_Trace Tcl_CreateObjTrace( Tcl_Interp *interp, /* Tcl interpreter */ - int level, /* Maximum nesting level */ + Tcl_Size level, /* Maximum nesting level */ int flags, /* Flags, see above */ Tcl_CmdObjTraceProc *proc, /* Trace callback */ - ClientData clientData, /* Client data for the callback */ + void *clientData, /* Client data for the callback */ + Tcl_CmdObjTraceDeleteProc *delProc) + /* Function to call when trace is deleted */ +{ + TraceWrapperInfo *info = (TraceWrapperInfo *)Tcl_Alloc(sizeof(TraceWrapperInfo)); + info->proc = proc; + info->delProc = delProc; + info->clientData = clientData; + return Tcl_CreateObjTrace2(interp, level, flags, + (proc ? traceWrapperProc : NULL), + info, traceWrapperDelProc); +} + +Tcl_Trace +Tcl_CreateObjTrace2( + Tcl_Interp *interp, /* Tcl interpreter */ + Tcl_Size level, /* Maximum nesting level */ + int flags, /* Flags, see above */ + Tcl_CmdObjTraceProc2 *proc, /* Trace callback */ + void *clientData, /* Client data for the callback */ Tcl_CmdObjTraceDeleteProc *delProc) /* Function to call when trace is deleted */ { Trace *tracePtr; Interp *iPtr = (Interp *) interp; @@ -2190,16 +2094,16 @@ * form: * * void * proc(clientData, interp, level, command, cmdProc, cmdClientData, * argc, argv) - * ClientData clientData; + * void *clientData; * Tcl_Interp *interp; * int level; * char *command; * int (*cmdProc)(); - * ClientData cmdClientData; + * void *cmdClientData; * int argc; * char **argv; * { * } * @@ -2216,21 +2120,21 @@ */ Tcl_Trace Tcl_CreateTrace( Tcl_Interp *interp, /* Interpreter in which to create trace. */ - int level, /* Only call proc for commands at nesting + Tcl_Size level, /* Only call proc for commands at nesting * level<=argument level (1=>top level). */ Tcl_CmdTraceProc *proc, /* Function to call before executing each * command. */ - ClientData clientData) /* Arbitrary value word to pass to proc. */ + void *clientData) /* Arbitrary value word to pass to proc. */ { StringTraceData *data = (StringTraceData *)Tcl_Alloc(sizeof(StringTraceData)); data->clientData = clientData; data->proc = proc; - return Tcl_CreateObjTrace(interp, level, 0, StringTraceProc, + return Tcl_CreateObjTrace2(interp, level, 0, StringTraceProc, data, StringTraceDeleteProc); } /* *---------------------------------------------------------------------- @@ -2248,22 +2152,22 @@ *---------------------------------------------------------------------- */ static int StringTraceProc( - ClientData clientData, + void *clientData, Tcl_Interp *interp, - int level, + Tcl_Size level, const char *command, Tcl_Command commandInfo, - int objc, + Tcl_Size objc, Tcl_Obj *const *objv) { StringTraceData *data = (StringTraceData *)clientData; Command *cmdPtr = (Command *) commandInfo; const char **argv; /* Args to pass to string trace proc */ - int i; + Tcl_Size i; /* * This is a bit messy because we have to emulate the old trace interface, * which uses strings for everything. */ @@ -2304,11 +2208,11 @@ *---------------------------------------------------------------------- */ static void StringTraceDeleteProc( - ClientData clientData) + void *clientData) { Tcl_Free(clientData); } /* @@ -2584,10 +2488,11 @@ 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. */ @@ -2634,10 +2539,24 @@ } 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. */ @@ -2755,17 +2674,17 @@ } Tcl_AddErrorInfo((Tcl_Interp *)iPtr, ""); Tcl_AppendObjToErrorInfo((Tcl_Interp *)iPtr, Tcl_ObjPrintf( "\n (%s trace on \"%s%s%s%s\")", type, part1, - (part2 ? "(" : ""), (part2 ? part2 : ""), - (part2 ? ")" : "") )); + (element ? "(" : ""), (element ? element : ""), + (element ? ")" : "") )); if (disposeFlags & TCL_TRACE_RESULT_OBJECT) { - TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb, + TclVarErrMsg((Tcl_Interp *) iPtr, part1, element, verb, TclGetString((Tcl_Obj *) result)); } else { - TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb, result); + TclVarErrMsg((Tcl_Interp *) iPtr, part1, element, verb, result); } iPtr->flags &= ~(ERR_ALREADY_LOGGED); Tcl_DiscardInterpState(state); } else { Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state); @@ -2852,12 +2771,12 @@ * as-a-whole. */ int flags, /* OR-ed collection of bits describing current * trace, including any of TCL_TRACE_READS, * TCL_TRACE_WRITES, TCL_TRACE_UNSETS, * TCL_GLOBAL_ONLY, and TCL_NAMESPACE_ONLY. */ - Tcl_VarTraceProc *proc, /* Function assocated with trace. */ - ClientData clientData) /* Arbitrary argument to pass to proc. */ + Tcl_VarTraceProc *proc, /* Function associated with trace. */ + void *clientData) /* Arbitrary argument to pass to proc. */ { VarTrace *tracePtr; VarTrace *prevPtr, *nextPtr; Var *varPtr, *arrayPtr; Interp *iPtr = (Interp *) interp; @@ -2882,13 +2801,10 @@ * 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) { @@ -2971,21 +2887,21 @@ * None. * *---------------------------------------------------------------------- */ -ClientData +void * Tcl_VarTraceInfo2( Tcl_Interp *interp, /* Interpreter containing variable. */ const char *part1, /* Name of variable or array. */ const char *part2, /* Name of element within array; NULL means * trace applies to scalar variable or array * as-a-whole. */ int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY. */ - Tcl_VarTraceProc *proc, /* Function assocated with trace. */ - ClientData prevClientData) /* If non-NULL, gives last value returned by + Tcl_VarTraceProc *proc, /* Function associated with trace. */ + void *prevClientData) /* If non-NULL, gives last value returned by * this function, so this call will return the * next trace after that one. If NULL, this * call will return the first trace. */ { Interp *iPtr = (Interp *) interp; @@ -3038,11 +2954,11 @@ * Results: * A standard Tcl return value. * * Side effects: * A trace is set up on the variable given by part1 and part2, such that - * future references to the variable will be intermediated by proc. See + * future references to the variable will be mediated by proc. See * the manual entry for complete details on the calling sequence for * proc. The variable's flags are updated. * *---------------------------------------------------------------------- */ @@ -3059,11 +2975,11 @@ * TCL_TRACE_READS, TCL_TRACE_WRITES, * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY, and * TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc, /* Function to call when specified ops are * invoked upon varName. */ - ClientData clientData) /* Arbitrary argument to pass to proc. */ + void *clientData) /* Arbitrary argument to pass to proc. */ { VarTrace *tracePtr; int result; tracePtr = (VarTrace *)Tcl_Alloc(sizeof(VarTrace)); @@ -3091,11 +3007,11 @@ * Results: * A standard Tcl return value. * * Side effects: * A trace is set up on the variable given by part1 and part2, such that - * future references to the variable will be intermediated by the + * future references to the variable will be mediated by the * traceProc listed in tracePtr. See the manual entry for complete * details on the calling sequence for proc. * *---------------------------------------------------------------------- */ @@ -3149,13 +3065,10 @@ * 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; Index: generic/tclUniData.c ================================================================== --- generic/tclUniData.c +++ generic/tclUniData.c @@ -3,11 +3,11 @@ * * Declarations of Unicode character information tables. This file is * automatically generated by the tools/uniParse.tcl script. Do not * modify this file by hand. * - * Copyright (c) 1998 by Scriptics Corporation. + * Copyright © 1998 Scriptics Corporation. * All rights reserved. */ /* * A 16-bit Unicode character is split into two parts in order to index @@ -27,39 +27,39 @@ 0, 32, 64, 96, 0, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 224, 480, 512, 544, 576, 608, 640, 672, 704, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 224, 1024, 224, 1056, 224, 224, 1088, 1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1344, 1344, 1440, 1472, 1504, 1536, 1568, 1344, 1344, 1600, 1632, 1664, 1696, 1728, - 1760, 1792, 1824, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080, 2112, - 2144, 2176, 2208, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, 2496, - 2528, 2560, 2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848, 2880, - 2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 3232, 3264, - 3296, 1824, 3328, 3360, 3392, 1824, 3424, 3456, 3488, 3520, 3552, 3584, - 3616, 1824, 1344, 3648, 3680, 3712, 3744, 3776, 3808, 3840, 1344, 1344, + 1760, 1792, 1824, 1344, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080, + 2112, 2144, 2176, 2208, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, + 2496, 2528, 2560, 2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848, + 2880, 2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 3232, + 3264, 3296, 3328, 3360, 3392, 3296, 3424, 3456, 3488, 3520, 3552, 3584, + 3616, 3296, 1344, 3648, 3680, 3712, 3744, 3776, 3808, 3840, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 3872, 1344, 3904, 3936, 3968, 1344, 4000, 1344, 4032, 4064, 4096, 4128, 4128, 4160, 4192, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 4224, 4256, 1344, 1344, 4288, 4320, 4352, 4384, 4416, 1344, 4448, 4480, 4512, 4544, 1344, 4576, 4608, 4640, 4672, 1344, 4704, 4736, 4768, 4800, 4832, 1344, 4864, 4896, 4928, 4960, 1344, - 4992, 5024, 5056, 5088, 5120, 1824, 5152, 5184, 5216, 5248, 5280, 5312, + 4992, 5024, 5056, 5088, 5120, 3296, 5152, 5184, 5216, 5248, 5280, 5312, 1344, 5344, 1344, 5376, 5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632, - 5664, 5696, 5728, 5664, 704, 5760, 224, 224, 224, 224, 5792, 224, 224, - 224, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, 6144, - 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432, 6464, 6496, 6528, - 6560, 6592, 6592, 6592, 6592, 6592, 6592, 6592, 6592, 6624, 6656, 4928, - 6688, 6720, 6752, 6784, 6816, 4928, 6848, 6880, 6912, 6944, 6976, 7008, - 7040, 4928, 4928, 4928, 4928, 4928, 7072, 7104, 7136, 4928, 4928, 4928, - 7168, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 7200, 7232, 4928, 7264, - 7296, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 6592, 6592, 6592, - 6592, 7328, 6592, 7360, 7392, 6592, 6592, 6592, 6592, 6592, 6592, 6592, - 6592, 4928, 7424, 7456, 7488, 7520, 4928, 4928, 4928, 7552, 7584, 7616, - 7648, 224, 224, 224, 7680, 7712, 7744, 1344, 7776, 7808, 7840, 7840, - 704, 7872, 7904, 7936, 1824, 7968, 4928, 4928, 8000, 4928, 4928, 4928, - 4928, 4928, 4928, 8032, 8064, 8096, 8128, 3232, 1344, 8160, 4192, 1344, - 8192, 8224, 8256, 1344, 1344, 8288, 1344, 4928, 8320, 8352, 8384, 8416, - 4928, 8384, 8448, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, + 5664, 5696, 5728, 5664, 704, 704, 224, 224, 224, 224, 5760, 224, 224, + 224, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, + 6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432, 6464, 6496, + 6528, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6592, 6624, 4928, + 6656, 6688, 6720, 6752, 6784, 4928, 6816, 6848, 6880, 6912, 6944, 6976, + 7008, 4928, 4928, 4928, 4928, 4928, 7040, 7072, 7104, 4928, 4928, 4928, + 7136, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 7168, 7200, 4928, 7232, + 7264, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 6560, 6560, 6560, + 6560, 7296, 6560, 7328, 7360, 6560, 6560, 6560, 6560, 6560, 6560, 6560, + 6560, 4928, 7392, 7424, 7456, 7488, 4928, 4928, 4928, 7520, 7552, 7584, + 7616, 224, 224, 224, 7648, 7680, 7712, 1344, 7744, 7776, 7808, 7808, + 704, 7840, 7872, 7904, 3296, 7936, 4928, 4928, 7968, 4928, 4928, 4928, + 4928, 4928, 4928, 8000, 8032, 8064, 8096, 3200, 1344, 8128, 4192, 1344, + 8160, 8192, 8224, 1344, 1344, 8256, 1344, 4928, 8288, 8320, 8352, 8384, + 4928, 8352, 8416, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -128,19 +128,19 @@ 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 8480, 8512, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 8448, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 8544, 4928, 8576, 5440, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 8608, 8640, 224, 8672, 8704, 1344, 1344, 8736, 8768, 8800, 224, - 8832, 8864, 8896, 8928, 8960, 8992, 9024, 1344, 9056, 9088, 9120, 9152, - 9184, 1632, 9216, 9248, 8480, 1952, 9280, 9312, 9344, 1344, 9376, 9408, - 9440, 1344, 9472, 9504, 9536, 9568, 9600, 9632, 9664, 9696, 9696, 1344, - 9728, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 8480, 4928, 8512, 5440, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 8544, 8576, 224, 8608, 8640, 1344, 1344, 8672, 8704, 8736, 224, + 8768, 8800, 8832, 8864, 8896, 8928, 8960, 1344, 8992, 9024, 9056, 9088, + 9120, 1632, 9152, 9184, 9216, 1920, 9248, 9280, 9312, 1344, 9344, 9376, + 9408, 1344, 9440, 9472, 9504, 9536, 9568, 9600, 9632, 9664, 9664, 1344, + 9696, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -165,216 +165,401 @@ 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 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, + 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, 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 + 9856, 9856, 9856, 9856, 9856, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 1344, 9888, 1344, 1344, 9920, 3296, 9952, 9984, 10016, + 1344, 1344, 10048, 10080, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 10112, 10144, 1344, 10176, 1344, 10208, 10240, 10272, + 10304, 10336, 10368, 1344, 1344, 1344, 10400, 10432, 64, 10464, 10496, + 10528, 4736, 10560, 10592 #if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6 - ,10656, 10688, 10720, 1824, 1344, 1344, 1344, 10752, 10784, 10816, - 10848, 10880, 10912, 10944, 10976, 11008, 1824, 1824, 1824, 1824, 8480, - 1344, 11040, 11072, 1344, 11104, 11136, 11168, 11200, 1344, 11232, - 1824, 11264, 11296, 11328, 1344, 11360, 11392, 11424, 11456, 1344, - 11488, 1344, 11520, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 7808, 4704, 10240, 1824, 1824, 1824, - 1824, 11552, 11584, 11616, 11648, 4736, 11680, 1824, 11712, 11744, - 11776, 1824, 1824, 1344, 11808, 11840, 6912, 11872, 11904, 11936, 11968, - 12000, 1824, 12032, 12064, 1344, 12096, 12128, 12160, 12192, 12224, - 1824, 1824, 1344, 1344, 12256, 1824, 12288, 12320, 12352, 12384, 1344, - 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, + ,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, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 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, + 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, 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, + 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, @@ -381,184 +566,11 @@ 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 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 + 15488 #endif /* TCL_UTF_MAX > 3 */ }; /* * The groupMap is indexed by combining the alternate page number with @@ -643,11 +655,11 @@ 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, + 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, @@ -669,397 +681,394 @@ 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, + 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, - 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, + 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, 0, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 93, 15, 125, 93, - 125, 125, 125, 125, 125, 0, 93, 125, 125, 0, 125, 125, 93, 93, 0, 0, - 0, 0, 0, 0, 0, 125, 125, 0, 0, 0, 0, 0, 0, 0, 15, 0, 15, 15, 93, 93, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 93, 93, 125, 125, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 93, 93, 15, 125, 125, - 125, 93, 93, 93, 93, 0, 125, 125, 125, 0, 125, 125, 125, 93, 15, 14, - 0, 0, 0, 0, 15, 15, 15, 125, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, - 93, 93, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 14, 15, 15, 15, 15, 15, 15, 0, 93, 125, 125, 0, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, - 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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, 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, + 15, 15, 15, 15, 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, 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, + 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, 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, + 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, - 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, + 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, 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, + 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, - 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, + 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, 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, + 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, 21, 21, 21, 21, 21, 21, 21, 92, 92, 92, 92, 92, + 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, - 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, + 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, @@ -1070,107 +1079,109 @@ 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, + 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, 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, + 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, 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, + 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, 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, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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, + 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, 201, 201, 201, 201, 201, 201, + 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, 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 + 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, @@ -1186,419 +1197,463 @@ 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, 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, 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, + 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, 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, + 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, 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, 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, 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, + 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, 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, + 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, 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 + 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 @@ -1640,15 +1695,15 @@ -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 + 18, 17, 10305, 10370, 10049, 10114, 8769, 8834 }; #if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6 -# define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1FFFFF) >= 0x31360) +# define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1FFFFF) >= 0x323C0) #else # define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1F0000) != 0) #endif /* Index: generic/tclUtf.c ================================================================== --- generic/tclUtf.c +++ generic/tclUtf.c @@ -1,11 +1,11 @@ /* * tclUtf.c -- * * Routines for manipulating UTF-8 strings. * - * Copyright (c) 1997-1998 Sun Microsystems, Inc. + * Copyright © 1997-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -62,24 +62,16 @@ 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" */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,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, -#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 + 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, @@ -86,19 +78,13 @@ /* 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 + 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); @@ -117,11 +103,11 @@ * None. * *--------------------------------------------------------------------------- */ -size_t +int TclUtfCount( int ch) /* The Unicode character whose size is returned. */ { if ((unsigned)(ch - 1) < (UNICODE_SELF - 1)) { return 1; @@ -194,103 +180,117 @@ /* *--------------------------------------------------------------------------- * * 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. + * 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: - * The return values is the number of bytes in the buffer that were - * consumed. + * Returns the number of bytes stored into the buffer. * * Side effects: * None. * *--------------------------------------------------------------------------- */ -int +#undef Tcl_UniCharToUtf +Tcl_Size 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). */ + 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) ((ch | 0x80) & 0xBF); - buf[0] = (char) ((ch >> 6) | 0xC0); + buf[1] = (char) (0x80 | (0x3F & ch)); + buf[0] = (char) (0xC0 | (ch >> 6)); return 2; } if (ch <= 0xFFFF) { - if ((ch & 0xF800) == 0xD800) { + if ( + (flags & TCL_COMBINE) && + ((ch & 0xF800) == 0xD800)) { if (ch & 0x0400) { /* Low surrogate */ - if (((buf[0] & 0xC0) == 0x80) && ((buf[1] & 0xCF) == 0)) { + if ( (0x80 == (0xC0 & buf[0])) + && (0 == (0xCF & buf[1]))) { /* Previous Tcl_UniChar was a high surrogate, so combine */ - buf[2] = (char) ((ch & 0x3F) | 0x80); - buf[1] |= (char) (((ch >> 6) & 0x0F) | 0x80); + buf[2] = (char) (0x80 | (0x3F & ch)); + buf[1] |= (char) (0x80 | (0x0F & (ch >> 6))); return 3; } /* Previous Tcl_UniChar was not a high surrogate, so just output */ } else { /* High surrogate */ + + /* Add 0x10000 to the raw number encoded in the surrogate + * pair in order to get the code point. + */ ch += 0x40; + /* Fill buffer with specific 3-byte (invalid) byte combination, so following low surrogate can recognize it and combine */ buf[2] = (char) ((ch << 4) & 0x30); - buf[1] = (char) (((ch >> 2) & 0x3F) | 0x80); - buf[0] = (char) (((ch >> 8) & 0x07) | 0xF0); + buf[1] = (char) (0x80 | (0x3F & (ch >> 2))); + buf[0] = (char) (0xF0 | (0x07 & (ch >> 8))); return 1; } } goto three; } if (ch <= 0x10FFFF) { - buf[3] = (char) ((ch | 0x80) & 0xBF); - buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF); - buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF); - buf[0] = (char) ((ch >> 18) | 0xF0); + buf[3] = (char) (0x80 | (0x3F & ch)); + buf[2] = (char) (0x80 | (0x3F & (ch >> 6))); + buf[1] = (char) (0x80 | (0x3F & (ch >> 12))); + buf[0] = (char) (0xF0 | (ch >> 18)); return 4; } } else if (ch == -1) { - if (((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); + 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) ((ch | 0x80) & 0xBF); - buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF); - buf[0] = (char) ((ch >> 12) | 0xE0); + buf[2] = (char) (0x80 | (0x3F & ch)); + buf[1] = (char) (0x80 | (0x3F & (ch >> 6))); + buf[0] = (char) (0xE0 | (ch >> 12)); return 3; } /* *--------------------------------------------------------------------------- @@ -312,26 +312,27 @@ #undef Tcl_UniCharToUtfDString char * Tcl_UniCharToUtfDString( const int *uniStr, /* Unicode string to convert to UTF-8. */ - size_t uniLength, /* Length of Unicode string. */ + Tcl_Size uniLength, /* Length of Unicode string. Negative for nul + * nul terminated string */ Tcl_DString *dsPtr) /* UTF-8 representation of string is appended * to this previously initialized DString. */ { const int *w, *wEnd; char *p, *string; - size_t oldLength; + Tcl_Size oldLength; /* * UTF-8 string length in bytes will be <= Unicode string length * 4. */ if (uniStr == NULL) { return NULL; } - if (uniLength == TCL_INDEX_NONE) { + if (uniLength < 0) { uniLength = 0; w = uniStr; while (*w != '\0') { uniLength++; w++; @@ -341,10 +342,11 @@ 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)); @@ -353,11 +355,11 @@ } char * Tcl_Char16ToUtfDString( const unsigned short *uniStr,/* Utf-16 string to convert to UTF-8. */ - size_t uniLength, /* Length of Utf-16 string. */ + Tcl_Size uniLength, /* Length of Utf-16 string. */ Tcl_DString *dsPtr) /* UTF-8 representation of string is appended * to this previously initialized DString. */ { const unsigned short *w, *wEnd; char *p, *string; @@ -369,11 +371,11 @@ */ if (uniStr == NULL) { return NULL; } - if (uniLength == TCL_INDEX_NONE) { + if (uniLength < 0) { uniLength = 0; w = uniStr; while (*w != '\0') { uniLength++; @@ -384,16 +386,17 @@ Tcl_DStringSetLength(dsPtr, oldLength + (uniLength + 1) * 3); string = Tcl_DStringValue(dsPtr) + oldLength; p = string; wEnd = uniStr + uniLength; + for (w = uniStr; w < wEnd; ) { if (!len && ((*w & 0xFC00) != 0xDC00)) { /* Special case for handling high surrogates. */ p += Tcl_UniCharToUtf(-1, p); } - len = Tcl_UniCharToUtf(*w, p); + len = Tcl_UniCharToUtf(*w | TCL_COMBINE, p); p += len; if ((*w >= 0xD800) && (len < 3)) { len = 0; /* Indication that high surrogate was found */ } w++; @@ -420,19 +423,10 @@ * 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: @@ -447,11 +441,11 @@ 0x90, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x2DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x9D, 0x017E, 0x0178 }; #undef Tcl_UtfToUniChar -int +Tcl_Size Tcl_UtfToUniChar( const char *src, /* The UTF-8 string. */ int *chPtr)/* Filled with the Unicode character represented by * the UTF-8 string. */ { @@ -476,11 +470,11 @@ } else { *chPtr = byte; } return 1; } else if (byte < 0xE0) { - if ((src[1] & 0xC0) == 0x80) { + if ((byte != 0xC1) && ((src[1] & 0xC0) == 0x80)) { /* * Two-byte-character lead-byte followed by a trail-byte. */ *chPtr = (((byte & 0x1F) << 6) | (src[1] & 0x3F)); @@ -508,12 +502,11 @@ /* * A three-byte-character lead-byte not followed by two trail-bytes * represents itself. */ - } - else if (byte < 0xF5) { + } else if (byte < 0xF5) { if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80) && ((src[3] & 0xC0) == 0x80)) { /* * Four-byte-character lead byte followed by three trail bytes. */ *chPtr = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12) @@ -531,11 +524,11 @@ *chPtr = byte; return 1; } -int +Tcl_Size Tcl_UtfToChar16( const char *src, /* The UTF-8 string. */ unsigned short *chPtr)/* Filled with the Tcl_UniChar represented by * the UTF-8 string. This could be a surrogate too. */ { @@ -572,11 +565,11 @@ } else { *chPtr = byte; } return 1; } else if (byte < 0xE0) { - if ((src[1] & 0xC0) == 0x80) { + if ((byte != 0xC1) && ((src[1] & 0xC0) == 0x80)) { /* * Two-byte-character lead-byte followed by a trail-byte. */ *chPtr = (((byte & 0x1F) << 6) | (src[1] & 0x3F)); @@ -604,12 +597,11 @@ /* * A three-byte-character lead-byte not followed by two trail-bytes * represents itself. */ - } - else if (byte < 0xF5) { + } else if (byte < 0xF5) { if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80)) { /* * Four-byte-character lead byte followed by at least two trail bytes. * We don't test the validity of 3th trail byte, see [ed29806ba] */ @@ -653,28 +645,28 @@ #undef Tcl_UtfToUniCharDString int * Tcl_UtfToUniCharDString( const char *src, /* UTF-8 string to convert to Unicode. */ - size_t length, /* Length of UTF-8 string in bytes, or -1 for + Tcl_Size length, /* Length of UTF-8 string in bytes, or -1 for * strlen(). */ Tcl_DString *dsPtr) /* Unicode representation of string is * appended to this previously initialized * DString. */ { int ch = 0, *w, *wString; const char *p; - size_t oldLength; + Tcl_Size oldLength; /* Pointer to the end of string. Never read endPtr[0] */ const char *endPtr = src + length; /* Pointer to last byte where optimization still can be used */ const char *optPtr = endPtr - TCL_UTF_MAX; if (src == NULL) { return NULL; } - if (length == TCL_INDEX_NONE) { + if (length < 0) { length = strlen(src); } /* * Unicode string length in Tcl_UniChars will be <= UTF-8 string length in @@ -690,15 +682,15 @@ w = wString; p = src; endPtr = src + length; optPtr = endPtr - 4; while (p <= optPtr) { - p += TclUtfToUCS4(p, &ch); + p += Tcl_UtfToUniChar(p, &ch); *w++ = ch; } - while ((p < endPtr) && TclUCS4Complete(p, endPtr-p)) { - p += TclUtfToUCS4(p, &ch); + while ((p < endPtr) && Tcl_UtfCharComplete(p, endPtr-p)) { + p += Tcl_UtfToUniChar(p, &ch); *w++ = ch; } while (p < endPtr) { *w++ = UCHAR(*p++); } @@ -710,28 +702,28 @@ } unsigned short * Tcl_UtfToChar16DString( const char *src, /* UTF-8 string to convert to Unicode. */ - size_t length, /* Length of UTF-8 string in bytes, or -1 for + Tcl_Size length, /* Length of UTF-8 string in bytes, or -1 for * strlen(). */ Tcl_DString *dsPtr) /* Unicode representation of string is * appended to this previously initialized * DString. */ { unsigned short ch = 0, *w, *wString; const char *p; - size_t oldLength; + Tcl_Size oldLength; /* Pointer to the end of string. Never read endPtr[0] */ const char *endPtr = src + length; /* Pointer to last byte where optimization still can be used */ const char *optPtr = endPtr - TCL_UTF_MAX; if (src == NULL) { return NULL; } - if (length == TCL_INDEX_NONE) { + if (length < 0) { length = strlen(src); } /* * Unicode string length in WCHARs will be <= UTF-8 string length in @@ -751,11 +743,11 @@ while (p <= optPtr) { p += Tcl_UtfToChar16(p, &ch); *w++ = ch; } while (p < endPtr) { - if (TclChar16Complete(p, endPtr-p)) { + if (Tcl_UtfCharComplete(p, endPtr-p)) { p += Tcl_UtfToChar16(p, &ch); *w++ = ch; } else { *w++ = UCHAR(*p++); } @@ -788,11 +780,11 @@ int Tcl_UtfCharComplete( const char *src, /* String to check if first few bytes contain * a complete UTF-8 character. */ - size_t length) /* Length of above string in bytes. */ + Tcl_Size length) /* Length of above string in bytes. */ { return length >= complete[UCHAR(*src)]; } /* @@ -811,20 +803,20 @@ * None. * *--------------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_NumUtfChars( const char *src, /* The UTF-8 string to measure. */ - size_t length) /* The length of the string in bytes, or - * TCL_INDEX_NONE for strlen(src). */ + Tcl_Size length) /* The length of the string in bytes, or + * negative value for strlen(src). */ { Tcl_UniChar ch = 0; - size_t i = 0; + Tcl_Size i = 0; - if (length == TCL_INDEX_NONE) { + if (length < 0) { /* string is NUL-terminated, so TclUtfToUniChar calls are safe. */ while (*src != '\0') { src += TclUtfToUniChar(src, &ch); i++; } @@ -832,11 +824,11 @@ /* Will return value between 0 and length. No overflow checks. */ /* Pointer to the end of string. Never read endPtr[0] */ const char *endPtr = src + length; /* Pointer to last byte where optimization still can be used */ - const char *optPtr = endPtr - TCL_UTF_MAX; + const char *optPtr = endPtr - 4; /* * Optimize away the call in this loop. Justified because... * when (src <= optPtr), (endPtr - src) >= (endPtr - optPtr) * By initialization above (endPtr - optPtr) = TCL_UTF_MAX @@ -863,10 +855,62 @@ } } 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 -- * @@ -888,11 +932,11 @@ Tcl_UtfFindFirst( const char *src, /* The UTF-8 string to be searched. */ int ch) /* The Unicode character to search for. */ { while (1) { - int find, len = TclUtfToUCS4(src, &find); + int find, len = Tcl_UtfToUniChar(src, &find); if (find == ch) { return src; } if (*src == '\0') { @@ -927,11 +971,11 @@ int ch) /* The Unicode character to search for. */ { const char *last = NULL; while (1) { - int find, len = TclUtfToUCS4(src, &find); + int find, len = Tcl_UtfToUniChar(src, &find); if (find == ch) { last = src; } if (*src == '\0') { @@ -969,10 +1013,14 @@ { size_t 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; } @@ -1063,11 +1111,11 @@ * anything. From what we know, this non-trail byte * is a prefix of a previous character, and accepting * it (the fallback) is correct. */ - || (trailBytesSeen >= complete[byte])) { + || (trailBytesSeen >= totalBytes[byte])) { /* * That is, (1 + trailBytesSeen > needed). * We've examined more bytes than needed to complete * this lead byte. No matter about well-formedness or * validity, the sequence starting with this lead byte @@ -1104,23 +1152,18 @@ return fallback; } /* Continue the search backwards... */ look--; - } while (trailBytesSeen < TCL_UTF_MAX); + } while (trailBytesSeen < 4); /* - * We've seen TCL_UTF_MAX trail bytes, so we know there will not be a + * We've seen 4 trail bytes, so we know there will not be a * properly formed byte sequence to find, and we can stop looking, - * accepting the fallback (for TCL_UTF_MAX > 3) or just go back as - * far as we can. + * accepting the fallback. */ -#if TCL_UTF_MAX > 3 return fallback; -#else - return src - TCL_UTF_MAX; -#endif } /* *--------------------------------------------------------------------------- * @@ -1139,41 +1182,33 @@ */ int Tcl_UniCharAtIndex( const char *src, /* The UTF-8 string to dereference. */ - size_t index) /* The position of the desired character. */ + Tcl_Size index) /* The position of the desired character. */ { Tcl_UniChar ch = 0; int i = 0; - if (index == TCL_INDEX_NONE) { + if (index < 0) { return -1; } while (index--) { i = TclUtfToUniChar(src, &ch); src += i; } -#if TCL_UTF_MAX <= 3 - if ((ch >= 0xD800) && (i < 3)) { - /* Index points at character following high Surrogate */ - return -1; - } -#endif - TclUtfToUCS4(src, &i); + Tcl_UtfToUniChar(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. + * the UTF-8 string. * * Results: * As above. * * Side effects: @@ -1183,35 +1218,43 @@ */ 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) { + Tcl_Size index) /* The position of the desired character. */ +{ + int ch = 0; + + if (index > 0) { + while (index--) { + /* Make use of the #undef Tcl_UtfToUniChar above, which already handles UCS4. */ + src += Tcl_UtfToUniChar(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--) { -#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 + 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 -- * @@ -1234,21 +1277,22 @@ * buffer overruns should occur. * *--------------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_UtfBackslash( const char *src, /* Points to the backslash character of a * backslash sequence. */ int *readPtr, /* Fill in with number of characters read from * src, unless NULL. */ char *dst) /* Filled with the bytes represented by the * backslash sequence. */ { #define LINE_LENGTH 128 - size_t numRead, result; + 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() @@ -1278,34 +1322,34 @@ * Writes a terminating null after the last converted character. * *---------------------------------------------------------------------- */ -int +Tcl_Size Tcl_UtfToUpper( char *str) /* String to convert in place. */ { int ch, upChar; char *src, *dst; - size_t len; + Tcl_Size len; /* * Iterate over the string until we hit the terminating null. */ src = dst = str; while (*src) { - len = TclUtfToUCS4(src, &ch); + len = Tcl_UtfToUniChar(src, &ch); upChar = Tcl_UniCharToUpper(ch); /* * To keep badly formed Utf strings from getting inflated by the * conversion (thereby causing a segfault), only copy the upper case * char to dst if its size is <= the original char. */ - if ((len < TclUtfCount(upChar)) || ((upChar & ~0x7FF) == 0xD800)) { + if (len < TclUtfCount(upChar)) { memmove(dst, src, len); dst += len; } else { dst += Tcl_UniCharToUtf(upChar, dst); } @@ -1331,34 +1375,34 @@ * Writes a terminating null after the last converted character. * *---------------------------------------------------------------------- */ -int +Tcl_Size Tcl_UtfToLower( char *str) /* String to convert in place. */ { int ch, lowChar; char *src, *dst; - size_t len; + Tcl_Size len; /* * Iterate over the string until we hit the terminating null. */ src = dst = str; while (*src) { - len = TclUtfToUCS4(src, &ch); + len = Tcl_UtfToUniChar(src, &ch); lowChar = Tcl_UniCharToLower(ch); /* * To keep badly formed Utf strings from getting inflated by the * conversion (thereby causing a segfault), only copy the lower case * char to dst if its size is <= the original char. */ - if ((len < TclUtfCount(lowChar)) || ((lowChar & ~0x7FF) == 0xD800)) { + if (len < TclUtfCount(lowChar)) { memmove(dst, src, len); dst += len; } else { dst += Tcl_UniCharToUtf(lowChar, dst); } @@ -1385,46 +1429,46 @@ * Writes a terminating null after the last converted character. * *---------------------------------------------------------------------- */ -int +Tcl_Size Tcl_UtfToTitle( char *str) /* String to convert in place. */ { int ch, titleChar, lowChar; char *src, *dst; - size_t len; + Tcl_Size len; /* * Capitalize the first character and then lowercase the rest of the * characters until we get to a null. */ src = dst = str; if (*src) { - len = TclUtfToUCS4(src, &ch); + len = Tcl_UtfToUniChar(src, &ch); titleChar = Tcl_UniCharToTitle(ch); - if ((len < TclUtfCount(titleChar)) || ((titleChar & ~0x7FF) == 0xD800)) { + if (len < TclUtfCount(titleChar)) { memmove(dst, src, len); dst += len; } else { dst += Tcl_UniCharToUtf(titleChar, dst); } src += len; } while (*src) { - len = TclUtfToUCS4(src, &ch); + len = Tcl_UtfToUniChar(src, &ch); lowChar = ch; /* Special exception for Georgian Asomtavruli chars, no titlecase. */ if ((unsigned)(lowChar - 0x1C90) >= 0x30) { lowChar = Tcl_UniCharToLower(lowChar); } - if ((len < TclUtfCount(lowChar)) || ((lowChar & ~0x7FF) == 0xD800)) { + if (len < TclUtfCount(lowChar)) { memmove(dst, src, len); dst += len; } else { dst += Tcl_UniCharToUtf(lowChar, dst); } @@ -1520,20 +1564,10 @@ */ 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; } @@ -1571,20 +1605,10 @@ * 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); } @@ -1620,20 +1644,10 @@ 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); } @@ -1666,20 +1680,10 @@ 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; } @@ -1749,11 +1753,11 @@ } } /* Clear away extension bits, if any */ return ch & 0x1FFFFF; } - + /* *---------------------------------------------------------------------- * * Tcl_UniCharToTitle -- * @@ -1793,11 +1797,41 @@ } /* *---------------------------------------------------------------------- * - * TclUniCharLen -- + * 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: @@ -1807,15 +1841,16 @@ * None. * *---------------------------------------------------------------------- */ -size_t -TclUniCharLen( - const Tcl_UniChar *uniStr) /* Unicode string to find length of. */ +#undef Tcl_UniCharLen +Tcl_Size +Tcl_UniCharLen( + const int *uniStr) /* Unicode string to find length of. */ { - size_t len = 0; + Tcl_Size len = 0; while (*uniStr != '\0') { len++; uniStr++; } @@ -1843,11 +1878,11 @@ 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 +#if defined(WORDS_BIGENDIAN) /* * We are definitely on a big-endian machine; memcmp() is safe */ return memcmp(ucs, uct, numChars*sizeof(Tcl_UniChar)); @@ -1886,11 +1921,11 @@ int TclUniCharNcasecmp( const Tcl_UniChar *ucs, /* Unicode string to compare to uct. */ const Tcl_UniChar *uct, /* Unicode string ucs is compared to. */ - size_t numChars) /* Number of unichars to compare. */ + size_t numChars) /* Number of Unichars to compare. */ { for ( ; numChars != 0; numChars--, ucs++, uct++) { if (*ucs != *uct) { Tcl_UniChar lcs = Tcl_UniCharToLower(*ucs); Tcl_UniChar lct = Tcl_UniCharToLower(*uct); @@ -2186,10 +2221,40 @@ } /* *---------------------------------------------------------------------- * + * Tcl_UniCharIsUnicode -- + * + * Test if a character is a Unicode character. + * + * Results: + * Returns non-zero if character belongs to the Unicode set. + * + * Excluded are: + * 1) All characters > U+10FFFF + * 2) Surrogates U+D800 - U+DFFF + * 3) Last 2 characters of each plane, so U+??FFFE and U+??FFFF + * 4) The characters in the range U+FDD0 - U+FDEF + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_UniCharIsUnicode( + int ch) /* Unicode character to test. */ +{ + return ((unsigned int)ch <= 0x10FFFF) && ((ch & 0xFFF800) != 0xD800) + && ((ch & 0xFFFE) != 0xFFFE) && ((unsigned int)(ch - 0xFDD0) >= 32); +} + +/* + *---------------------------------------------------------------------- + * * Tcl_UniCharIsWordChar -- * * Test if a character is alphanumeric or a connector punctuation mark. * * Results: @@ -2423,14 +2488,14 @@ */ int TclUniCharMatch( const Tcl_UniChar *string, /* Unicode String. */ - size_t strLen, /* Length of String */ + Tcl_Size strLen, /* Length of String */ const Tcl_UniChar *pattern, /* Pattern, which may contain special * characters. */ - size_t ptnLen, /* Length of Pattern */ + Tcl_Size ptnLen, /* Length of Pattern */ int nocase) /* 0 for case sensitive, 1 for insensitive */ { const Tcl_UniChar *stringEnd, *patternEnd; Tcl_UniChar p; @@ -2590,64 +2655,12 @@ 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: */ Index: generic/tclUtil.c ================================================================== --- generic/tclUtil.c +++ generic/tclUtil.c @@ -2,18 +2,19 @@ * tclUtil.c -- * * This file contains utility functions that are used by many Tcl * commands. * - * Copyright (c) 1987-1993 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. - * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. + * Copyright © 1987-1993 The Regents of the University of California. + * Copyright © 1994-1998 Sun Microsystems, Inc. + * Copyright © 2001 Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include #include "tclInt.h" #include "tclParse.h" #include "tclStringTrim.h" #include "tclTomMath.h" #include @@ -97,28 +98,28 @@ /* * Prototypes for functions defined later in this file. */ static void ClearHash(Tcl_HashTable *tablePtr); -static void FreeProcessGlobalValue(ClientData clientData); -static void FreeThreadHash(ClientData clientData); +static void FreeProcessGlobalValue(void *clientData); +static void FreeThreadHash(void *clientData); static int GetEndOffsetFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, - size_t endValue, Tcl_WideInt *indexPtr); + Tcl_WideInt endValue, Tcl_WideInt *indexPtr); static Tcl_HashTable * GetThreadHash(Tcl_ThreadDataKey *keyPtr); static int GetWideForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, - size_t endValue, Tcl_WideInt *widePtr); + Tcl_WideInt endValue, Tcl_WideInt *widePtr); static int FindElement(Tcl_Interp *interp, const char *string, - int stringLength, const char *typeStr, + Tcl_Size stringLength, const char *typeStr, const char *typeCode, const char **elementPtr, - const char **nextPtr, size_t *sizePtr, + const char **nextPtr, Tcl_Size *sizePtr, int *literalPtr); /* * The following is the Tcl object type definition for an object that * represents a list index in the form, "end-offset". It is used as a * performance optimization in Tcl_GetIntForIndex. The internal rep is * stored directly in the wideValue, so no memory management is required - * for it. This is a caching intrep, keeping the result of a parse + * for it. This is a caching internalrep, keeping the result of a parse * around. This type is only created from a pre-existing string, so an * updateStringProc will never be called and need not exist. The type * is unregistered, so has no need of a setFromAnyProc either. */ @@ -125,13 +126,21 @@ static const Tcl_ObjType endOffsetType = { "end-offset", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ NULL, /* updateStringProc */ - NULL /* setFromAnyProc */ + NULL, /* setFromAnyProc */ + TCL_OBJTYPE_V1(TclLengthOne) }; +Tcl_Size +TclLengthOne( + TCL_UNUSED(Tcl_Obj *)) +{ + return 1; +} + /* * * STRING REPRESENTATION OF LISTS * * * * * The next several routines implement the conversions of strings to and from * Tcl lists. To understand their operation, the rules of parsing and @@ -366,14 +375,14 @@ * * TclMaxListLength -- * * Given 'bytes' pointing to 'numBytes' bytes, scan through them and * count the number of whitespace runs that could be list element - * separators. If 'numBytes' is -1, scan to the terminating '\0'. Not a - * full list parser. Typically used to get a quick and dirty overestimate - * of length size in order to allocate space for an actual list parser to - * operate with. + * separators. If 'numBytes' is TCL_INDEX_NONE, scan to the terminating + * '\0'. Not a full list parser. Typically used to get a quick and dirty + * overestimate of length size in order to allocate space for an actual + * list parser to operate with. * * Results: * Returns the largest number of list elements that could possibly be in * this string, interpreted as a Tcl list. If 'endPtr' is not NULL, * writes a pointer to the end of the string scanned there. @@ -382,17 +391,17 @@ * None. * *---------------------------------------------------------------------- */ -int +Tcl_Size TclMaxListLength( const char *bytes, - size_t numBytes, + Tcl_Size numBytes, const char **endPtr) { - size_t count = 0; + Tcl_Size count = 0; if ((numBytes == 0) || ((numBytes == TCL_INDEX_NONE) && (*bytes == '\0'))) { /* Empty string case - quick exit */ goto done; } @@ -491,17 +500,17 @@ * NULL, then no error message is left after * errors. */ const char *list, /* Points to the first byte of a string * containing a Tcl list with zero or more * elements (possibly in braces). */ - int listLength, /* Number of bytes in the list's string. */ + Tcl_Size listLength, /* Number of bytes in the list's string. */ const char **elementPtr, /* Where to put address of first significant * character in first element of list. */ const char **nextPtr, /* Fill in with location of character just * after all white space following end of * argument (next arg or end of list). */ - size_t *sizePtr, /* If non-zero, fill in with size of + Tcl_Size *sizePtr, /* If non-zero, fill in with size of * element. */ int *literalPtr) /* If non-zero, fill in with non-zero/zero to * indicate that the substring of *sizePtr * bytes starting at **elementPtr is/is not * the literal list element and therefore @@ -519,18 +528,18 @@ * errors. */ const char *dict, /* Points to the first byte of a string * containing a Tcl dictionary with zero or * more keys and values (possibly in * braces). */ - int dictLength, /* Number of bytes in the dict's string. */ + Tcl_Size dictLength, /* Number of bytes in the dict's string. */ const char **elementPtr, /* Where to put address of first significant * character in the first element (i.e., key * or value) of dict. */ const char **nextPtr, /* Fill in with location of character just * after all white space following end of * element (next arg or end of list). */ - size_t *sizePtr, /* If non-zero, fill in with size of + Tcl_Size *sizePtr, /* If non-zero, fill in with size of * element. */ int *literalPtr) /* If non-zero, fill in with non-zero/zero to * indicate that the substring of *sizePtr * bytes starting at **elementPtr is/is not * the literal key or value and therefore @@ -548,21 +557,21 @@ * errors. */ const char *string, /* Points to the first byte of a string * containing a Tcl list or dictionary with * zero or more elements (possibly in * braces). */ - int stringLength, /* Number of bytes in the string. */ + Tcl_Size stringLength, /* Number of bytes in the string. */ const char *typeStr, /* The name of the type of thing we are * parsing, for error messages. */ const char *typeCode, /* The type code for thing we are parsing, for * error messages. */ const char **elementPtr, /* Where to put address of first significant * character in first element. */ const char **nextPtr, /* Fill in with location of character just * after all white space following end of * argument (next arg or end of list/dict). */ - size_t *sizePtr, /* If non-zero, fill in with size of + Tcl_Size *sizePtr, /* If non-zero, fill in with size of * element. */ int *literalPtr) /* If non-zero, fill in with non-zero/zero to * indicate that the substring of *sizePtr * bytes starting at **elementPtr is/is not * the literal list/dict element and therefore @@ -570,14 +579,14 @@ * TclCopyAndCollapse() by the caller. */ { const char *p = string; const char *elemStart; /* Points to first byte of first element. */ const char *limit; /* Points just after list/dict's last byte. */ - int openBraces = 0; /* Brace nesting level during parse. */ + Tcl_Size openBraces = 0; /* Brace nesting level during parse. */ int inQuotes = 0; - int size = 0; - size_t numChars; + Tcl_Size size = 0; + Tcl_Size numChars; int literal = 1; const char *p2; /* * Skim off leading white space and check for an opening brace or quote. @@ -647,11 +656,11 @@ } 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); + (void *)NULL); } return TCL_ERROR; } break; @@ -699,11 +708,11 @@ } 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); + (void *)NULL); } return TCL_ERROR; } break; @@ -732,19 +741,19 @@ 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); + (void *)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); + (void *)NULL); } return TCL_ERROR; } size = (p - elemStart); } @@ -781,25 +790,27 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size TclCopyAndCollapse( - size_t count, /* Number of byte to copy from src. */ + Tcl_Size count, /* Number of byte to copy from src. */ const char *src, /* Copy from here... */ char *dst) /* ... to here. */ { - size_t newCount = 0; + Tcl_Size newCount = 0; while (count > 0) { char c = *src; if (c == '\\') { - size_t numRead; - size_t backslashCount = TclParseBackslash(src, count, &numRead, dst); + 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 { @@ -840,34 +851,35 @@ * Memory is allocated. * *---------------------------------------------------------------------- */ +#undef Tcl_SplitList int Tcl_SplitList( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, no error message is left. */ const char *list, /* Pointer to string with list structure. */ - int *argcPtr, /* Pointer to location to fill in with the + Tcl_Size *argcPtr, /* Pointer to location to fill in with the * number of elements in the list. */ const char ***argvPtr) /* Pointer to place to store pointer to array * of pointers to list elements. */ { const char **argv, *end, *element; char *p; - int length, size, i, result; - size_t elSize; + 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, -1, &end) + 1; + size = TclMaxListLength(list, TCL_INDEX_NONE, &end) + 1; length = end - list; argv = (const char **)Tcl_Alloc((size * sizeof(char *)) + length + 1); for (i = 0, p = ((char *) argv) + size*sizeof(char *); *list != 0; i++) { @@ -888,11 +900,11 @@ 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); + (void *)NULL); } return TCL_ERROR; } argv[i] = p; if (literal) { @@ -930,17 +942,17 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_ScanElement( const char *src, /* String to convert to list element. */ int *flagPtr) /* Where to store information to guide * Tcl_ConvertCountedElement. */ { - return Tcl_ScanCountedElement(src, -1, flagPtr); + return Tcl_ScanCountedElement(src, TCL_INDEX_NONE, flagPtr); } /* *---------------------------------------------------------------------- * @@ -947,12 +959,12 @@ * Tcl_ScanCountedElement -- * * This function is a companion function to Tcl_ConvertCountedElement. It * scans a string to see what needs to be done to it (e.g. add * backslashes or enclosing braces) to make the string into a valid Tcl - * list element. If length is -1, then the string is scanned from src up - * to the first null byte. + * list element. If length is TCL_INDEX_NONE, then the string is scanned + * from src up to the first null byte. * * Results: * The return value is an overestimate of the number of bytes that will * be needed by Tcl_ConvertCountedElement to produce a valid list element * from src. The word at *flagPtr is filled in with a value needed by @@ -962,19 +974,19 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_ScanCountedElement( const char *src, /* String to convert to Tcl list element. */ - size_t length, /* Number of bytes in src, or -1. */ + Tcl_Size length, /* Number of bytes in src, or TCL_INDEX_NONE. */ int *flagPtr) /* Where to store information to guide * Tcl_ConvertElement. */ { char flags = CONVERT_ANY; - int numBytes = TclScanElement(src, length, &flags); + Tcl_Size numBytes = TclScanElement(src, length, &flags); *flagPtr = flags; return numBytes; } @@ -984,11 +996,11 @@ * TclScanElement -- * * This function is a companion function to TclConvertElement. It scans a * string to see what needs to be done to it (e.g. add backslashes or * enclosing braces) to make the string into a valid Tcl list element. If - * length is -1, then the string is scanned from src up to the first null + * length is TCL_INDEX_NONE, then the string is scanned from src up to the first null * byte. A NULL value for src is treated as an empty string. The incoming * value of *flagPtr is a report from the caller what additional flags it * will pass to TclConvertElement(). * * Results: @@ -1006,27 +1018,27 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size TclScanElement( const char *src, /* String to convert to Tcl list element. */ - size_t length, /* Number of bytes in src, or -1. */ + Tcl_Size length, /* Number of bytes in src, or TCL_INDEX_NONE. */ char *flagPtr) /* Where to store information to guide * Tcl_ConvertElement. */ { const char *p = src; - int nestingLevel = 0; /* Brace nesting count */ + Tcl_Size nestingLevel = 0; /* Brace nesting count */ int forbidNone = 0; /* Do not permit CONVERT_NONE mode. Something * needs protection or escape. */ int requireEscape = 0; /* Force use of CONVERT_ESCAPE mode. For some * reason bare or brace-quoted form fails. */ - int extra = 0; /* Count of number of extra bytes needed for + Tcl_Size extra = 0; /* Count of number of extra bytes needed for * formatted element, assuming we use escape * sequences in formatting. */ - size_t bytesNeeded; /* Buffer length computed to complete the + Tcl_Size bytesNeeded; /* Buffer length computed to complete the * element formatting in the selected mode. */ #if COMPAT int preferEscape = 0; /* Use preferences to track whether to use */ int preferBrace = 0; /* CONVERT_MASK mode. */ int braceCount = 0; /* Count of all braces '{' '}' seen. */ @@ -1083,12 +1095,11 @@ case '}': /* TYPE_BRACE */ #if COMPAT braceCount++; #endif /* COMPAT */ extra++; /* Escape '}' => '\}' */ - nestingLevel--; - if (nestingLevel < 0) { + if (nestingLevel-- < 1) { /* * Unbalanced braces! Cannot format with brace quoting. */ requireEscape = 1; @@ -1160,16 +1171,16 @@ #endif } break; } } - length -= (length+1 > 1); + length -= (length > 0); p++; } endOfString: - if (nestingLevel != 0) { + if (nestingLevel > 0) { /* * Unbalanced braces! Cannot format with brace quoting. */ requireEscape = 1; @@ -1224,11 +1235,11 @@ if (preferEscape && !preferBrace) { /* * If we are quoting solely due to ] or internal " characters use * the CONVERT_MASK mode where we escape all special characters * except for braces. "extra" counted space needed to escape - * braces too, so substract "braceCount" to get our actual needs. + * braces too, so subtract "braceCount" to get our actual needs. */ bytesNeeded += (extra - braceCount); /* Make room to escape leading #, if needed. */ if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) { @@ -1308,17 +1319,17 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_ConvertElement( const char *src, /* Source information for list element. */ char *dst, /* Place to put list-ified element. */ int flags) /* Flags produced by Tcl_ScanElement. */ { - return Tcl_ConvertCountedElement(src, -1, dst, flags); + return Tcl_ConvertCountedElement(src, TCL_INDEX_NONE, dst, flags); } /* *---------------------------------------------------------------------- * @@ -1338,18 +1349,18 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size Tcl_ConvertCountedElement( const char *src, /* Source information for list element. */ - size_t length, /* Number of bytes in src, or -1. */ + Tcl_Size length, /* Number of bytes in src, or TCL_INDEX_NONE. */ char *dst, /* Place to put list-ified element. */ int flags) /* Flags produced by Tcl_ScanElement. */ { - size_t numBytes = TclConvertElement(src, length, dst, flags); + Tcl_Size numBytes = TclConvertElement(src, length, dst, flags); dst[numBytes] = '\0'; return numBytes; } /* @@ -1371,14 +1382,14 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size TclConvertElement( const char *src, /* Source information for list element. */ - size_t length, /* Number of bytes in src, or -1. */ + Tcl_Size length, /* Number of bytes in src, or TCL_INDEX_NONE. */ char *dst, /* Place to put list-ified element. */ int flags) /* Flags produced by Tcl_ScanElement. */ { int conversion = flags & CONVERT_MASK; char *p = dst; @@ -1409,11 +1420,11 @@ if (conversion == CONVERT_ESCAPE) { p[0] = '\\'; p[1] = '#'; p += 2; src++; - length -= (length+1 > 1); + length -= (length > 0); } else { conversion = CONVERT_BRACE; } } @@ -1450,20 +1461,20 @@ memcpy(p, src, length); p += length; } *p = '}'; p++; - return (size_t)(p - dst); + return (p - dst); } /* conversion == CONVERT_ESCAPE or CONVERT_MASK */ /* * Formatted string is original string converted to escape sequences. */ - for ( ; length; src++, length -= (length+1 > 1)) { + for ( ; length; src++, length -= (length > 0)) { switch (*src) { case ']': case '[': case '$': case ';': @@ -1513,11 +1524,11 @@ *p = 'v'; p++; continue; case '\0': if (length == TCL_INDEX_NONE) { - return (size_t)(p - dst); + return (p - dst); } /* * If we reach this point, there's an embedded NULL in the string * range being processed, which should not happen when the @@ -1529,11 +1540,11 @@ break; } *p = *src; p++; } - return (size_t)(p - dst); + return (p - dst); } /* *---------------------------------------------------------------------- * @@ -1554,25 +1565,28 @@ *---------------------------------------------------------------------- */ char * Tcl_Merge( - int argc, /* How many strings to merge. */ + Tcl_Size argc, /* How many strings to merge. */ const char *const *argv) /* Array of string values. */ { #define LOCAL_SIZE 64 char localFlags[LOCAL_SIZE], *flagPtr = NULL; - int i; + Tcl_Size i; size_t bytesNeeded = 0; char *result, *dst; /* * Handle empty list case first, so logic of the general case can be * simpler. */ - if (argc == 0) { + if (argc <= 0) { + if (argc < 0) { + Tcl_Panic("Tcl_Merge called with negative argc (%" TCL_SIZE_MODIFIER "d)", argc); + } result = (char *)Tcl_Alloc(1); result[0] = '\0'; return result; } @@ -1585,11 +1599,11 @@ } else { flagPtr = (char *)Tcl_Alloc(argc); } for (i = 0; i < argc; i++) { flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 ); - bytesNeeded += TclScanElement(argv[i], -1, &flagPtr[i]); + bytesNeeded += TclScanElement(argv[i], TCL_INDEX_NONE, &flagPtr[i]); } bytesNeeded += argc; /* * Pass two: copy into the result area. @@ -1597,11 +1611,11 @@ result = (char *)Tcl_Alloc(bytesNeeded); dst = result; for (i = 0; i < argc; i++) { flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 ); - dst += TclConvertElement(argv[i], -1, dst, flagPtr[i]); + dst += TclConvertElement(argv[i], TCL_INDEX_NONE, dst, flagPtr[i]); *dst = ' '; dst++; } dst[-1] = 0; @@ -1626,18 +1640,18 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size TclTrimRight( const char *bytes, /* String to be trimmed... */ - size_t numBytes, /* ...and its length in bytes */ + Tcl_Size numBytes, /* ...and its length in bytes */ /* Calls to TclUtfToUniChar() in this routine * rely on (bytes[numBytes] == '\0'). */ const char *trim, /* String of trim characters... */ - size_t numTrim) /* ...and its length in bytes */ + Tcl_Size numTrim) /* ...and its length in bytes */ /* Calls to TclUtfToUniChar() in this routine * rely on (trim[numTrim] == '\0'). */ { const char *pp, *p = bytes + numBytes; int ch1, ch2; @@ -1651,31 +1665,31 @@ * Outer loop: iterate over string to be trimmed. */ do { const char *q = trim; - size_t pInc = 0, bytesLeft = numTrim; + Tcl_Size pInc = 0, bytesLeft = numTrim; - pp = TclUtfPrev(p, bytes); + pp = Tcl_UtfPrev(p, bytes); do { pp += pInc; - pInc = TclUtfToUCS4(pp, &ch1); + pInc = Tcl_UtfToUniChar(pp, &ch1); } while (pp + pInc < p); /* * Inner loop: scan trim string for match to current character. */ do { - size_t qInc = TclUtfToUCS4(q, &ch2); + pInc = Tcl_UtfToUniChar(q, &ch2); if (ch1 == ch2) { break; } - q += qInc; - bytesLeft -= qInc; + q += pInc; + bytesLeft -= pInc; } while (bytesLeft); if (bytesLeft == 0) { /* * No match; trim task done; *p is last non-trimmed char. @@ -1705,23 +1719,23 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size TclTrimLeft( const char *bytes, /* String to be trimmed... */ - size_t numBytes, /* ...and its length in bytes */ + Tcl_Size numBytes, /* ...and its length in bytes */ /* Calls to TclUtfToUniChar() in this routine * rely on (bytes[numBytes] == '\0'). */ const char *trim, /* String of trim characters... */ - size_t numTrim) /* ...and its length in bytes */ + Tcl_Size numTrim) /* ...and its length in bytes */ /* Calls to TclUtfToUniChar() in this routine * rely on (trim[numTrim] == '\0'). */ { const char *p = bytes; - int ch1, ch2; + int ch1, ch2; /* Empty strings -> nothing to do */ if ((numBytes == 0) || (numTrim == 0)) { return 0; } @@ -1729,20 +1743,20 @@ /* * Outer loop: iterate over string to be trimmed. */ do { - size_t pInc = TclUtfToUCS4(p, &ch1); + Tcl_Size pInc = Tcl_UtfToUniChar(p, &ch1); const char *q = trim; - size_t bytesLeft = numTrim; + Tcl_Size bytesLeft = numTrim; /* * Inner loop: scan trim string for match to current character. */ do { - size_t qInc = TclUtfToUCS4(q, &ch2); + Tcl_Size qInc = Tcl_UtfToUniChar(q, &ch2); if (ch1 == ch2) { break; } @@ -1779,23 +1793,23 @@ * None. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size TclTrim( const char *bytes, /* String to be trimmed... */ - size_t numBytes, /* ...and its length in bytes */ + Tcl_Size numBytes, /* ...and its length in bytes */ /* Calls in this routine * rely on (bytes[numBytes] == '\0'). */ const char *trim, /* String of trim characters... */ - size_t numTrim, /* ...and its length in bytes */ + Tcl_Size numTrim, /* ...and its length in bytes */ /* Calls in this routine * rely on (trim[numTrim] == '\0'). */ - size_t *trimRightPtr) /* Offset from the end of the string. */ + Tcl_Size *trimRightPtr) /* Offset from the end of the string. */ { - size_t trimLeft = 0, trimRight = 0; + Tcl_Size trimLeft = 0, trimRight = 0; /* Empty strings -> nothing to do */ if ((numBytes > 0) && (numTrim > 0)) { /* When bytes is NUL-terminated, returns 0 <= trimLeft <= numBytes */ @@ -1805,11 +1819,11 @@ /* If we did not trim the whole string, it starts with a character * that we will not trim. Skip over it. */ if (numBytes > 0) { int ch; const char *first = bytes + trimLeft; - bytes += TclUtfToUCS4(first, &ch); + bytes += Tcl_UtfToUniChar(first, &ch); numBytes -= (bytes - first); if (numBytes > 0) { /* When bytes is NUL-terminated, returns * 0 <= trimRight <= numBytes */ @@ -1843,15 +1857,14 @@ /* The whitespace characters trimmed during [concat] operations */ #define CONCAT_WS_SIZE (sizeof(CONCAT_TRIM_SET "") - 1) char * Tcl_Concat( - int argc, /* Number of strings to concatenate. */ + Tcl_Size argc, /* Number of strings to concatenate. */ const char *const *argv) /* Array of strings to concatenate. */ { - int i; - size_t needSpace = 0, bytesNeeded = 0; + Tcl_Size i, needSpace = 0, bytesNeeded = 0; char *result, *p; /* * Dispose of the empty result corner case first to simplify later code. */ @@ -1866,20 +1879,31 @@ * First allocate the result buffer at the size required. */ for (i = 0; i < argc; i++) { bytesNeeded += strlen(argv[i]); + if (bytesNeeded < 0) { + Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded"); + } } /* * All element bytes + (argc - 1) spaces + 1 terminating NULL. */ + if (bytesNeeded + argc - 1 < 0) { + /* + * Panic test could be tighter, but not going to bother for this + * legacy routine. + */ + + Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded"); + } result = (char *)Tcl_Alloc(bytesNeeded + argc); for (p = result, i = 0; i < argc; i++) { - size_t triml, trimr, elemLength; + Tcl_Size triml, trimr, elemLength; const char *element; element = argv[i]; elemLength = strlen(argv[i]); @@ -1933,15 +1957,15 @@ *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_ConcatObj( - int objc, /* Number of objects to concatenate. */ + Tcl_Size objc, /* Number of objects to concatenate. */ Tcl_Obj *const objv[]) /* Array of objects to concatenate. */ { - int i, needSpace = 0; - size_t bytesNeeded = 0, elemLength; + int needSpace = 0; + Tcl_Size i, bytesNeeded = 0, elemLength; const char *element; Tcl_Obj *objPtr, *resPtr; /* * Check first to see if all the items are of list type or empty. If so, @@ -1948,34 +1972,45 @@ * we will concat them together as lists, and return a list object. This * is only valid when the lists are in canonical form. */ for (i = 0; i < objc; i++) { - size_t length; + Tcl_Size length; objPtr = objv[i]; - if (TclListObjIsCanonical(objPtr)) { + if (TclListObjIsCanonical(objPtr) || + TclObjTypeHasProc(objPtr,indexProc)) { continue; } - (void)TclGetStringFromObj(objPtr, &length); + (void)Tcl_GetStringFromObj(objPtr, &length); if (length > 0) { break; } } if (i == objc) { resPtr = NULL; for (i = 0; i < objc; i++) { objPtr = objv[i]; - if (!TclListObjIsCanonical(objPtr)) { + if (!TclListObjIsCanonical(objPtr) && + !TclObjTypeHasProc(objPtr,indexProc)) { continue; } if (resPtr) { - if (TCL_OK != Tcl_ListObjAppendList(NULL, resPtr, objPtr)) { + Tcl_Obj *elemPtr = NULL; + + Tcl_ListObjIndex(NULL, objPtr, 0, &elemPtr); + if (elemPtr == NULL) { + continue; + } + if (Tcl_GetString(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) { @@ -1987,15 +2022,18 @@ slow: /* * Something cannot be determined to be safe, so build the concatenation * the slow way, using the string representations. * - * First try to pre-allocate the size required. + * First try to preallocate the size required. */ for (i = 0; i < objc; i++) { - element = TclGetStringFromObj(objv[i], &elemLength); + element = Tcl_GetStringFromObj(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 @@ -2006,13 +2044,13 @@ TclNewObj(resPtr); (void) Tcl_AttemptSetObjLength(resPtr, bytesNeeded + objc - 1); Tcl_SetObjLength(resPtr, 0); for (i = 0; i < objc; i++) { - size_t triml, trimr; + Tcl_Size triml, trimr; - element = TclGetStringFromObj(objv[i], &elemLength); + element = Tcl_GetStringFromObj(objv[i], &elemLength); /* Trim away the leading/trailing whitespace. */ triml = TclTrim(element, elemLength, CONCAT_TRIM_SET, CONCAT_WS_SIZE, &trimr); element += triml; @@ -2111,11 +2149,11 @@ if (UCHAR(*pattern) < 0x80) { ch2 = (int) (nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern)); } else { - TclUtfToUCS4(pattern, &ch2); + Tcl_UtfToUniChar(pattern, &ch2); if (nocase) { ch2 = Tcl_UniCharToLower(ch2); } } @@ -2127,11 +2165,11 @@ */ if ((p != '[') && (p != '?') && (p != '\\')) { if (nocase) { while (*str) { - charLen = TclUtfToUCS4(str, &ch1); + charLen = Tcl_UtfToUniChar(str, &ch1); if (ch2==ch1 || ch2==Tcl_UniCharToLower(ch1)) { break; } str += charLen; } @@ -2141,11 +2179,11 @@ * shorter, as the number of bytes you want to compare * each time is non-constant. */ while (*str) { - charLen = TclUtfToUCS4(str, &ch1); + charLen = Tcl_UtfToUniChar(str, &ch1); if (ch2 == ch1) { break; } str += charLen; } @@ -2155,11 +2193,11 @@ return 1; } if (*str == '\0') { return 0; } - str += TclUtfToUCS4(str, &ch1); + str += Tcl_UtfToUniChar(str, &ch1); } } /* * Check for a "?" as the next pattern character. It matches any @@ -2166,11 +2204,11 @@ * single character. */ if (p == '?') { pattern++; - str += TclUtfToUCS4(str, &ch1); + str += Tcl_UtfToUniChar(str, &ch1); continue; } /* * Check for a "[" as the next pattern character. It is followed by a @@ -2185,11 +2223,11 @@ if (UCHAR(*str) < 0x80) { ch1 = (int) (nocase ? tolower(UCHAR(*str)) : UCHAR(*str)); str++; } else { - str += TclUtfToUCS4(str, &ch1); + str += Tcl_UtfToUniChar(str, &ch1); if (nocase) { ch1 = Tcl_UniCharToLower(ch1); } } while (1) { @@ -2199,11 +2237,11 @@ if (UCHAR(*pattern) < 0x80) { startChar = (int) (nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern)); pattern++; } else { - pattern += TclUtfToUCS4(pattern, &startChar); + pattern += Tcl_UtfToUniChar(pattern, &startChar); if (nocase) { startChar = Tcl_UniCharToLower(startChar); } } if (*pattern == '-') { @@ -2214,11 +2252,11 @@ if (UCHAR(*pattern) < 0x80) { endChar = (int) (nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern)); pattern++; } else { - pattern += TclUtfToUCS4(pattern, &endChar); + pattern += Tcl_UtfToUniChar(pattern, &endChar); if (nocase) { endChar = Tcl_UniCharToLower(endChar); } } if (((startChar <= ch1) && (ch1 <= endChar)) @@ -2262,12 +2300,12 @@ /* * There's no special character. Just make sure that the next bytes of * each string match. */ - str += TclUtfToUCS4(str, &ch1); - pattern += TclUtfToUCS4(pattern, &ch2); + str += Tcl_UtfToUniChar(str, &ch1); + pattern += Tcl_UtfToUniChar(pattern, &ch2); if (nocase) { if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) { return 0; } } else if (ch1 != ch2) { @@ -2297,15 +2335,15 @@ */ int TclByteArrayMatch( const unsigned char *string,/* String. */ - size_t strLen, /* Length of String */ + Tcl_Size strLen, /* Length of String */ const unsigned char *pattern, /* Pattern, which may contain special * characters. */ - size_t ptnLen, /* Length of Pattern */ + Tcl_Size ptnLen, /* Length of Pattern */ TCL_UNUSED(int) /*flags*/) { const unsigned char *stringEnd, *patternEnd; unsigned char p; @@ -2479,31 +2517,31 @@ Tcl_Obj *ptnObj, /* pattern object. */ int flags) /* Only TCL_MATCH_NOCASE should be passed, or * 0. */ { int match; - size_t length = 0, plen = 0; + Tcl_Size length = 0, plen = 0; /* * Promote based on the type of incoming object. * XXX: Currently doesn't take advantage of exact-ness that * XXX: TclReToGlob tells us about trivial = nocase ? 0 : TclMatchIsTrivial(TclGetString(ptnObj)); */ - if (TclHasIntRep(strObj, &tclStringType) || (strObj->typePtr == NULL)) { + if (TclHasInternalRep(strObj, &tclStringType) || (strObj->typePtr == NULL)) { Tcl_UniChar *udata, *uptn; - udata = TclGetUnicodeFromObj(strObj, &length); - uptn = TclGetUnicodeFromObj(ptnObj, &plen); + udata = Tcl_GetUnicodeFromObj(strObj, &length); + uptn = Tcl_GetUnicodeFromObj(ptnObj, &plen); match = TclUniCharMatch(udata, length, uptn, plen, flags); } else if (TclIsPureByteArray(strObj) && TclIsPureByteArray(ptnObj) && !flags) { unsigned char *data, *ptn; - data = TclGetByteArrayFromObj(strObj, &length); - ptn = TclGetByteArrayFromObj(ptnObj, &plen); + data = Tcl_GetByteArrayFromObj(strObj, &length); + ptn = Tcl_GetByteArrayFromObj(ptnObj, &plen); match = TclByteArrayMatch(data, length, ptn, plen, 0); } else { match = Tcl_StringCaseMatch(TclGetString(strObj), TclGetString(ptnObj), flags); } @@ -2559,47 +2597,48 @@ 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_Size length) /* Number of bytes from "bytes" to append. If * TCL_INDEX_NONE, then append all of bytes, up to null * at end. */ { - size_t newSize; + Tcl_Size newSize; - if (length == TCL_INDEX_NONE) { + if (length < 0) { length = strlen(bytes); } - newSize = length + dsPtr->length; - - /* - * Allocate a larger buffer for the string if the current one isn't large - * enough. Allocate extra space in the new buffer so that there will be - * room to grow before we have to allocate again. - */ - - if (newSize >= dsPtr->spaceAvl) { - dsPtr->spaceAvl = newSize * 2; + + 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 = (char *)Tcl_Alloc(dsPtr->spaceAvl); - + char *newString; + newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl); memcpy(newString, dsPtr->string, dsPtr->length); dsPtr->string = newString; } else { - size_t index = TCL_INDEX_NONE; + Tcl_Size offset = -1; /* See [16896d49fd] */ if (bytes >= dsPtr->string && bytes <= dsPtr->string + dsPtr->length) { - index = bytes - dsPtr->string; + /* Source string is within this DString. Note offset */ + offset = bytes - dsPtr->string; } - - dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, dsPtr->spaceAvl); - - if (index != TCL_INDEX_NONE) { - bytes = dsPtr->string + index; + dsPtr->string = + (char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl); + if (offset >= 0) { + bytes = dsPtr->string + offset; } } } /* @@ -2626,12 +2665,12 @@ char * TclDStringAppendObj( Tcl_DString *dsPtr, Tcl_Obj *objPtr) { - size_t length; - const char *bytes = TclGetStringFromObj(objPtr, &length); + Tcl_Size length; + const char *bytes = Tcl_GetStringFromObj(objPtr, &length); return Tcl_DStringAppend(dsPtr, bytes, length); } char * @@ -2669,11 +2708,11 @@ { char *dst = dsPtr->string + dsPtr->length; int needSpace = TclNeedSpace(dsPtr->string, dst); char flags = 0; int quoteHash = 1; - size_t newSize; + Tcl_Size newSize; if (needSpace) { /* * If we need a space to separate the new element from something * already ending the string, we're not appending the first element @@ -2695,11 +2734,11 @@ quoteHash = !TclNeedSpace(dsPtr->string, dst+1); } if (!quoteHash) { flags |= TCL_DONT_QUOTE_HASH; } - newSize = dsPtr->length + needSpace + TclScanElement(element, -1, &flags); + newSize = dsPtr->length + needSpace + TclScanElement(element, TCL_INDEX_NONE, &flags); if (!quoteHash) { flags |= TCL_DONT_QUOTE_HASH; } /* @@ -2707,29 +2746,27 @@ * 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; + newSize += 1; /* For terminating nul */ + if (newSize > dsPtr->spaceAvl) { if (dsPtr->string == dsPtr->staticSpace) { - char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl); - + char *newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl); memcpy(newString, dsPtr->string, dsPtr->length); dsPtr->string = newString; } else { int offset = -1; /* See [16896d49fd] */ if (element >= dsPtr->string && element <= dsPtr->string + dsPtr->length) { + /* Source string is within this DString. Note offset */ offset = element - dsPtr->string; } - - dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, dsPtr->spaceAvl); - + dsPtr->string = + (char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl); if (offset >= 0) { element = dsPtr->string + offset; } } } @@ -2744,11 +2781,11 @@ *dst = ' '; dst++; dsPtr->length++; } - dsPtr->length += TclConvertElement(element, -1, dst, flags); + dsPtr->length += TclConvertElement(element, TCL_INDEX_NONE, dst, flags); dsPtr->string[dsPtr->length] = '\0'; return dsPtr->string; } /* @@ -2770,28 +2807,34 @@ */ void Tcl_DStringSetLength( Tcl_DString *dsPtr, /* Structure describing dynamic string. */ - size_t length) /* New length for dynamic string. */ + Tcl_Size length) /* New length for dynamic string. */ { - size_t newsize; + Tcl_Size newsize; + if (length < 0) { + length = 0; + } if (length >= dsPtr->spaceAvl) { /* * There are two interesting cases here. In the first case, the user * may be trying to allocate a large buffer of a specific size. It * would be wasteful to overallocate that buffer, so we just allocate * enough for the requested size plus the trailing null byte. In the * second case, we are growing the buffer incrementally, so we need - * behavior similar to Tcl_DStringAppend. The requested length will - * usually be a small delta above the current spaceAvl, so we'll end - * up doubling the old size. This won't grow the buffer quite as - * quickly, but it should be close enough. + * behavior similar to Tcl_DStringAppend. + * TODO - the above makes no sense to me. How does the code below + * translate into distinguishing the two cases above? IMO, if caller + * specifically sets the length, there is no cause for overallocation. */ - newsize = dsPtr->spaceAvl * 2; + 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; } @@ -2862,11 +2905,11 @@ Tcl_DStringResult( Tcl_Interp *interp, /* Interpreter whose result is to be reset. */ Tcl_DString *dsPtr) /* Dynamic string that is to become the * result of interp. */ { - Tcl_SetObjResult(interp, TclDStringToObj(dsPtr)); + Tcl_SetObjResult(interp, Tcl_DStringToObj(dsPtr)); } /* *---------------------------------------------------------------------- * @@ -2892,21 +2935,21 @@ Tcl_Interp *interp, /* Interpreter whose result is to be reset. */ Tcl_DString *dsPtr) /* Dynamic string that is to become the result * of interp. */ { Tcl_Obj *obj = Tcl_GetObjResult(interp); - char *bytes = TclGetString(obj); + const char *bytes = TclGetString(obj); Tcl_DStringFree(dsPtr); Tcl_DStringAppend(dsPtr, bytes, obj->length); Tcl_ResetResult(interp); } /* *---------------------------------------------------------------------- * - * TclDStringToObj -- + * Tcl_DStringToObj -- * * This function moves a dynamic string's contents to a new Tcl_Obj. Be * aware that this function does *not* check that the encoding of the * contents of the dynamic string is correct; this is the caller's * responsibility to enforce. @@ -2922,11 +2965,11 @@ * *---------------------------------------------------------------------- */ Tcl_Obj * -TclDStringToObj( +Tcl_DStringToObj( Tcl_DString *dsPtr) { Tcl_Obj *result; if (dsPtr->string == dsPtr->staticSpace) { @@ -3049,20 +3092,20 @@ /* * Handle NaN. */ - if (TclIsNaN(value)) { + if (isnan(value)) { TclFormatNaN(value, dst); return; } /* * Handle infinities. */ - if (TclIsInfinite(value)) { + if (isinf(value)) { /* * Remember to copy the terminating NUL too. */ if (value < 0) { @@ -3096,11 +3139,11 @@ *dst++ = c; c = *++p; } } - sprintf(dst, "e%+d", exponent); + snprintf(dst, TCL_DOUBLE_SPACE, "e%+d", exponent); } else { /* * F format for others. */ @@ -3249,18 +3292,18 @@ * the "buffer" argument. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size TclFormatInt( char *buffer, /* Points to the storage into which the * formatted characters are written. */ Tcl_WideInt n) /* The integer to format. */ { Tcl_WideUInt intVal; - size_t i = 0, numFormatted, j; + int i = 0, numFormatted, j; static const char digits[] = "0123456789"; /* * Generate the characters of the result backwards in the buffer. */ @@ -3319,24 +3362,27 @@ GetWideForIndex( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, then no error message is left after * errors. */ Tcl_Obj *objPtr, /* Points to the value to be parsed */ - size_t endValue, /* The value to be stored at *widePtr if + Tcl_WideInt endValue, /* The value to be stored at *widePtr if * objPtr holds "end". * NOTE: this value may be TCL_INDEX_NONE. */ Tcl_WideInt *widePtr) /* Location filled in with a wide integer * representing an index. */ { int numType; - ClientData cd; - int code = TclGetNumberFromObj(NULL, objPtr, &cd, &numType); + void *cd; + int code = Tcl_GetNumberFromObj(NULL, objPtr, &cd, &numType); if (code == TCL_OK) { if (numType == TCL_NUMBER_INT) { /* objPtr holds an integer in the signed wide range */ *widePtr = *(Tcl_WideInt *)cd; + if ((*widePtr < 0)) { + *widePtr = (endValue == -1) ? WIDE_MIN : -1; + } return TCL_OK; } if (numType == TCL_NUMBER_BIG) { /* objPtr holds an integer outside the signed wide range */ /* Truncate to the signed wide range. */ @@ -3356,26 +3402,32 @@ * * 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 + * 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'. If - * 'objPtr' has the value "end", the value stored is 'endValue'. + * 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. * - * Effect + * Side effects: * - * The object referenced by 'objPtr' is converted, as needed, to an - * integer, wide integer, or end-based-index object. + * The internal representation contained within objPtr may shimmer. * *---------------------------------------------------------------------- */ int @@ -3383,33 +3435,36 @@ 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_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; - /* 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; + /* 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 -- * @@ -3422,11 +3477,12 @@ * WIDE_MIN+1: Index value n, for any n < -1 (usually same effect as -1) * -$n: Index "end-[expr {$n-1}]" * -2: Index "end-1" * -1: Index "end" * 0: Index "0" - * WIDE_MAX-1: Index "end+n", for any n > 1 + * WIDE_MAX-1: Index "end+n", for any n > 1. Distinguish from end+1 for + * commands like lset. * WIDE_MAX: Index "end+1" * * Results: * Tcl return code. * @@ -3438,28 +3494,28 @@ 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 + 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_ObjIntRep *irPtr; + Tcl_ObjInternalRep *irPtr; Tcl_WideInt offset = -1; /* Offset in the "end-offset" expression - 1 */ - ClientData cd; + void *cd; - while ((irPtr = TclFetchIntRep(objPtr, &endOffsetType)) == NULL) { - Tcl_ObjIntRep ir; - size_t length; - const char *bytes = TclGetStringFromObj(objPtr, &length); + while ((irPtr = TclFetchInternalRep(objPtr, &endOffsetType)) == NULL) { + Tcl_ObjInternalRep ir; + Tcl_Size length; + const char *bytes = Tcl_GetStringFromObj(objPtr, &length); if (*bytes != 'e') { int numType; const char *opPtr; - int len, t1 = 0, t2 = 0; + int t1 = 0, t2 = 0; /* Value doesn't start with "e" */ /* If we reach here, the string rep of objPtr exists. */ @@ -3472,47 +3528,47 @@ /* * Quick scan to see if multi-value list is even possible. * This relies on TclGetString() returning a NUL-terminated string. */ - if ((TclMaxListLength(bytes, -1, NULL) > 1) + if ((TclMaxListLength(bytes, TCL_INDEX_NONE, NULL) > 1) /* If it's possible, do the full list parse. */ - && (TCL_OK == Tcl_ListObjLength(NULL, objPtr, &len)) - && (len > 1)) { + && (TCL_OK == TclListObjLengthM(NULL, objPtr, &length)) + && (length > 1)) { goto parseError; } /* Passed the list screen, so parse for index arithmetic expression */ - if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, NULL, -1, &opPtr, + if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE, &opPtr, TCL_PARSE_INTEGER_ONLY)) { Tcl_WideInt w1=0, w2=0; /* value starts with valid integer... */ if ((*opPtr == '-') || (*opPtr == '+')) { /* ... value continues with [-+] ... */ /* Save first integer as wide if possible */ - TclGetNumberFromObj(NULL, objPtr, &cd, &t1); + Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t1); if (t1 == TCL_NUMBER_INT) { w1 = (*(Tcl_WideInt *)cd); } if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, opPtr + 1, - -1, NULL, TCL_PARSE_INTEGER_ONLY)) { + TCL_INDEX_NONE, NULL, TCL_PARSE_INTEGER_ONLY)) { /* ... value concludes with second valid integer */ /* Save second integer as wide if possible */ - TclGetNumberFromObj(NULL, objPtr, &cd, &t2); + Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t2); if (t2 == TCL_NUMBER_INT) { w2 = (*(Tcl_WideInt *)cd); } } } - /* Clear invalid intreps left by TclParseNumber */ - TclFreeIntRep(objPtr); + /* Clear invalid internalreps left by TclParseNumber */ + TclFreeInternalRep(objPtr); if (t1 && t2) { /* We have both integer values */ if ((t1 == TCL_NUMBER_INT) && (t2 == TCL_NUMBER_INT)) { /* Both are wide, do wide-integer math */ @@ -3554,11 +3610,11 @@ } else { Tcl_Interp *compute = Tcl_CreateInterp(); Tcl_ExprObj(compute, objPtr, &sum); Tcl_DeleteInterp(compute); } - TclGetNumberFromObj(NULL, sum, &cd, &numType); + Tcl_GetNumberFromObj(NULL, sum, &cd, &numType); if (numType == TCL_NUMBER_INT) { /* sum holds an integer in the signed wide range */ offset = *(Tcl_WideInt *)cd; } else { @@ -3605,11 +3661,11 @@ /* Not a recognized integer format */ goto parseError; } /* Got an integer offset; pull it from where parser left it. */ - TclGetNumberFromObj(NULL, objPtr, &cd, &t); + Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t); if (t == TCL_NUMBER_BIG) { /* Truncate to the signed wide range. */ if (mp_isneg((mp_int *)cd)) { offset = (bytes[3] == '-') ? WIDE_MAX : WIDE_MIN; @@ -3633,27 +3689,37 @@ } parseOK: /* Success. Store the new internal rep. */ ir.wideValue = offset; - Tcl_StoreIntRep(objPtr, &endOffsetType, &ir); + Tcl_StoreInternalRep(objPtr, &endOffsetType, &ir); } offset = irPtr->wideValue; if (offset == WIDE_MAX) { - *widePtr = endValue + 1; + /* + * 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 (endValue == (size_t)-1) { - *widePtr = offset; } else if (offset < 0) { - /* Different signs, sum cannot overflow */ + /* end-(n-1) - Different signs, sum cannot overflow */ *widePtr = endValue + offset + 1; } else if (offset < WIDE_MAX) { + /* 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. */ @@ -3664,33 +3730,40 @@ "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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", (void *)NULL); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclIndexEncode -- + * IMPORTANT: function only encodes indices in the range that fits within + * an "int" type. Do NOT change this as the byte code compiler and engine + * which call this function cannot handle wider index types. Indices + * outside the range will result in the function returning an error. * * Parse objPtr to determine if it is an index value. Two cases * are possible. The value objPtr might be parsed as an absolute - * index value in the C signed int range. Note that this includes + * index value in the Tcl_Size range. Note that this includes * index values that are integers as presented and it includes index - * arithmetic expressions. The absolute index values that can be + * arithmetic expressions. + * + * 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 - * 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. + * 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 @@ -3711,16 +3784,13 @@ * string possible in Tcl 8 is 0x7FFFFFFE, the interpretation of * "end-0x7FFFFFFE" for that largest string would be 0. Thus, * if the tokens "end-0x7FFFFFFF" or "end+-0x80000000" are parsed, * they can be encoded with the before value. * - * These details will require re-examination whenever string and - * list length limits are increased, but that will likely also - * mean a revised routine capable of returning Tcl_WideInt values. - * * Returns: - * TCL_OK if parsing succeeded, and TCL_ERROR if it failed. + * TCL_OK if parsing succeeded, and TCL_ERROR if it failed or the + * index does not fit in an int type. * * Side effects: * When TCL_OK is returned, the encoded index value is written * to *indexPtr. * @@ -3729,45 +3799,137 @@ int TclIndexEncode( Tcl_Interp *interp, /* For error reporting, may be NULL */ Tcl_Obj *objPtr, /* Index value to parse */ - size_t before, /* Value to return for index before beginning */ - size_t after, /* Value to return for index after end */ + int before, /* Value to return for index before beginning */ + int after, /* Value to return for index after end */ int *indexPtr) /* Where to write the encoded answer, not NULL */ { Tcl_WideInt wide; int idx; - - 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". + 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 <= (irPtr ? INT_MAX : -1)) { - /* These indices always indicate "before the beginning */ + } else if (wide < 0) { + /* 4(a,b) (32-bit systems), 5(a,b) - before the beginning */ idx = before; } else { - /* Encoded end-positive (or end+negative) are offset */ + /* 1(a,b) Encodable range */ idx = (int)wide; } } else { - return TCL_ERROR; + /* 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; } /* *---------------------------------------------------------------------- * @@ -3781,23 +3943,94 @@ * The decoded index value. * *---------------------------------------------------------------------- */ -size_t +Tcl_Size TclIndexDecode( int encoded, /* Value to decode */ - size_t endValue) /* Meaning of "end" to use, > TCL_INDEX_END */ + Tcl_Size endValue) /* Meaning of "end" to use, > TCL_INDEX_END */ { - if (encoded > (int)TCL_INDEX_END) { + if (encoded > TCL_INDEX_END) { return encoded; } - if (endValue >= TCL_INDEX_END - encoded) { - return endValue + encoded - TCL_INDEX_END; + endValue += encoded - TCL_INDEX_END; + if (endValue >= 0) { + return endValue; } return TCL_INDEX_NONE; } + +/* + *------------------------------------------------------------------------ + * + * TclIndexInvalidError -- + * + * Generates an error message including the invalid index. + * + * Results: + * Always return TCL_ERROR. + * + * Side effects: + * If interp is not-NULL, an error message is stored in it. + * + *------------------------------------------------------------------------ + */ +int +TclIndexInvalidError ( + Tcl_Interp *interp, /* May be NULL */ + const char *idxType, /* The descriptive string for idx. Defaults to "index" */ + Tcl_Size idx) /* Invalid index value */ +{ + if (interp) { + Tcl_SetObjResult(interp, + Tcl_ObjPrintf("Invalid %s value %" TCL_SIZE_MODIFIER "d.", + idxType ? idxType : "index", + idx)); + } + return TCL_ERROR; /* Always */ +} + +/* + *------------------------------------------------------------------------ + * + * 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 -- @@ -3870,11 +4103,11 @@ *---------------------------------------------------------------------- */ static void FreeThreadHash( - ClientData clientData) + void *clientData) { Tcl_HashTable *tablePtr = (Tcl_HashTable *)clientData; ClearHash(tablePtr); Tcl_DeleteHashTable(tablePtr); @@ -3892,11 +4125,11 @@ *---------------------------------------------------------------------- */ static void FreeProcessGlobalValue( - ClientData clientData) + void *clientData) { ProcessGlobalValue *pgvPtr = (ProcessGlobalValue *)clientData; pgvPtr->epoch++; pgvPtr->numBytes = 0; @@ -3952,11 +4185,11 @@ } 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 + * 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); @@ -3985,11 +4218,11 @@ ProcessGlobalValue *pgvPtr) { Tcl_Obj *value = NULL; Tcl_HashTable *cacheMap; Tcl_HashEntry *hPtr; - size_t epoch = pgvPtr->epoch; + Tcl_Size epoch = pgvPtr->epoch; if (pgvPtr->encoding) { Tcl_Encoding current = Tcl_GetEncoding(NULL, NULL); if (pgvPtr->encoding != current) { @@ -4001,14 +4234,15 @@ 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_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); @@ -4191,11 +4425,11 @@ int TclReToGlob( Tcl_Interp *interp, const char *reStr, - size_t reStrLen, + Tcl_Size reStrLen, Tcl_DString *dsPtr, int *exactPtr, int *quantifiersFoundPtr) { int anchorLeft, anchorRight, lastIsStar, numStars; @@ -4385,11 +4619,11 @@ return TCL_OK; invalidGlob: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1)); - Tcl_SetErrorCode(interp, "TCL", "RE2GLOB", code, NULL); + Tcl_SetErrorCode(interp, "TCL", "RE2GLOB", code, (void *)NULL); } Tcl_DStringFree(dsPtr); return TCL_ERROR; } Index: generic/tclVar.c ================================================================== --- generic/tclVar.c +++ generic/tclVar.c @@ -5,15 +5,15 @@ * and arrays). * * The implementation of arrays is modelled after an initial * implementation by Mark Diekhans and Karl Lehenbauer. * - * Copyright (c) 1987-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. - * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. - * Copyright (c) 2007 Miguel Sofer + * Copyright © 1987-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. + * Copyright © 2001 Kevin B. Kenny. All rights reserved. + * Copyright © 2007 Miguel Sofer * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -106,13 +106,10 @@ 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 @@ -198,11 +195,11 @@ static Tcl_Var ObjFindNamespaceVar(Tcl_Interp *interp, Tcl_Obj *namePtr, Tcl_Namespace *contextNsPtr, int flags); static int ObjMakeUpvar(Tcl_Interp *interp, CallFrame *framePtr, Tcl_Obj *otherP1Ptr, - const char *otherP2, const int otherFlags, + const char *otherP2, int otherFlags, Tcl_Obj *myNamePtr, int myFlags, int index); static ArraySearch * ParseSearchId(Tcl_Interp *interp, const Var *varPtr, Tcl_Obj *varNamePtr, Tcl_Obj *handleObj); static void UnsetVarStruct(Var *varPtr, Var *arrayPtr, Interp *iPtr, Tcl_Obj *part1Ptr, @@ -210,23 +207,21 @@ /* * TIP #508: [array default] */ -static int ArrayDefaultCmd(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); +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, const int create, + Tcl_Obj *varNamePtr, int flags, int create, const char **errMsgPtr, int *indexPtr); static Tcl_DupInternalRepProc DupLocalVarName; static Tcl_FreeInternalRepProc FreeLocalVarName; @@ -248,52 +243,54 @@ * Tcl_Obj), or NULL if it is a scalar variable */ static const Tcl_ObjType localVarNameType = { "localVarName", - FreeLocalVarName, DupLocalVarName, NULL, NULL + FreeLocalVarName, DupLocalVarName, NULL, NULL, + TCL_OBJTYPE_V0 }; -#define LocalSetIntRep(objPtr, index, namePtr) \ +#define LocalSetInternalRep(objPtr, index, namePtr) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ Tcl_Obj *ptr = (namePtr); \ if (ptr) {Tcl_IncrRefCount(ptr);} \ ir.twoPtrValue.ptr1 = ptr; \ ir.twoPtrValue.ptr2 = INT2PTR(index); \ - Tcl_StoreIntRep((objPtr), &localVarNameType, &ir); \ + Tcl_StoreInternalRep((objPtr), &localVarNameType, &ir); \ } while (0) -#define LocalGetIntRep(objPtr, index, name) \ +#define LocalGetInternalRep(objPtr, index, name) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), &localVarNameType); \ + const Tcl_ObjInternalRep *irPtr; \ + irPtr = TclFetchInternalRep((objPtr), &localVarNameType); \ (name) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr1 : NULL; \ - (index) = irPtr ? PTR2INT(irPtr->twoPtrValue.ptr2) : -1; \ + (index) = irPtr ? PTR2INT(irPtr->twoPtrValue.ptr2) : TCL_INDEX_NONE; \ } while (0) static const Tcl_ObjType parsedVarNameType = { "parsedVarName", - FreeParsedVarName, DupParsedVarName, NULL, NULL + FreeParsedVarName, DupParsedVarName, NULL, NULL, + TCL_OBJTYPE_V0 }; -#define ParsedSetIntRep(objPtr, arrayPtr, elem) \ +#define ParsedSetInternalRep(objPtr, arrayPtr, elem) \ do { \ - Tcl_ObjIntRep ir; \ + Tcl_ObjInternalRep ir; \ Tcl_Obj *ptr1 = (arrayPtr); \ Tcl_Obj *ptr2 = (elem); \ if (ptr1) {Tcl_IncrRefCount(ptr1);} \ if (ptr2) {Tcl_IncrRefCount(ptr2);} \ ir.twoPtrValue.ptr1 = ptr1; \ ir.twoPtrValue.ptr2 = ptr2; \ - Tcl_StoreIntRep((objPtr), &parsedVarNameType, &ir); \ + Tcl_StoreInternalRep((objPtr), &parsedVarNameType, &ir); \ } while (0) -#define ParsedGetIntRep(objPtr, parsed, array, elem) \ +#define ParsedGetInternalRep(objPtr, parsed, array, elem) \ do { \ - const Tcl_ObjIntRep *irPtr; \ - irPtr = TclFetchIntRep((objPtr), &parsedVarNameType); \ + const Tcl_ObjInternalRep *irPtr; \ + irPtr = TclFetchInternalRep((objPtr), &parsedVarNameType); \ (parsed) = (irPtr != NULL); \ (array) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr1 : NULL; \ (elem) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr2 : NULL; \ } while (0) @@ -344,11 +341,11 @@ { const char *nameStr = TclGetString(name); Tcl_SetObjResult(interp, Tcl_ObjPrintf("\"%s\" isn't an array", nameStr)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", nameStr, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", nameStr, (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -379,21 +376,21 @@ Var *arrayPtr) /* Array that contains the variable, or NULL * if this variable isn't an array element. */ { if (TclIsVarUndefined(varPtr) && TclIsVarInHash(varPtr) && !TclIsVarTraced(varPtr) - && (VarHashRefCount(varPtr) == (unsigned) + && (VarHashRefCount(varPtr) == (Tcl_Size) !TclIsVarDeadHash(varPtr))) { if (VarHashRefCount(varPtr) == 0) { Tcl_Free(varPtr); } else { VarHashDeleteEntry(varPtr); } } if (arrayPtr != NULL && TclIsVarUndefined(arrayPtr) && TclIsVarInHash(arrayPtr) && !TclIsVarTraced(arrayPtr) && - (VarHashRefCount(arrayPtr) == (unsigned) + (VarHashRefCount(arrayPtr) == (Tcl_Size) !TclIsVarDeadHash(arrayPtr))) { if (VarHashRefCount(arrayPtr) == 0) { Tcl_Free(arrayPtr); } else { VarHashDeleteEntry(arrayPtr); @@ -539,14 +536,14 @@ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * and TCL_LEAVE_ERR_MSG bits matter. */ const char *msg, /* Verb to use in error messages, e.g. "read" * or "set". Only needed if TCL_LEAVE_ERR_MSG * is set in flags. */ - const int createPart1, /* If 1, create hash table entry for part 1 of + int createPart1, /* If 1, create hash table entry for part 1 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ - const int createPart2, /* If 1, create hash table entry for part 2 of + int createPart2, /* If 1, create hash table entry for part 2 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var **arrayPtrPtr) /* If the name refers to an element of an * array, *arrayPtrPtr gets filled in with * address of array variable. Otherwise this @@ -589,14 +586,14 @@ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * and TCL_LEAVE_ERR_MSG bits matter. */ const char *msg, /* Verb to use in error messages, e.g. "read" * or "set". Only needed if TCL_LEAVE_ERR_MSG * is set in flags. */ - const int createPart1, /* If 1, create hash table entry for part 1 of + int createPart1, /* If 1, create hash table entry for part 1 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ - const int createPart2, /* If 1, create hash table entry for part 2 of + int createPart2, /* If 1, create hash table entry for part 2 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var **arrayPtrPtr) /* If the name refers to an element of an * array, *arrayPtrPtr gets filled in with * address of array variable. Otherwise this @@ -607,17 +604,17 @@ Var *varPtr; /* Points to the variable's in-frame Var * structure. */ const char *errMsg = NULL; int index, parsed = 0; - int localIndex; + Tcl_Size localIndex; Tcl_Obj *namePtr, *arrayPtr, *elem; *arrayPtrPtr = NULL; restart: - LocalGetIntRep(part1Ptr, localIndex, namePtr); + LocalGetInternalRep(part1Ptr, localIndex, namePtr); if (localIndex >= 0) { if (HasLocalVars(varFramePtr) && !(flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)) && (localIndex < varFramePtr->numCompiledLocals)) { /* @@ -634,14 +631,14 @@ } goto doneParsing; } /* - * If part1Ptr is a parsedVarNameType, retrieve the pre-parsed parts. + * If part1Ptr is a parsedVarNameType, retrieve the preparsed parts. */ - ParsedGetIntRep(part1Ptr, parsed, arrayPtr, elem); + ParsedGetInternalRep(part1Ptr, parsed, arrayPtr, elem); if (parsed && arrayPtr) { if (part2Ptr != NULL) { /* * ERROR: part1Ptr is already an array element, cannot specify * a part2. @@ -648,11 +645,11 @@ */ if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg, NOSUCHVAR, -1); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "VARNAME", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "VARNAME", (void *)NULL); } return NULL; } part2Ptr = elem; part1Ptr = arrayPtr; @@ -662,12 +659,12 @@ if (!parsed) { /* * part1Ptr is possibly an unparsed array element. */ - size_t len; - const char *part1 = TclGetStringFromObj(part1Ptr, &len); + Tcl_Size len; + const char *part1 = Tcl_GetStringFromObj(part1Ptr, &len); if ((len > 1) && (part1[len - 1] == ')')) { const char *part2 = strchr(part1, '('); if (part2) { @@ -674,20 +671,20 @@ if (part2Ptr != NULL) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg, NEEDARRAY, -1); Tcl_SetErrorCode(interp, "TCL", "VALUE", "VARNAME", - NULL); + (void *)NULL); } return NULL; } arrayPtr = Tcl_NewStringObj(part1, (part2 - part1)); part2Ptr = Tcl_NewStringObj(part2 + 1, len - (part2 - part1) - 2); - ParsedSetIntRep(part1Ptr, arrayPtr, part2Ptr); + ParsedSetInternalRep(part1Ptr, arrayPtr, part2Ptr); part1Ptr = arrayPtr; } } } @@ -702,11 +699,11 @@ &errMsg, &index); if (varPtr == NULL) { if ((errMsg != NULL) && (flags & TCL_LEAVE_ERR_MSG)) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg, errMsg, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", - TclGetString(part1Ptr), NULL); + TclGetString(part1Ptr), (void *)NULL); } return NULL; } /* @@ -719,46 +716,46 @@ */ Tcl_Obj *cachedNamePtr = localName(varFramePtr, index); if (part1Ptr == cachedNamePtr) { - LocalSetIntRep(part1Ptr, index, NULL); + LocalSetInternalRep(part1Ptr, index, NULL); } else { /* * [80304238ac] Trickiness here. We will store and incr the * refcount on cachedNamePtr. Trouble is that it's possible - * (see test var-22.1) for cachedNamePtr to have an intrep + * (see test var-22.1) for cachedNamePtr to have an internalrep * that contains a stored and refcounted part1Ptr. This * would be a reference cycle which leads to a memory leak. * - * The solution here is to wipe away all intrep(s) in + * The solution here is to wipe away all internalrep(s) in * cachedNamePtr and leave it as string only. This is * radical and destructive, so a better idea would be welcome. */ /* * Firstly set cached local var reference (avoid free before set, * see [45b9faf103f2]) */ - LocalSetIntRep(part1Ptr, index, cachedNamePtr); + LocalSetInternalRep(part1Ptr, index, cachedNamePtr); /* Then wipe it */ - TclFreeIntRep(cachedNamePtr); + TclFreeInternalRep(cachedNamePtr); /* * Now go ahead and convert it the the "localVarName" type, * since we suspect at least some use of the value as a * varname and we want to resolve it quickly. */ - LocalSetIntRep(cachedNamePtr, index, NULL); + LocalSetInternalRep(cachedNamePtr, index, NULL); } } else { /* * At least mark part1Ptr as already parsed. */ - ParsedSetIntRep(part1Ptr, NULL, NULL); + ParsedSetInternalRep(part1Ptr, NULL, NULL); } donePart1: while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; @@ -795,11 +792,11 @@ * is one of the compiledLocals, its index is placed in *indexPtr. * Otherwise, *indexPtr will be set to (according to the needs of * TclObjLookupVar): * -1 a global reference * -2 a reference to a namespace variable - * -3 a non-cachable reference, i.e., one of: + * -3 a non-cacheable reference, i.e., one of: * . non-indexed local var * . a reference of unknown origin; * . resolution by a namespace or interp resolver * * If the variable isn't found and creation wasn't specified, or some @@ -825,11 +822,11 @@ Tcl_Obj *varNamePtr, /* This is a simple variable name that could * represent a scalar or an array. */ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_AVOID_RESOLVERS and TCL_LEAVE_ERR_MSG * bits matter. */ - const int create, /* If 1, create hash table entry for varname, + int create, /* If 1, create hash table entry for varname, * if it doesn't already exist. If 0, return * error if it doesn't exist. */ const char **errMsgPtr, int *indexPtr) { @@ -844,13 +841,13 @@ 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); + int isNew, result; + Tcl_Size i, varLen; + const char *varName = Tcl_GetStringFromObj(varNamePtr, &varLen); varPtr = NULL; varNsPtr = NULL; /* Set non-NULL if a nonlocal variable. */ *indexPtr = -3; @@ -970,22 +967,22 @@ } else { *indexPtr = -2; } } } else { /* Local var: look in frame varFramePtr. */ - int localCt = varFramePtr->numCompiledLocals; + Tcl_Size localCt = varFramePtr->numCompiledLocals; if (localCt > 0) { Tcl_Obj **objPtrPtr = &varFramePtr->localCachePtr->varName0; const char *localNameStr; - size_t localLen; + Tcl_Size localLen; for (i=0 ; icompiledLocals[i]; @@ -996,10 +993,11 @@ 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; @@ -1057,19 +1055,19 @@ TclLookupArrayElement( Tcl_Interp *interp, /* Interpreter to use for lookup. */ Tcl_Obj *arrayNamePtr, /* This is the name of the array, or NULL if * index>= 0. */ Tcl_Obj *elNamePtr, /* Name of element within array. */ - const int flags, /* Only TCL_LEAVE_ERR_MSG bit matters. */ + int flags, /* Only TCL_LEAVE_ERR_MSG bit matters. */ const char *msg, /* Verb to use in error messages, e.g. "read" * or "set". Only needed if TCL_LEAVE_ERR_MSG * is set in flags. */ - const int createArray, /* If 1, transform arrayName to be an array if + int createArray, /* If 1, transform arrayName to be an array if * it isn't one yet and the transformation is * possible. If 0, return error if it isn't * already an array. */ - const int createElem, /* If 1, create hash table entry for the + int createElem, /* If 1, create hash table entry for the * element, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var *arrayPtr, /* Pointer to the array's Var structure. */ int index) /* If >=0, the index of the local array. */ { @@ -1085,11 +1083,11 @@ if (!createArray) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, NOSUCHVAR, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", - arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL); + arrayNamePtr?TclGetString(arrayNamePtr):NULL, (void *)NULL); } return NULL; } /* @@ -1100,11 +1098,11 @@ if (TclIsVarDeadHash(arrayPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, DANGLINGVAR, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", - arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL); + arrayNamePtr?TclGetString(arrayNamePtr):NULL, (void *)NULL); } return NULL; } TclInitArrayVar(arrayPtr); @@ -1111,11 +1109,11 @@ } else if (!TclIsVarArray(arrayPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, NEEDARRAY, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", - arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL); + arrayNamePtr?TclGetString(arrayNamePtr):NULL, (void *)NULL); } return NULL; } if (createElem) { @@ -1132,11 +1130,11 @@ if (varPtr == NULL) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, NOSUCHELEMENT, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ELEMENT", - TclGetString(elNamePtr), NULL); + TclGetString(elNamePtr), (void *)NULL); } } } return varPtr; } @@ -1333,11 +1331,11 @@ * containing array otherwise. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ - const int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, and + int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, and * TCL_LEAVE_ERR_MSG bits. */ { if (varPtr == NULL) { Tcl_Panic("varPtr must not be NULL"); } @@ -1379,18 +1377,21 @@ * containing array otherwise. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ - const int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, and + int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, and * TCL_LEAVE_ERR_MSG bits. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { Interp *iPtr = (Interp *) interp; const char *msg; + Var *initialArrayPtr = arrayPtr; + + TclVarFindHiddenArray(varPtr, arrayPtr); /* * Invoke any read traces that have been set for the variable. */ @@ -1433,12 +1434,12 @@ return avhtPtr->defaultObj; } } if (flags & TCL_LEAVE_ERR_MSG) { - if (TclIsVarUndefined(varPtr) && arrayPtr - && !TclIsVarUndefined(arrayPtr)) { + if (TclIsVarUndefined(varPtr) && initialArrayPtr + && !TclIsVarUndefined(initialArrayPtr)) { msg = NOSUCHELEMENT; } else if (TclIsVarArray(varPtr)) { msg = ISARRAY; } else { msg = NOSUCHVAR; @@ -1450,11 +1451,11 @@ * An error. If the variable doesn't exist anymore and no-one's using it, * then free up the relevant structures and hash table entries. */ errorReturn: - Tcl_SetErrorCode(interp, "TCL", "READ", "VARNAME", NULL); + Tcl_SetErrorCode(interp, "TCL", "READ", "VARNAME", (void *)NULL); if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); } return NULL; } @@ -1476,11 +1477,11 @@ *---------------------------------------------------------------------- */ int Tcl_SetObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp,/* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *varValueObj; @@ -1725,11 +1726,11 @@ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ Tcl_Obj *newValuePtr, /* New value for variable. */ - const int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, and + int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, and * TCL_LEAVE_ERR_MSG bits. */ { if (varPtr == NULL) { Tcl_Panic("varPtr must not be NULL"); } @@ -1904,11 +1905,11 @@ * the name of a variable. NULL if the 'index' * parameter is >= 0 */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ Tcl_Obj *newValuePtr, /* New value for variable. */ - const int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, and + int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, and * TCL_LEAVE_ERR_MSG bits. */ int index) /* Index of local var where part1 is to be * found. */ { Interp *iPtr = (Interp *) interp; @@ -1928,15 +1929,15 @@ if (TclIsVarDeadHash(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { if (TclIsVarArrayElement(varPtr)) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", DANGLINGELEMENT, index); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ELEMENT", NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ELEMENT", (void *)NULL); } else { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", DANGLINGVAR, index); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", (void *)NULL); } } goto earlyError; } @@ -1945,14 +1946,16 @@ */ if (TclIsVarArray(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", ISARRAY,index); - Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", (void *)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 @@ -2038,11 +2041,11 @@ * up the relevant structures and hash table entries. */ cleanup: if (resultPtr == NULL) { - Tcl_SetErrorCode(interp, "TCL", "WRITE", "VARNAME", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRITE", "VARNAME", (void *)NULL); } if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); } return resultPtr; @@ -2150,11 +2153,11 @@ Tcl_Obj *part2Ptr, /* If non-null, points to an object holding * the name of an element in the array * part1Ptr. */ Tcl_Obj *incrPtr, /* Increment value. */ /* TODO: Which of these flag values really make sense? */ - const int flags) /* Various flags that tell how to incr value: + int flags) /* Various flags that tell how to incr value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, * TCL_LEAVE_ERR_MSG. */ { if (varPtr == NULL) { @@ -2206,11 +2209,11 @@ Tcl_Obj *part2Ptr, /* If non-null, points to an object holding * the name of an element in the array * part1Ptr. */ Tcl_Obj *incrPtr, /* Increment value. */ /* TODO: Which of these flag values really make sense? */ - const int flags, /* Various flags that tell how to incr value: + int flags, /* Various flags that tell how to incr value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, * TCL_LEAVE_ERR_MSG. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is @@ -2384,11 +2387,11 @@ * containing array otherwise. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ - const int flags) /* OR-ed combination of any of + int flags) /* OR-ed combination of any of * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_LEAVE_ERR_MSG. */ { if (varPtr == NULL) { Tcl_Panic("varPtr must not be NULL"); @@ -2431,19 +2434,20 @@ * containing array otherwise. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ - const int flags, /* OR-ed combination of any of + int flags, /* OR-ed combination of any of * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_LEAVE_ERR_MSG. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { Interp *iPtr = (Interp *) interp; int result = (TclIsVarUndefined(varPtr)? TCL_ERROR : TCL_OK); + Var *initialArrayPtr = arrayPtr; /* * 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 @@ -2451,10 +2455,12 @@ */ 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. @@ -2461,12 +2467,12 @@ */ if (result != TCL_OK) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "unset", - ((arrayPtr == NULL) ? NOSUCHVAR : NOSUCHELEMENT), index); - Tcl_SetErrorCode(interp, "TCL", "UNSET", "VARNAME", NULL); + ((initialArrayPtr == NULL) ? NOSUCHVAR : NOSUCHELEMENT), index); + Tcl_SetErrorCode(interp, "TCL", "UNSET", "VARNAME", (void *)NULL); } } /* * Finally, if the variable is truly not in use then free up its Var @@ -2569,13 +2575,27 @@ } } if ((dummyVar.flags & VAR_TRACED_UNSET) || (arrayPtr && (arrayPtr->flags & VAR_TRACED_UNSET))) { + + /* + * Pass the array element name to TclObjCallVarTraces(), because + * it cannot be determined from dummyVar. Alternatively, indicate + * via flags whether the variable involved in the code that caused + * the trace to be triggered was an array element, for the correct + * formatting of error messages. + */ + if (part2Ptr) { + flags |= VAR_ARRAY_ELEMENT; + } else if (TclIsVarArrayElement(varPtr)) { + part2Ptr = VarHashGetKey(varPtr); + } + dummyVar.flags &= ~VAR_TRACE_ACTIVE; TclObjCallVarTraces(iPtr, arrayPtr, &dummyVar, part1Ptr, part2Ptr, - (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) + (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|VAR_ARRAY_ELEMENT)) | TCL_TRACE_UNSETS, /* leaveErrMsg */ 0, index); /* * The traces that we just called may have triggered a change in @@ -2672,11 +2692,11 @@ *---------------------------------------------------------------------- */ int Tcl_UnsetObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int i, flags = TCL_LEAVE_ERR_MSG; @@ -2739,11 +2759,11 @@ *---------------------------------------------------------------------- */ int Tcl_AppendObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Var *varPtr, *arrayPtr; @@ -2804,19 +2824,19 @@ *---------------------------------------------------------------------- */ int Tcl_LappendObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *varValuePtr, *newValuePtr; - int numElems, createdNewObj; + Tcl_Size numElems; Var *varPtr, *arrayPtr; - int result; + int result, createdNewObj; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "varName ?value ...?"); return TCL_ERROR; } @@ -2833,11 +2853,11 @@ TCL_LEAVE_ERR_MSG); if (newValuePtr == NULL) { return TCL_ERROR; } } else { - result = TclListObjLength(interp, newValuePtr, &numElems); + result = TclListObjLengthM(interp, newValuePtr, &numElems); if (result != TCL_OK) { return result; } } } else { @@ -2891,11 +2911,11 @@ } else if (Tcl_IsShared(varValuePtr)) { varValuePtr = Tcl_DuplicateObj(varValuePtr); createdNewObj = 1; } - result = TclListObjLength(interp, varValuePtr, &numElems); + result = TclListObjLengthM(interp, varValuePtr, &numElems); if (result == TCL_OK) { result = Tcl_ListObjReplace(interp, varValuePtr, numElems, 0, (objc-2), (objv+2)); } if (result != TCL_OK) { @@ -3010,29 +3030,30 @@ return donerc; } static int ArrayForObjCmd( - ClientData clientData, + void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, ArrayForNRCmd, clientData, objc, objv); } static int ArrayForNRCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *varListObj, *arrayNameObj, *scriptObj; ArraySearch *searchPtr = NULL; Var *varPtr; - int isArray, numVars; + int isArray; + Tcl_Size numVars; /* * array for {k v} a body */ @@ -3043,18 +3064,18 @@ /* * Parse arguments. */ - if (Tcl_ListObjLength(interp, objv[1], &numVars) != TCL_OK) { + if (TclListObjLengthM(interp, objv[1], &numVars) != TCL_OK) { return TCL_ERROR; } if (numVars != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have two variable names", -1)); - Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "array", "for", NULL); + Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "array", "for", (void *)NULL); return TCL_ERROR; } arrayNameObj = objv[2]; @@ -3077,10 +3098,13 @@ * 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. @@ -3091,11 +3115,11 @@ return TCL_OK; } static int ArrayForLoopCallback( - ClientData data[], + void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; ArraySearch *searchPtr = (ArraySearch *)data[0]; @@ -3104,11 +3128,12 @@ Tcl_Obj *scriptObj = (Tcl_Obj *)data[3]; Tcl_Obj **varv; Tcl_Obj *keyObj, *valueObj; Var *varPtr; Var *arrayPtr; - int done, varc; + int done; + Tcl_Size varc; /* * Process the result from the previous execution of the script body. */ @@ -3147,18 +3172,21 @@ if (done != TCL_CONTINUE) { Tcl_ResetResult(interp); if (done == TCL_ERROR) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "array changed during iteration", -1)); - Tcl_SetErrorCode(interp, "TCL", "READ", "array", "for", NULL); + Tcl_SetErrorCode(interp, "TCL", "READ", "array", "for", (void *)NULL); varPtr->flags |= TCL_LEAVE_ERR_MSG; result = done; } goto arrayfordone; } - Tcl_ListObjGetElements(NULL, varListObj, &varc, &varv); + result = TclListObjGetElementsM(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; } @@ -3249,11 +3277,11 @@ *---------------------------------------------------------------------- */ static int ArrayStartSearchCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Var *varPtr; @@ -3344,11 +3372,11 @@ *---------------------------------------------------------------------- */ static int ArrayAnyMoreCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; @@ -3422,11 +3450,11 @@ *---------------------------------------------------------------------- */ static int ArrayNextElementCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Var *varPtr; @@ -3502,11 +3530,11 @@ *---------------------------------------------------------------------- */ static int ArrayDoneSearchCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; @@ -3562,11 +3590,11 @@ *---------------------------------------------------------------------- */ static int ArrayExistsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *)interp; @@ -3602,21 +3630,22 @@ *---------------------------------------------------------------------- */ static int ArrayGetCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Var *varPtr, *varPtr2; Tcl_Obj *varNameObj, *nameObj, *valueObj, *nameLstObj, *tmpResObj; Tcl_Obj **nameObjPtr, *patternObj; Tcl_HashSearch search; const char *pattern; - int i, count, result, isArray; + Tcl_Size i, count; + int result, isArray; switch (objc) { case 2: varNameObj = objv[1]; patternObj = NULL; @@ -3694,11 +3723,11 @@ /* * Get the array values corresponding to each element name. */ TclNewObj(tmpResObj); - result = Tcl_ListObjGetElements(interp, nameLstObj, &count, &nameObjPtr); + result = TclListObjGetElementsM(interp, nameLstObj, &count, &nameObjPtr); if (result != TCL_OK) { goto errorInArrayGet; } for (i=0 ; i 4)) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName ?mode? ?pattern?"); return TCL_ERROR; } @@ -3837,11 +3866,11 @@ nameObj = VarHashGetKey(varPtr2); if (patternObj) { const char *name = TclGetString(nameObj); int matched = 0; - switch ((enum arrayNamesOptionsEnum) mode) { + switch (mode) { case OPT_EXACT: Tcl_Panic("exact matching shouldn't get here"); case OPT_GLOB: matched = Tcl_StringMatch(name, pattern); break; @@ -3904,11 +3933,11 @@ if (TclIsVarUndefined(varPtr)) { continue; } nameObj = VarHashGetKey(varPtr); - hPtr = Tcl_CreateHashEntry(tablePtr, (char *) nameObj, &dummy); + hPtr = Tcl_CreateHashEntry(tablePtr, nameObj, &dummy); Tcl_SetHashValue(hPtr, nameObj); } } /* @@ -3928,19 +3957,19 @@ *---------------------------------------------------------------------- */ static int ArraySetCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *arrayNameObj; Tcl_Obj *arrayElemObj; Var *varPtr, *arrayPtr; - int result, i; + int result; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName list"); return TCL_ERROR; } @@ -3958,28 +3987,29 @@ } if (arrayPtr) { CleanupVar(varPtr, arrayPtr); TclObjVarErrMsg(interp, arrayNameObj, NULL, "set", NEEDARRAY, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", - TclGetString(arrayNameObj), NULL); + TclGetString(arrayNameObj), (void *)NULL); return TCL_ERROR; } /* * Install the contents of the dictionary or list into the array. */ arrayElemObj = objv[2]; - if (TclHasIntRep(arrayElemObj, &tclDictType) && arrayElemObj->bytes == NULL) { + if (TclHasInternalRep(arrayElemObj, &tclDictType) && arrayElemObj->bytes == NULL) { Tcl_Obj *keyPtr, *valuePtr; Tcl_DictSearch search; int done; + Tcl_Size size; - if (Tcl_DictObjSize(interp, arrayElemObj, &done) != TCL_OK) { + if (Tcl_DictObjSize(interp, arrayElemObj, &size) != TCL_OK) { return TCL_ERROR; } - if (done == 0) { + if (size == 0) { /* * Empty, so we'll just force the array to be properly existing * instead. */ @@ -4014,35 +4044,43 @@ /* * Not a dictionary, so assume (and convert to, for backward- * -compatibility reasons) a list. */ - int elemLen; + Tcl_Size elemLen; Tcl_Obj **elemPtrs, *copyListObj; + Tcl_Size i; - result = TclListObjGetElements(interp, arrayElemObj, - &elemLen, &elemPtrs); + result = TclListObjLengthM(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", NULL); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "FORMAT", (void *)NULL); return TCL_ERROR; } if (elemLen == 0) { goto ensureArray; + } + result = TclListObjGetElementsM(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 ; ivalue.linkPtr; if (linkPtr == otherPtr) { @@ -4756,13 +4794,13 @@ if (!TclIsVarDeadHash(varPtr)) { namePtr = VarHashGetKey(varPtr); Tcl_AppendObjToObj(objPtr, namePtr); } } else if (iPtr->varFramePtr->procPtr) { - int index = varPtr - iPtr->varFramePtr->compiledLocals; + Tcl_Size index = varPtr - iPtr->varFramePtr->compiledLocals; - if (index >= 0 && index < iPtr->varFramePtr->numCompiledLocals) { + if (index < iPtr->varFramePtr->numCompiledLocals) { namePtr = localName(iPtr->varFramePtr, index); Tcl_AppendObjToObj(objPtr, namePtr); } } } @@ -4784,11 +4822,11 @@ *---------------------------------------------------------------------- */ int Tcl_GlobalObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -4888,11 +4926,11 @@ *---------------------------------------------------------------------- */ int Tcl_VariableObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -4920,11 +4958,11 @@ * non-NULL, it is, so throw up an error and return. */ TclObjVarErrMsg(interp, varNamePtr, NULL, "define", ISARRAYELEMENT, -1); - Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL); + Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", (void *)NULL); return TCL_ERROR; } if (varPtr == NULL) { return TCL_ERROR; @@ -5021,11 +5059,11 @@ *---------------------------------------------------------------------- */ int Tcl_UpvarObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { CallFrame *framePtr; @@ -5071,11 +5109,11 @@ */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad level \"%s\"", TclGetString(levelObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", - TclGetString(levelObj), NULL); + TclGetString(levelObj), (void *)NULL); return TCL_ERROR; } /* * We've now finished with parsing levels; skip to the variable names. @@ -5162,11 +5200,11 @@ handle, TclGetString(varNamePtr))); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't find search \"%s\"", handle)); } - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", handle, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", handle, (void *)NULL); return NULL; } /* *---------------------------------------------------------------------- @@ -5382,11 +5420,11 @@ Interp *iPtr, /* Interpreter to which variables belong. */ CallFrame *framePtr) /* Procedure call frame containing compiler- * assigned local variables to delete. */ { Var *varPtr; - int numLocals, i; + Tcl_Size numLocals, i; Tcl_Obj **namePtrPtr; numLocals = framePtr->numCompiledLocals; varPtr = framePtr->compiledLocals; namePtrPtr = &localName(framePtr, 0); @@ -5580,14 +5618,14 @@ static void FreeLocalVarName( Tcl_Obj *objPtr) { - int index; + Tcl_Size index; Tcl_Obj *namePtr; - LocalGetIntRep(objPtr, index, namePtr); + LocalGetInternalRep(objPtr, index, namePtr); index++; /* Compiler warning bait. */ if (namePtr) { Tcl_DecrRefCount(namePtr); } @@ -5596,18 +5634,18 @@ static void DupLocalVarName( Tcl_Obj *srcPtr, Tcl_Obj *dupPtr) { - int index; + Tcl_Size index; Tcl_Obj *namePtr; - LocalGetIntRep(srcPtr, index, namePtr); + LocalGetInternalRep(srcPtr, index, namePtr); if (!namePtr) { namePtr = srcPtr; } - LocalSetIntRep(dupPtr, index, namePtr); + LocalSetInternalRep(dupPtr, index, namePtr); } /* * parsedVarName - * @@ -5622,11 +5660,11 @@ Tcl_Obj *objPtr) { Tcl_Obj *arrayPtr, *elem; int parsed; - ParsedGetIntRep(objPtr, parsed, arrayPtr, elem); + ParsedGetInternalRep(objPtr, parsed, arrayPtr, elem); parsed++; /* Silence compiler. */ if (arrayPtr != NULL) { TclDecrRefCount(arrayPtr); TclDecrRefCount(elem); @@ -5639,14 +5677,14 @@ Tcl_Obj *dupPtr) { Tcl_Obj *arrayPtr, *elem; int parsed; - ParsedGetIntRep(srcPtr, parsed, arrayPtr, elem); + ParsedGetInternalRep(srcPtr, parsed, arrayPtr, elem); parsed++; /* Silence compiler. */ - ParsedSetIntRep(dupPtr, arrayPtr, elem); + ParsedSetInternalRep(dupPtr, arrayPtr, elem); } /* *---------------------------------------------------------------------- * @@ -5806,11 +5844,11 @@ Tcl_DecrRefCount(simpleNamePtr); } if ((varPtr == NULL) && (flags & TCL_LEAVE_ERR_MSG)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown variable \"%s\"", name)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", name, NULL); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", name, (void *)NULL); } return (Tcl_Var) varPtr; } /* @@ -5837,11 +5875,11 @@ *---------------------------------------------------------------------- */ int TclInfoVarsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -6028,11 +6066,11 @@ *---------------------------------------------------------------------- */ int TclInfoGlobalsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *varName, *pattern; @@ -6121,11 +6159,11 @@ *---------------------------------------------------------------------- */ int TclInfoLocalsCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; @@ -6180,11 +6218,12 @@ 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_Size i, localVarCt; + int added; Tcl_Obj *objNamePtr; const char *varName; TclVarHashTable *localVarTablePtr; Tcl_HashSearch search; Tcl_HashTable addedTable; @@ -6332,10 +6371,11 @@ 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 *), @@ -6426,22 +6466,22 @@ *---------------------------------------------------------------------- */ static int ArrayDefaultCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const options[] = { "get", "set", "exists", "unset", NULL }; - enum arrayDefaultOptionsEnum { OPT_GET, OPT_SET, OPT_EXISTS, OPT_UNSET }; + enum arrayDefaultOptionsEnum { OPT_GET, OPT_SET, OPT_EXISTS, OPT_UNSET } option; Tcl_Obj *arrayNameObj, *defaultValueObj; Var *varPtr, *arrayPtr; - int isArray, option; + int isArray; /* * Parse arguments. */ @@ -6458,11 +6498,11 @@ if (TCL_ERROR == LocateArray(interp, arrayNameObj, &varPtr, &isArray)) { return TCL_ERROR; } - switch ((enum arrayDefaultOptionsEnum)option) { + switch (option) { case OPT_GET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "arrayName"); return TCL_ERROR; } @@ -6473,11 +6513,11 @@ defaultValueObj = TclGetArrayDefault(varPtr); if (!defaultValueObj) { /* Array default must exist. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "array has no default value", -1)); - Tcl_SetErrorCode(interp, "TCL", "READ", "ARRAY", "DEFAULT", NULL); + Tcl_SetErrorCode(interp, "TCL", "READ", "ARRAY", "DEFAULT", (void *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, defaultValueObj); return TCL_OK; @@ -6503,21 +6543,21 @@ CleanupVar(varPtr, arrayPtr); TclObjVarErrMsg(interp, arrayNameObj, NULL, "array default set", NEEDARRAY, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", - TclGetString(arrayNameObj), NULL); + TclGetString(arrayNameObj), (void *)NULL); return TCL_ERROR; } if (!TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) { /* * Not an array. */ TclObjVarErrMsg(interp, arrayNameObj, NULL, "array default set", NEEDARRAY, -1); - Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); + Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", (void *)NULL); return TCL_ERROR; } if (!TclIsVarArray(varPtr)) { TclInitArrayVar(varPtr); @@ -6586,10 +6626,11 @@ * Regular TclVarHashTable initialization. */ arrayPtr->value.tablePtr = (TclVarHashTable *) tablePtr; TclInitVarHashTable(arrayPtr->value.tablePtr, TclGetVarNsPtr(arrayPtr)); + arrayPtr->value.tablePtr->arrayPtr = arrayPtr; /* * Default value initialization. */ Index: generic/tclZipfs.c ================================================================== --- generic/tclZipfs.c +++ generic/tclZipfs.c @@ -1,72 +1,99 @@ /* * tclZipfs.c -- * * Implementation of the ZIP filesystem used in TIP 430 - * Adapted from the implentation for AndroWish. + * Adapted from the implementation for AndroWish. * - * Copyright (c) 2016-2017 Sean Woods - * Copyright (c) 2013-2015 Christian Werner + * Copyright © 2016-2017 Sean Woods + * Copyright © 2013-2015 Christian Werner * * 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 #ifndef _WIN32 #include #endif /* _WIN32*/ #ifndef MAP_FILE #define MAP_FILE 0 #endif /* !MAP_FILE */ #define NOBYFOUR -#define crc32tab crc_table[0] #ifndef TBLS #define TBLS 1 #endif + +#if !defined(_WIN32) && !defined(NO_DLFCN_H) +#include +#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", (void *)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, (void *)NULL); \ + } \ + } while (0) #ifdef HAVE_ZLIB #include "zlib.h" #include "crypt.h" #include "zutil.h" #include "crc32.h" -#ifdef CFG_RUNTIME_DLLFILE +static const z_crc_t* crc32tab; /* ** We are compiling as part of the core. ** TIP430 style zipfs prefix */ #define ZIPFS_VOLUME "//zipfs:/" +#define ZIPFS_ROOTDIR_DEPTH 3 /* Number of / in root mount */ #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 */ +#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 */ @@ -132,70 +159,29 @@ #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 */ +#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 { @@ -208,16 +194,17 @@ 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 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 */ - size_t mountPointLen; /* Length of mount point name */ + Tcl_Size mountPointLen; /* Length of mount point name */ #ifdef _WIN32 HANDLE mountHandle; /* Handle used for direct file access. */ #endif /* _WIN32 */ } ZipFile; @@ -226,50 +213,73 @@ */ typedef struct ZipEntry { char *name; /* The full pathname of the virtual file */ ZipFile *zipFilePtr; /* The ZIP file holding this virtual file */ - Tcl_WideInt offset; /* Data offset into memory mapped ZIP file */ - int numBytes; /* Uncompressed size of the virtual file */ - int numCompressedBytes; /* Compressed size of the virtual file */ + size_t offset; /* Data offset into memory mapped ZIP file */ + int numBytes; /* Uncompressed size of the virtual file. + -1 for zip64 */ + int numCompressedBytes; /* Compressed size of the virtual file. + -1 for zip64 */ int compressMethod; /* Compress method */ - int isDirectory; /* Set to 1 if directory, or -1 if root */ + int isDirectory; /* 0 if file, 1 if directory, -1 if root */ int depth; /* Number of slashes in path. */ - int crc32; /* CRC-32 */ + int crc32; /* CRC-32 as stored in ZIP */ int timestamp; /* Modification time */ int isEncrypted; /* True if data is encrypted */ + int flags; +#define ZE_F_CRC_COMPARED 0x0001 /* If 1, the CRC has been compared. */ +#define ZE_F_CRC_CORRECT 0x0002 /* Only meaningful if ZE_F_CRC_COMPARED is 1 */ +#define ZE_F_VOLUME 0x0004 /* Entry corresponds to //zipfs:/ */ unsigned char *data; /* File data if written */ struct ZipEntry *next; /* Next file in the same archive */ struct ZipEntry *tnext; /* Next top-level dir in archive */ } ZipEntry; /* * File channel for file contained in mounted ZIP archive. + * + * Regarding data buffers: + * For READ-ONLY files that are not encrypted and not compressed (zip STORE + * method), ubuf points directly to the mapped zip file data in memory. No + * additional storage is allocated and so ubufToFree is NULL. + * + * In all other combinations of compression and encryption or if channel is + * writable, storage is allocated for the decrypted and/or uncompressed data + * and a pointer to it is stored in ubufToFree and ubuf. When channel is + * closed, ubufToFree is freed if not NULL. ubuf is irrelevant since it may + * or may not point to allocated storage as above. */ typedef struct ZipChannel { ZipFile *zipFilePtr; /* The ZIP file holding this channel */ ZipEntry *zipEntryPtr; /* Pointer back to virtual file */ - size_t maxWrite; /* Maximum size for write */ - size_t numBytes; /* Number of bytes of uncompressed data */ - size_t numRead; /* Position of next byte to be read from the - * channel */ + 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 */ - int iscompr; /* True if data is compressed */ + 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 isWriting; /* True if open for writing */ + int mode; /* O_WRITE, O_APPEND, O_TRUNC etc.*/ unsigned long keys[3]; /* Key for decryption */ } ZipChannel; +static inline int ZipChannelWritable(ZipChannel *info) { + return (info->mode & (O_WRONLY | O_RDWR)) != 0; +} /* * Global variables. * * Most are kept in single ZipFS struct. When build with threading support * this struct is protected by the ZipFSMutex (see below). * - * The "fileHash" component is the process wide global table of all known ZIP + * The "fileHash" component is the process-wide global table of all known ZIP * archive members in all mounted ZIP archives. * * The "zipHash" components is the process wide global table of all mounted * ZIP archive files. */ @@ -276,16 +286,22 @@ static struct { int initialized; /* True when initialized */ int lock; /* RW lock, see below */ int waiters; /* RW lock, see below */ - int wrmax; /* Maximum write size of a file */ + int wrmax; /* Maximum write size of a file; only written + * to from Tcl code in a trusted interpreter, + * so NOT protected by mutex. */ + char *fallbackEntryEncoding;/* The fallback encoding for ZIP entries when + * they are believed to not be UTF-8; only + * written to from Tcl code in a trusted + * interpreter, so not protected by mutex. */ int idCount; /* Counter for channel names */ Tcl_HashTable fileHash; /* File name to ZipEntry mapping */ Tcl_HashTable zipHash; /* Mount to ZipFile mapping */ } ZipFS = { - 0, 0, 0, DEFAULT_WRITE_MAX_SIZE, 0, + 0, 0, 0, DEFAULT_WRITE_MAX_SIZE, NULL, 0, {0,{0,0,0,0},0,0,0,0,0,0,0,0,0}, {0,{0,0,0,0},0,0,0,0,0,0,0,0,0} }; /* @@ -298,14 +314,43 @@ static const char *zipfs_literal_tcl_library = NULL; /* Function prototypes */ -static inline int DescribeMounted(Tcl_Interp *interp, +static int CopyImageFile(Tcl_Interp *interp, const char *imgName, + Tcl_Channel out); +static int DescribeMounted(Tcl_Interp *interp, const char *mountPoint); -static inline int ListMountPoints(Tcl_Interp *interp); +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); @@ -313,10 +358,13 @@ 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); @@ -323,19 +371,20 @@ 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 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 Tcl_WideInt ZipChannelWideSeek(void *instanceData, Tcl_WideInt offset, - int mode, int *errloc); +static long long ZipChannelWideSeek(void *instanceData, + long long offset, int mode, int *errloc); static void ZipChannelWatchChannel(void *instanceData, int mask); static int ZipChannelWrite(void *instanceData, const char *buf, int toWrite, int *errloc); @@ -370,39 +419,146 @@ NULL, /* deleteFileProc */ NULL, /* copyFileProc */ NULL, /* renameFileProc */ NULL, /* copyDirectoryProc */ NULL, /* lstatProc */ - (Tcl_FSLoadFileProc *)(void *)ZipFSLoadFile, + (Tcl_FSLoadFileProc *) (void *) ZipFSLoadFile, NULL, /* getCwdProc */ NULL, /* chdirProc */ }; /* * The channel type/driver definition used for ZIP archive members. */ static Tcl_ChannelType ZipChannelType = { - "zip", /* Type name. */ + "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 */ + 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 -- * @@ -420,11 +576,11 @@ #if TCL_THREADS static Tcl_Condition ZipFSCond; -static void +static inline void ReadLock(void) { Tcl_MutexLock(&ZipFSMutex); while (ZipFS.lock < 0) { ZipFS.waiters++; @@ -433,11 +589,11 @@ } ZipFS.lock++; Tcl_MutexUnlock(&ZipFSMutex); } -static void +static inline void WriteLock(void) { Tcl_MutexLock(&ZipFSMutex); while (ZipFS.lock != 0) { ZipFS.waiters++; @@ -446,11 +602,11 @@ } ZipFS.lock = -1; Tcl_MutexUnlock(&ZipFSMutex); } -static void +static inline void Unlock(void) { Tcl_MutexLock(&ZipFSMutex); if (ZipFS.lock > 0) { --ZipFS.lock; @@ -566,15 +722,15 @@ * None. * *------------------------------------------------------------------------- */ -static int +static inline size_t CountSlashes( const char *string) { - int count = 0; + size_t count = 0; const char *p = string; while (*p != '\0') { if (*p == '/') { count++; @@ -582,176 +738,380 @@ 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; +} + /* *------------------------------------------------------------------------- * - * CanonicalPath -- + * DecodeZipEntryText -- * - * This function computes the canonical path from a directory and file - * name components into the specified Tcl_DString. + * 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 = Tcl_GetStringFromObj(normalizedObj, &normalizedLen); + Tcl_DStringFree(&dsJoin); + Tcl_DStringAppend(dsPtr, normalizedPath, normalizedLen); + Tcl_DecrRefCount(normalizedObj); + return TCL_OK; + +invalidMountPath: + if (interp) { + Tcl_SetObjResult(interp, + Tcl_ObjPrintf("Invalid mount path \"%s\"", mountPath)); + ZIPFS_ERROR_CODE(interp, "MOUNT_PATH"); + } + +errorReturn: + Tcl_DStringFree(&dsJoin); + return TCL_ERROR; +} + +/* + *------------------------------------------------------------------------ + * + * MapPathToZipfs -- + * + * Maps a path as stored in a zip archive to its normalized location + * under a given zipfs mount point. Relative paths and Unix style + * absolute paths go directly under the mount point. Volume relative + * paths and absolute paths that have a volume (drive or UNC) are + * stripped of the volume before joining the mount point. * * Results: - * Returns the pointer to the canonical path contained in the specified - * Tcl_DString. + * Pointer to normalized path. * * Side effects: - * Modifies the specified Tcl_DString. + * Stores mapped path in dsPtr. * - *------------------------------------------------------------------------- + *------------------------------------------------------------------------ */ - 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); +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 = Tcl_GetStringFromObj(normalizedObj, &normalizedLen); + Tcl_DStringAppend(dsPtr, normalizedPath, normalizedLen); + Tcl_DecrRefCount(normalizedObj); return Tcl_DStringValue(dsPtr); } /* *------------------------------------------------------------------------- @@ -770,60 +1130,180 @@ * None. * *------------------------------------------------------------------------- */ -static ZipEntry * +static inline ZipEntry * ZipFSLookup( - char *filename) + const char *filename) { Tcl_HashEntry *hPtr; ZipEntry *z = NULL; hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, filename); if (hPtr) { - z = (ZipEntry *)Tcl_GetHashValue(hPtr); + z = (ZipEntry *) Tcl_GetHashValue(hPtr); } return z; } /* *------------------------------------------------------------------------- * - * ZipFSLookupMount -- + * ZipFSLookupZip -- * - * This function returns an indication if the given file name corresponds - * to a mounted ZIP archive file. + * This function gets the structure for a mounted ZIP archive. * * Results: - * Returns true, if the given file name is a mounted ZIP archive file. + * Returns a pointer to the structure, or NULL if the file is ZIP file is + * unknown/not mounted. * * Side effects: * None. * *------------------------------------------------------------------------- */ -#ifdef NEVER_USED +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 -ZipFSLookupMount( - char *filename) +ContainsMountPoint (const char *path, int pathLen) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; + if (ZipFS.zipHash.numEntries == 0) { + return 0; + } + if (pathLen < 0) + pathLen = strlen(path); + + /* + * We are looking for the case where the path is //zipfs:/a/b + * and there is a mount point //zipfs:/a/b/c/.. below it + */ for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; - hPtr = Tcl_NextHashEntry(&search)) { - ZipFile *zf = Tcl_GetHashValue(hPtr); + hPtr = Tcl_NextHashEntry(&search)) { + ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr); - if (strcmp(zf->mountPoint, filename) == 0) { + 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; } -#endif /* NEVER_USED */ + +/* + *------------------------------------------------------------------------- + * + * AllocateZipFile, AllocateZipEntry, AllocateZipChannel -- + * + * Allocates the memory for a datastructure. Always ensures that it is + * zeroed out for safety. + * + * Returns: + * The allocated structure, or NULL if allocate fails. + * + * Side effects: + * The interpreter result may be written to on error. Which might fail + * (for ZipFile) in a low-memory situation. Always panics if ZipEntry + * allocation fails. + * + *------------------------------------------------------------------------- + */ + +static inline ZipFile * +AllocateZipFile( + Tcl_Interp *interp, + size_t mountPointNameLength) +{ + size_t size = sizeof(ZipFile) + mountPointNameLength + 1; + ZipFile *zf = (ZipFile *) Tcl_AttemptAlloc(size); + + if (!zf) { + ZIPFS_MEM_ERROR(interp); + } else { + memset(zf, 0, size); + } + return zf; +} + +static inline ZipEntry * +AllocateZipEntry(void) +{ + ZipEntry *z = (ZipEntry *) Tcl_Alloc(sizeof(ZipEntry)); + memset(z, 0, sizeof(ZipEntry)); + return z; +} + +static inline ZipChannel * +AllocateZipChannel( + Tcl_Interp *interp) +{ + ZipChannel *zc = (ZipChannel *) Tcl_AttemptAlloc(sizeof(ZipChannel)); + + if (!zc) { + ZIPFS_MEM_ERROR(interp); + } else { + memset(zc, 0, sizeof(ZipChannel)); + } + return zc; +} /* *------------------------------------------------------------------------- * * ZipFSCloseArchive -- @@ -856,10 +1336,14 @@ } 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; } @@ -867,20 +1351,20 @@ CloseHandle(zf->mountHandle); } #else /* !_WIN32 */ if ((zf->data != MAP_FAILED) && !zf->ptrToFree) { munmap(zf->data, zf->length); - zf->data = (unsigned char *)MAP_FAILED; + zf->data = (unsigned char *) MAP_FAILED; } #endif /* _WIN32 */ if (zf->ptrToFree) { Tcl_Free(zf->ptrToFree); zf->ptrToFree = NULL; } if (zf->chan) { - Tcl_CloseEx(interp, zf->chan, 0); + Tcl_Close(interp, zf->chan); zf->chan = NULL; } } /* @@ -888,19 +1372,20 @@ * * ZipFSFindTOC -- * * This function takes a memory mapped zip file and indexes the contents. * When "needZip" is zero an embedded ZIP archive in an executable file - * is accepted. + * is accepted. Note that we do not support ZIP64. * * Results: * TCL_OK on success, TCL_ERROR otherwise with an error message placed * into the given "interp" if it is not NULL. * * Side effects: - * The given ZipFile struct is filled with information about the ZIP - * archive file. + * The given ZipFile struct is filled with information about the ZIP + * archive file. On error, ZipFSCloseArchive is called on zf but + * it is not freed. * *------------------------------------------------------------------------- */ static int @@ -907,100 +1392,182 @@ ZipFSFindTOC( Tcl_Interp *interp, /* Current interpreter. NULLable. */ int needZip, ZipFile *zf) { - size_t i; - unsigned char *p, *q; + size_t i, minoff; + const unsigned char *eocdPtr; /* End of Central Directory Record */ + const unsigned char *start = zf->data; + const unsigned char *end = zf->data + zf->length; - 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) { + /* + * 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; } - p -= ZIP_SIG_LEN; + eocdPtr -= ZIP_SIG_LEN; } else { - --p; + --eocdPtr; } } - if (p < zf->data) { + if (eocdPtr < zf->data) { + /* + * Didn't find it (or not enough space for a central directory!); not + * a ZIP archive. This might be OK or a problem. + */ + if (!needZip) { zf->baseOffset = zf->passOffset = zf->length; return TCL_OK; } - ZIPFS_ERROR(interp, "wrong end signature"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "END_SIG", NULL); - } - goto error; + ZIPFS_ERROR(interp, "archive directory end signature not found"); + ZIPFS_ERROR_CODE(interp, "END_SIG"); + + error: + ZipFSCloseArchive(interp, zf); + return TCL_ERROR; + } - zf->numFiles = ZipReadShort(p + ZIP_CENTRAL_ENTS_OFFS); + + /* + * eocdPtr -> End of Central Directory (EOCD) record at this point. + * Note this is not same as "end of Central Directory" :-) as EOCD + * is a record/structure in the ZIP spec terminology + */ + + /* + * How many files in the archive? If that's bogus, we're done here. + */ + + zf->numFiles = ZipReadShort(start, end, eocdPtr + ZIP_CENTRAL_ENTS_OFFS); if (zf->numFiles == 0) { if (!needZip) { zf->baseOffset = zf->passOffset = zf->length; return TCL_OK; } ZIPFS_ERROR(interp, "empty archive"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "EMPTY", NULL); - } + ZIPFS_ERROR_CODE(interp, "EMPTY"); goto error; } - q = zf->data + ZipReadInt(p + ZIP_CENTRAL_DIRSTART_OFFS); - p -= ZipReadInt(p + ZIP_CENTRAL_DIRSIZE_OFFS); - if ((p < zf->data) || (p > zf->data + zf->length) - || (q < zf->data) || (q > zf->data + zf->length)) { + + /* + * The Central Directory (CD) is a series of Central Directory File + * Header (CDFH) records preceding the EOCD (but not necessarily + * immediately preceding). cdirZipOffset is the offset into the + * *archive* to the CD (first CDFH). The size of the CD is given by + * cdirSize. NOTE: offset into archive does NOT mean offset into + * (zf->data) as other data may precede the archive in the file. + */ + ptrdiff_t eocdDataOffset = eocdPtr - zf->data; + unsigned int cdirZipOffset = ZipReadInt(start, end, eocdPtr + ZIP_CENTRAL_DIRSTART_OFFS); + unsigned int cdirSize = ZipReadInt(start, end, eocdPtr + ZIP_CENTRAL_DIRSIZE_OFFS); + + /* + * As computed above, + * eocdDataOffset < zf->length. + * In addition, the following consistency checks must be met + * (1) cdirZipOffset <= eocdDataOffset (to prevent under flow in computation of (2)) + * (2) cdirZipOffset + cdirSize <= eocdDataOffset. Else the CD will be overlapping + * the EOCD. Note this automatically means cdirZipOffset+cdirSize < zf->length. + */ + if (!(cdirZipOffset <= (size_t)eocdDataOffset && + cdirSize <= eocdDataOffset - cdirZipOffset)) { if (!needZip) { - zf->baseOffset = zf->passOffset = zf->length; + /* Simply point to end od data */ + zf->directoryOffset = zf->baseOffset = zf->passOffset = zf->length; return TCL_OK; } - ZIPFS_ERROR(interp, "archive directory not found"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_DIR", NULL); - } - 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, "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"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "HDR_SIG", NULL); - } + ZIPFS_ERROR_CODE(interp, "HDR_SIG"); + goto error; + } + int pathlen = ZipReadShort(start, end, dirEntry + ZIP_CENTRAL_PATHLEN_OFFS); + int comlen = ZipReadShort(start, end, dirEntry + ZIP_CENTRAL_FCOMMENTLEN_OFFS); + int extra = ZipReadShort(start, end, dirEntry + ZIP_CENTRAL_EXTRALEN_OFFS); + size_t localhdr_off = ZipReadInt(start, end, dirEntry + ZIP_CENTRAL_LOCALHDR_OFFS); + const unsigned char *localP = zf->data + zf->baseOffset + localhdr_off; + if (localP > (cdirStart - ZIP_LOCAL_HEADER_LEN) || + ZipReadInt(start, end, localP) != ZIP_LOCAL_HEADER_SIG) { + ZIPFS_ERROR(interp, "Failed to find local header"); + ZIPFS_ERROR_CODE(interp, "LCL_HDR"); goto error; } - pathlen = ZipReadShort(q + ZIP_CENTRAL_PATHLEN_OFFS); - comlen = ZipReadShort(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); - extra = ZipReadShort(q + ZIP_CENTRAL_EXTRALEN_OFFS); - q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN; + if (localhdr_off < minoff) { + minoff = localhdr_off; + } + dirEntry += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN; } - q = zf->data + zf->baseOffset; - if ((zf->baseOffset >= 6) && (ZipReadInt(q - 4) == ZIP_PASSWORD_END_SIG)) { + 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]; - if (q - 5 - i > zf->data) { + passPtr = q - 5 - i; + if (passPtr >= start && passPtr + i < end) { zf->passBuf[0] = i; - memcpy(zf->passBuf + 1, q - 5 - i, i); + memcpy(zf->passBuf + 1, passPtr, i); zf->passOffset -= i ? (5 + i) : 0; } } + return TCL_OK; - - error: - ZipFSCloseArchive(interp, zf); - return TCL_ERROR; } /* *------------------------------------------------------------------------- * @@ -1012,11 +1579,12 @@ * function to succeed. When "needZip" is zero an embedded ZIP archive in * an executable file is accepted. * * Results: * TCL_OK on success, TCL_ERROR otherwise with an error message placed - * into the given "interp" if it is not NULL. + * into the given "interp" if it is not NULL. On error, ZipFSCloseArchive + * is called on zf but it is not freed. * * Side effects: * ZIP archive is memory mapped or read into allocated memory, the given * ZipFile struct is filled with information about the ZIP archive file. * @@ -1037,201 +1605,305 @@ zf->isMemBuffer = 0; #ifdef _WIN32 zf->data = NULL; zf->mountHandle = INVALID_HANDLE_VALUE; #else /* !_WIN32 */ - zf->data = (unsigned char *)MAP_FAILED; + zf->data = (unsigned char *) MAP_FAILED; #endif /* _WIN32 */ zf->length = 0; zf->numFiles = 0; zf->baseOffset = zf->passOffset = 0; zf->ptrToFree = NULL; zf->passBuf[0] = 0; + + /* + * Actually open the file. + */ + zf->chan = Tcl_OpenFileChannel(interp, zipname, "rb", 0); if (!zf->chan) { return TCL_ERROR; } - if (Tcl_GetChannelHandle(zf->chan, TCL_READABLE, &handle) != TCL_OK) { + + /* + * 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 == TCL_IO_FAILURE) { + if (zf->length == (size_t) TCL_INDEX_NONE) { ZIPFS_POSIX_ERROR(interp, "seek error"); goto error; } - if ((zf->length - ZIP_CENTRAL_END_LEN) - > (64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) { + /* 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"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "FILE_SIZE", NULL); - } + 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); + 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); - } + 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; } - 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 */ - } + } + /* + * 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; } /* *------------------------------------------------------------------------- * - * ZipFSRootNode -- + * ZipMapArchive -- * - * This function generates the root node for a ZIPFS filesystem. + * 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. + * into the given "interp" if it is not NULL. On error, frees zf!! * * Side effects: - * ... + * Will acquire and release the write lock. * *------------------------------------------------------------------------- */ static int ZipFSCatalogFilesystem( Tcl_Interp *interp, /* Current interpreter. NULLable. */ - ZipFile *zf0, - const char *mountPoint, /* Mount point path. */ + ZipFile *zf, /* Temporary buffer hold archive descriptors */ + const char *mountPoint, /* Mount point path. Must be fully normalized */ const char *passwd, /* Password for opening the ZIP, or NULL if * the ZIP is unprotected. */ const char *zipname) /* Path to ZIP file to build a catalog of. */ { - int pwlen, isNew; - size_t i; - ZipFile *zf; + int isNew; + size_t i, pwlen; + ZipFile *zf0; ZipEntry *z; Tcl_HashEntry *hPtr; - Tcl_DString ds, dsm, fpBuf; + Tcl_DString ds, fpBuf; unsigned char *q; + + assert(TclIsZipfsPath(mountPoint)); /* Caller should have normalized */ + + Tcl_DStringInit(&ds); /* * Basic verification of the password for sanity. */ pwlen = 0; if (passwd) { pwlen = strlen(passwd); - if ((pwlen > 255) || strchr(passwd, 0xff)) { - if (interp) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("illegal password", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_PASS", NULL); - } + 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(); - /* - * 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); + zf0 = (ZipFile *) Tcl_GetHashValue(hPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "%s is already mounted on %s", zf->name, mountPoint)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "MOUNTED", NULL); - } - 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); + "%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); + 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; @@ -1239,73 +1911,77 @@ zf->passBuf[k++] = (passwd[i] & 0x0f) | pwrot[(passwd[i] >> 4) & 0x0f]; } zf->passBuf[k] = '\0'; } + /* TODO - is this test necessary? When will mountPoint[0] be \0 ? */ if (mountPoint[0] != '\0') { hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, mountPoint, &isNew); if (isNew) { - z = (ZipEntry *)Tcl_Alloc(sizeof(ZipEntry)); + z = AllocateZipEntry(); Tcl_SetHashValue(hPtr, z); - z->tnext = NULL; z->depth = CountSlashes(mountPoint); + assert(z->depth >= ZIPFS_ROOTDIR_DEPTH); z->zipFilePtr = zf; z->isDirectory = (zf->baseOffset == 0) ? 1 : -1; /* root marker */ - z->isEncrypted = 0; z->offset = zf->baseOffset; - z->crc32 = 0; - z->timestamp = 0; - z->numBytes = z->numCompressedBytes = 0; z->compressMethod = ZIP_COMPMETH_STORED; - z->data = NULL; - z->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + z->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + if (!strcmp(z->name, ZIPFS_VOLUME)) { + z->flags |= ZE_F_VOLUME; /* Mark as root volume */ + } + Tcl_Time t; + Tcl_GetTime(&t); + z->timestamp = t.sec; z->next = zf->entries; zf->entries = z; } } q = zf->data + zf->directoryOffset; Tcl_DStringInit(&fpBuf); for (i = 0; i < zf->numFiles; i++) { + const unsigned char *start = zf->data; + const unsigned char *end = zf->data + zf->length; int extra, isdir = 0, dosTime, dosDate, nbcompr; size_t offs, pathlen, comlen; unsigned char *lq, *gq = NULL; char *fullpath, *path; - pathlen = ZipReadShort(q + ZIP_CENTRAL_PATHLEN_OFFS); - comlen = ZipReadShort(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); - extra = ZipReadShort(q + ZIP_CENTRAL_EXTRALEN_OFFS); + pathlen = ZipReadShort(start, end, q + ZIP_CENTRAL_PATHLEN_OFFS); + comlen = ZipReadShort(start, end, q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); + extra = ZipReadShort(start, end, q + ZIP_CENTRAL_EXTRALEN_OFFS); Tcl_DStringSetLength(&ds, 0); - Tcl_DStringAppend(&ds, (char *) q + ZIP_CENTRAL_HEADER_LEN, pathlen); - path = Tcl_DStringValue(&ds); + 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(q + ZIP_CENTRAL_LOCALHDR_OFFS); - if ((lq < zf->data) || (lq > zf->data + zf->length)) { + + ZipReadInt(start, end, q + ZIP_CENTRAL_LOCALHDR_OFFS); + if ((lq < start) || (lq + ZIP_LOCAL_HEADER_LEN > end)) { goto nextent; } - nbcompr = ZipReadInt(lq + ZIP_LOCAL_COMPLEN_OFFS); + nbcompr = ZipReadInt(start, end, lq + ZIP_LOCAL_COMPLEN_OFFS); if (!isdir && (nbcompr == 0) - && (ZipReadInt(lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0) - && (ZipReadInt(lq + ZIP_LOCAL_CRC32_OFFS) == 0)) { + && (ZipReadInt(start, end, lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0) + && (ZipReadInt(start, end, lq + ZIP_LOCAL_CRC32_OFFS) == 0)) { gq = q; - nbcompr = ZipReadInt(gq + ZIP_CENTRAL_COMPLEN_OFFS); + nbcompr = ZipReadInt(start, end, gq + ZIP_CENTRAL_COMPLEN_OFFS); } offs = (lq - zf->data) + ZIP_LOCAL_HEADER_LEN - + ZipReadShort(lq + ZIP_LOCAL_PATHLEN_OFFS) - + ZipReadShort(lq + ZIP_LOCAL_EXTRALEN_OFFS); + + ZipReadShort(start, end, lq + ZIP_LOCAL_PATHLEN_OFFS) + + ZipReadShort(start, end, lq + ZIP_LOCAL_EXTRALEN_OFFS); if (offs + nbcompr > zf->length) { goto nextent; } + if (!isdir && (mountPoint[0] == '\0') && !CountSlashes(path)) { #ifdef ANDROID /* * When mounting the ZIP archive on the root directory try to * remap top level regular files of the archive to @@ -1317,12 +1993,11 @@ 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) { + if (ZipFSLookup(Tcl_DStringValue(&ds2))) { /* should not happen but skip it anyway */ Tcl_DStringFree(&ds2); goto nextent; } Tcl_DStringSetLength(&ds, 0); @@ -1335,97 +2010,107 @@ * 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; + 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(lq + ZIP_LOCAL_FLAGS_OFFS) & 1) - && (nbcompr > 12); + z->isEncrypted = + (ZipReadShort(start, end, lq + ZIP_LOCAL_FLAGS_OFFS) & 1) + && (nbcompr > ZIP_CRYPT_HDR_LEN); z->offset = offs; if (gq) { - z->crc32 = ZipReadInt(gq + ZIP_CENTRAL_CRC32_OFFS); - dosDate = ZipReadShort(gq + ZIP_CENTRAL_MDATE_OFFS); - dosTime = ZipReadShort(gq + ZIP_CENTRAL_MTIME_OFFS); - z->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; + 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); - } 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; - } + 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); - Unlock(); return TCL_OK; } /* *------------------------------------------------------------------------- @@ -1451,15 +2136,19 @@ 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; } /* *------------------------------------------------------------------------- @@ -1478,30 +2167,77 @@ * Interpreter result may be updated. * *------------------------------------------------------------------------- */ -static inline int +static int ListMountPoints( Tcl_Interp *interp) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; ZipFile *zf; + Tcl_Obj *resultList; + if (!interp) { + /* + * Are there any entries in the zipHash? Don't need to enumerate them + * all to know. + */ + + return (ZipFS.zipHash.numEntries ? TCL_OK : TCL_BREAK); + } + + TclNewObj(resultList); for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - 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); + 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 -- * @@ -1517,22 +2253,19 @@ * Interpreter result may be updated. * *------------------------------------------------------------------------- */ -static inline int +static 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); + ZipFile *zf = ZipFSLookupZip(mountPoint); + + if (zf) { Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1)); return TCL_OK; } } return (interp ? TCL_OK : TCL_BREAK); @@ -1557,16 +2290,17 @@ */ int TclZipfs_Mount( Tcl_Interp *interp, /* Current interpreter. NULLable. */ + const char *zipname, /* Path to ZIP file to mount */ const char *mountPoint, /* Mount point path. */ - const char *zipname, /* Path to ZIP file to mount. */ const char *passwd) /* Password for opening the ZIP, or NULL if * the ZIP is unprotected. */ { ZipFile *zf; + int ret; ReadLock(); if (!ZipFS.initialized) { ZipfsSetup(); } @@ -1573,70 +2307,91 @@ /* * No mount point, so list all mount points and what is mounted there. */ - if (!mountPoint) { - int ret = ListMountPoints(interp); + if (mountPoint == NULL) { + ret = ListMountPoints(interp); + Unlock(); + return ret; + } + + Tcl_DString ds; + Tcl_DStringInit(&ds); + ret = NormalizeMountPoint(interp, mountPoint, &ds); + if (ret != TCL_OK) { Unlock(); return ret; } - - /* - * Mount point but no file, so describe what is mounted at that mount - * point. - */ + mountPoint = Tcl_DStringValue(&ds); 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; + /* + * 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", (void *)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 with optional ZIP password. + * mountpoint. * * Results: * A standard Tcl result. * * Side effects: @@ -1647,82 +2402,90 @@ */ int TclZipfs_MountBuffer( Tcl_Interp *interp, /* Current interpreter. NULLable. */ - const char *mountPoint, /* Mount point path. */ - unsigned char *data, + const void *data, size_t datalen, + const char *mountPoint, /* Mount point path. */ int copy) { ZipFile *zf; - int result; + int ret; + if (mountPoint == NULL || data == NULL) { + ZIPFS_ERROR(interp, "mount point and/or data are null"); + return TCL_ERROR; + } + + /* TODO - how come a *read* lock suffices for initialzing ? */ ReadLock(); if (!ZipFS.initialized) { ZipfsSetup(); } - /* - * No mount point, so list all mount points and what is mounted there. - */ - - if (!mountPoint) { - int ret = ListMountPoints(interp); + Tcl_DString ds; + Tcl_DStringInit(&ds); + ret = NormalizeMountPoint(interp, mountPoint, &ds); + if (ret != TCL_OK) { Unlock(); return ret; } - - /* - * Mount point but no data, so describe what is mounted at that mount - * point. - */ - - if (!data) { - DescribeMounted(interp, mountPoint); - Unlock(); - return TCL_OK; - } + mountPoint = Tcl_DStringValue(&ds); + Unlock(); /* * Have both a mount point and data to mount there. + * What's the magic about 64 * 1024 * 1024 ? */ - - 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; + 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) { - if (interp) { - Tcl_AppendResult(interp, "out of memory", (char *) NULL); - Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); - } - return TCL_ERROR; + 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 = data; + } + else { + zf->data = (unsigned char *)data; zf->ptrToFree = NULL; } - zf->passBuf[0] = 0; /* stop valgrind cries */ - if (ZipFSFindTOC(interp, 0, zf) != TCL_OK) { - return TCL_ERROR; - } - result = ZipFSCatalogFilesystem(interp, zf, mountPoint, NULL, - "Memory Buffer"); - Tcl_Free(zf); - return result; + 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; } /* *------------------------------------------------------------------------- * @@ -1743,14 +2506,15 @@ TclZipfs_Unmount( Tcl_Interp *interp, /* Current interpreter. NULLable. */ const char *mountPoint) /* Mount point path. */ { ZipFile *zf; - ZipEntry *z, *znext; Tcl_HashEntry *hPtr; Tcl_DString dsm; int ret = TCL_OK, unmounted = 0; + + Tcl_DStringInit(&dsm); WriteLock(); if (!ZipFS.initialized) { goto done; } @@ -1758,43 +2522,44 @@ /* * Mount point sometimes is a relative or otherwise denormalized path. * But an absolute name is needed as mount point here. */ - Tcl_DStringInit(&dsm); - mountPoint = CanonicalPath("", mountPoint, &dsm, 1); + if (NormalizeMountPoint(interp, mountPoint, &dsm) != TCL_OK) { + goto done; + } + mountPoint = Tcl_DStringValue(&dsm); hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint); /* don't report no-such-mount as an error */ if (!hPtr) { goto done; } - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (zf->numOpen > 0) { ZIPFS_ERROR(interp, "filesystem is busy"); + ZIPFS_ERROR_CODE(interp, "BUSY"); ret = TCL_ERROR; goto done; } Tcl_DeleteHashEntry(hPtr); - for (z = zf->entries; z; z = znext) { - znext = z->next; - hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, z->name); - if (hPtr) { - Tcl_DeleteHashEntry(hPtr); - } - if (z->data) { - Tcl_Free(z->data); - } - Tcl_Free(z); - } + + /* + * Now no longer mounted - the rest of the code won't find it - but we're + * still cleaning things up. + */ + + CleanupMount(zf); ZipFSCloseArchive(interp, zf); - Tcl_DeleteExitHandler(ZipfsExitHandler, zf); + Tcl_Free(zf); unmounted = 1; + done: Unlock(); + Tcl_DStringFree(&dsm); if (unmounted) { Tcl_FSMountsChanged(NULL); } return ret; } @@ -1815,25 +2580,42 @@ *------------------------------------------------------------------------- */ static int ZipFSMountObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + const char *mountPoint = NULL, *zipFile = NULL, *password = NULL; + int result; if (objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, - "?mountpoint? ?zipfile? ?password?"); + "?zipfile? ?mountpoint? ?password?"); return TCL_ERROR; } + /* + * 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]); + } + } + } - return TclZipfs_Mount(interp, (objc > 1) ? TclGetString(objv[1]) : NULL, - (objc > 2) ? TclGetString(objv[2]) : NULL, - (objc > 3) ? TclGetString(objv[3]) : NULL); + result = TclZipfs_Mount(interp, zipFile, mountPoint, password); + return result; } /* *------------------------------------------------------------------------- * @@ -1850,45 +2632,29 @@ *------------------------------------------------------------------------- */ static int ZipFSMountBufferObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - const char *mountPoint; /* Mount point path. */ - unsigned char *data; - size_t length = 0; + const char *mountPoint = NULL; /* Mount point path. */ + unsigned char *data = NULL; + Tcl_Size length; - if (objc > 3) { - Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? ?data?"); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "data mountpoint"); return TCL_ERROR; } - if (objc < 2) { - int ret; - - 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); + data = Tcl_GetBytesFromObj(interp, objv[1], &length); + mountPoint = Tcl_GetString(objv[2]); if (data == NULL) { return TCL_ERROR; } - return TclZipfs_MountBuffer(interp, mountPoint, data, length, 1); + return TclZipfs_MountBuffer(interp, data, length, mountPoint, 1); } /* *------------------------------------------------------------------------- * @@ -1905,15 +2671,19 @@ *------------------------------------------------------------------------- */ static int ZipFSRootObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ - TCL_UNUSED(int) /*objc*/, - TCL_UNUSED(Tcl_Obj *const *)) /*objv*/ + int objc, + Tcl_Obj *const *objv) { + if (objc != 1) { + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } Tcl_SetObjResult(interp, Tcl_NewStringObj(ZIPFS_VOLUME, -1)); return TCL_OK; } /* @@ -1932,18 +2702,17 @@ *------------------------------------------------------------------------- */ static int ZipFSUnmountObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - if (objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "zipfile"); + Tcl_WrongNumArgs(interp, 1, objv, "mountpoint"); return TCL_ERROR; } return TclZipfs_Unmount(interp, TclGetString(objv[1])); } @@ -1964,58 +2733,104 @@ *------------------------------------------------------------------------- */ static int ZipFSMkKeyObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int len, i = 0; - char *pw, passBuf[264]; + Tcl_Size len, i = 0; + const char *pw; + Tcl_Obj *passObj; + unsigned char *passBuf; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "password"); return TCL_ERROR; } - pw = TclGetString(objv[1]); - len = strlen(pw); + pw = Tcl_GetStringFromObj(objv[1], &len); if (len == 0) { return TCL_OK; } - if ((len > 255) || strchr(pw, 0xff)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("illegal password", -1)); + if (IsPasswordValid(interp, pw, len) != TCL_OK) { return TCL_ERROR; } + + passObj = Tcl_NewByteArrayObj(NULL, 264); + passBuf = Tcl_GetByteArrayFromObj(passObj, (Tcl_Size *)NULL); while (len > 0) { int ch = pw[len - 1]; - passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; - i++; + passBuf[i++] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; len--; } passBuf[i] = i; - ++i; - passBuf[i++] = (char) ZIP_PASSWORD_END_SIG; - passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 8); - passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 16); - passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 24); - passBuf[i] = '\0'; - Tcl_AppendResult(interp, passBuf, (char *) NULL); + i++; + ZipWriteInt(passBuf, passBuf + 264, passBuf + i, ZIP_PASSWORD_END_SIG); + Tcl_SetByteArrayLength(passObj, i + 4); + Tcl_SetObjResult(interp, passObj); + return TCL_OK; +} + +/* + *------------------------------------------------------------------------- + * + * RandomChar -- + * + * Worker for ZipAddFile(). Picks a random character (range: 0..255) + * using Tcl's standard PRNG. + * + * Returns: + * Tcl result code. Updates chPtr with random character on success. + * + * Side effects: + * Advances the PRNG state. May reenter the Tcl interpreter if the user + * has replaced the PRNG. + * + *------------------------------------------------------------------------- + */ + +static int +RandomChar( + Tcl_Interp *interp, + int step, + int *chPtr) +{ + double r; + Tcl_Obj *ret; + + if (Tcl_EvalEx(interp, "::tcl::mathfunc::rand", TCL_INDEX_NONE, 0) != TCL_OK) { + goto failed; + } + ret = Tcl_GetObjResult(interp); + if (Tcl_GetDoubleFromObj(interp, ret, &r) != TCL_OK) { + goto failed; + } + *chPtr = (int) (r * 256); return TCL_OK; + + failed: + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (evaluating PRNG step %d for password encoding)", + step)); + return TCL_ERROR; } /* *------------------------------------------------------------------------- * * ZipAddFile -- * - * This procedure is used by ZipFSMkZipOrImgCmd() to add a single file to + * This procedure is used by ZipFSMkZipOrImg() to add a single file to * the output ZIP archive file being written. A ZipEntry struct about the * input file is added to the given fileHash table for later creation of * the central ZIP directory. + * + * Tcl *always* encodes filenames in the ZIP as UTF-8. Similarly, it + * would always encode comments as UTF-8, if it supported comments. * * Results: * A standard Tcl result. * * Side effects: @@ -2026,85 +2841,105 @@ */ static int ZipAddFile( Tcl_Interp *interp, /* Current interpreter. */ - const char *path, - const char *name, - Tcl_Channel out, + Tcl_Obj *pathObj, /* Actual name of the file to add. */ + const char *name, /* Name to use in the ZIP archive, in Tcl's + * internal encoding. */ + Tcl_Channel out, /* The open ZIP archive being built. */ const char *passwd, /* Password for encoding the file, or NULL if * the file is to be unprotected. */ - char *buf, - int bufsize, - Tcl_HashTable *fileHash) + char *buf, /* Working buffer. */ + int bufsize, /* Size of buf */ + Tcl_HashTable *fileHash) /* Where to record ZIP entry metdata so we can + * built the central directory. */ { + const unsigned char *start = (unsigned char *) buf; + const unsigned char *end = (unsigned char *) buf + bufsize; Tcl_Channel in; Tcl_HashEntry *hPtr; ZipEntry *z; z_stream stream; - const char *zpath; + 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, len, olen, align = 0; - Tcl_WideInt pos[3]; + size_t nbyte, nbytecompr; + Tcl_Size len, olen, align = 0; + long long headerStartOffset, dataStartOffset, dataEndOffset; int mtime = 0, isNew, compMeth; unsigned long keys[3], keys0[3]; char obuf[4096]; /* * Trim leading '/' characters. If this results in an empty string, we've * nothing to do. */ - zpath = name; - while (zpath && zpath[0] == '/') { - zpath++; + zpathTcl = name; + while (zpathTcl && zpathTcl[0] == '/') { + zpathTcl++; } - if (!zpath || (zpath[0] == '\0')) { + if (!zpathTcl || (zpathTcl[0] == '\0')) { return TCL_OK; } - zpathlen = strlen(zpath); + /* + * 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! + */ + + zpathExt = Tcl_UtfToExternalDString(tclUtf8Encoding, zpathTcl, -1, &zpathDs); + zpathlen = strlen(zpathExt); if (zpathlen + ZIP_CENTRAL_HEADER_LEN > bufsize) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "path too long for \"%s\"", path)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "PATH_LEN", NULL); + "path too long for \"%s\"", TclGetString(pathObj))); + ZIPFS_ERROR_CODE(interp, "PATH_LEN"); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } - in = Tcl_OpenFileChannel(interp, path, "rb", 0); + in = Tcl_FSOpenFileChannel(interp, pathObj, "rb", 0); if (!in) { + Tcl_DStringFree(&zpathDs); #ifdef _WIN32 /* hopefully a directory */ if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) { - Tcl_CloseEx(interp, in, 0); + Tcl_Close(interp, in); return TCL_OK; } #endif /* _WIN32 */ - Tcl_CloseEx(interp, in, 0); + Tcl_Close(interp, in); return TCL_ERROR; } else { - Tcl_Obj *pathObj = Tcl_NewStringObj(path, -1); Tcl_StatBuf statBuf; - Tcl_IncrRefCount(pathObj); if (Tcl_FSStat(pathObj, &statBuf) != -1) { mtime = statBuf.st_mtime; } - Tcl_DecrRefCount(pathObj); } Tcl_ResetResult(interp); + + /* + * Compute the CRC. + */ + crc = 0; nbyte = nbytecompr = 0; while (1) { len = Tcl_Read(in, buf, bufsize); - if (len == TCL_IO_FAILURE) { + if (len < 0) { + Tcl_DStringFree(&zpathDs); if (nbyte == 0 && errno == EISDIR) { - Tcl_CloseEx(interp, in, 0); + Tcl_Close(interp, in); return TCL_OK; } + readErrorWithChannelOpen: Tcl_SetObjResult(interp, Tcl_ObjPrintf("read error on \"%s\": %s", - path, Tcl_PosixError(interp))); - Tcl_CloseEx(interp, in, 0); + TclGetString(pathObj), Tcl_PosixError(interp))); + Tcl_Close(interp, in); return TCL_ERROR; } if (len == 0) { break; } @@ -2111,241 +2946,249 @@ crc = crc32(crc, (unsigned char *) buf, len); nbyte += len; } if (Tcl_Seek(in, 0, SEEK_SET) == -1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("seek error on \"%s\": %s", - path, Tcl_PosixError(interp))); - Tcl_CloseEx(interp, in, 0); + TclGetString(pathObj), Tcl_PosixError(interp))); + Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } - pos[0] = Tcl_Tell(out); + + /* + * 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, zpath, zpathlen); + memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpathExt, zpathlen); len = zpathlen + ZIP_LOCAL_HEADER_LEN; if (Tcl_Write(out, buf, len) != len) { - wrerr: + writeErrorWithChannelOpen: Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "write error on %s: %s", path, Tcl_PosixError(interp))); - Tcl_CloseEx(interp, in, 0); + "write error on \"%s\": %s", + TclGetString(pathObj), Tcl_PosixError(interp))); + Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } - if ((len + pos[0]) & 3) { + + /* + * 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]; - - /* - * 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); + 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 wrerr; + goto writeErrorWithChannelOpen; } } + + /* + * Set up encryption if we were asked to. + */ + 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)); + 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 < 12 - 2; i++) { - kvbuf[i] = UCHAR(zencode(keys, crc32tab, kvbuf[i + 12], tmp)); + for (i = 0; i < ZIP_CRYPT_HDR_LEN - 2; i++) { + kvbuf[i] = UCHAR(zencode(keys, crc32tab, kvbuf[i + ZIP_CRYPT_HDR_LEN], tmp)); } kvbuf[i++] = UCHAR(zencode(keys, crc32tab, crc >> 16, tmp)); kvbuf[i++] = UCHAR(zencode(keys, crc32tab, crc >> 24, tmp)); - len = Tcl_Write(out, (char *) kvbuf, 12); - memset(kvbuf, 0, 24); - if (len != 12) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "write error on %s: %s", path, Tcl_PosixError(interp))); - Tcl_CloseEx(interp, in, 0); - return TCL_ERROR; + 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 += 12; + nbytecompr += ZIP_CRYPT_HDR_LEN; } + + /* + * Save where we've got to in case we need to just store this file. + */ + Tcl_Flush(out); - pos[2] = Tcl_Tell(out); + dataStartOffset = Tcl_Tell(out); + + /* + * Compress the stream. + */ + compMeth = ZIP_COMPMETH_DEFLATED; memset(&stream, 0, sizeof(z_stream)); stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.opaque = Z_NULL; if (deflateInit2(&stream, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "compression init error on \"%s\"", path)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DEFLATE_INIT", NULL); - Tcl_CloseEx(interp, in, 0); + "compression init error on \"%s\"", TclGetString(pathObj))); + ZIPFS_ERROR_CODE(interp, "DEFLATE_INIT"); + Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } + do { len = Tcl_Read(in, buf, bufsize); - if (len == TCL_IO_FAILURE) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "read error on %s: %s", path, Tcl_PosixError(interp))); + if (len < 0) { deflateEnd(&stream); - Tcl_CloseEx(interp, in, 0); - return TCL_ERROR; + 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 == (size_t) Z_STREAM_ERROR) { + if (len == Z_STREAM_ERROR) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "deflate error on %s", path)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DEFLATE", NULL); + "deflate error on \"%s\"", TclGetString(pathObj))); + ZIPFS_ERROR_CODE(interp, "DEFLATE"); deflateEnd(&stream); - Tcl_CloseEx(interp, in, 0); + Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } olen = sizeof(obuf) - stream.avail_out; if (passwd) { - size_t i; + Tcl_Size i; int tmp; for (i = 0; i < olen; i++) { obuf[i] = (char) zencode(keys, crc32tab, obuf[i], tmp); } } if (olen && (Tcl_Write(out, obuf, olen) != olen)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "write error: %s", Tcl_PosixError(interp))); deflateEnd(&stream); - Tcl_CloseEx(interp, in, 0); - return TCL_ERROR; + goto writeErrorWithChannelOpen; } nbytecompr += olen; } while (stream.avail_out == 0); } while (flush != Z_FINISH); deflateEnd(&stream); + + /* + * Work out where we've got to. + */ + Tcl_Flush(out); - pos[1] = Tcl_Tell(out); + dataEndOffset = Tcl_Tell(out); + if (nbyte - nbytecompr <= 0) { /* * Compressed file larger than input, write it again uncompressed. */ + if (Tcl_Seek(in, 0, SEEK_SET) != 0) { goto seekErr; } - if (Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) { + if (Tcl_Seek(out, dataStartOffset, SEEK_SET) != dataStartOffset) { seekErr: - Tcl_CloseEx(interp, in, 0); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "seek error: %s", Tcl_PosixError(interp))); + Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } - nbytecompr = (passwd ? 12 : 0); + nbytecompr = (passwd ? ZIP_CRYPT_HDR_LEN : 0); while (1) { len = Tcl_Read(in, buf, bufsize); - if (len == TCL_IO_FAILURE) { - 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) { + goto readErrorWithChannelOpen; } else if (len == 0) { break; } if (passwd) { - size_t i; + Tcl_Size i; int tmp; for (i = 0; i < len; i++) { buf[i] = (char) zencode(keys0, crc32tab, buf[i], tmp); } } if (Tcl_Write(out, buf, len) != len) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "write error: %s", Tcl_PosixError(interp))); - Tcl_CloseEx(interp, in, 0); - return TCL_ERROR; + 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); - pos[1] = Tcl_Tell(out); - Tcl_TruncateChannel(out, pos[1]); + dataEndOffset = Tcl_Tell(out); + Tcl_TruncateChannel(out, dataEndOffset); } - Tcl_CloseEx(interp, in, 0); + Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); + zpathExt = NULL; - hPtr = Tcl_CreateHashEntry(fileHash, zpath, &isNew); + hPtr = Tcl_CreateHashEntry(fileHash, zpathTcl, &isNew); if (!isNew) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "non-unique path name \"%s\"", path)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DUPLICATE_PATH", NULL); + "non-unique path name \"%s\"", TclGetString(pathObj))); + ZIPFS_ERROR_CODE(interp, "DUPLICATE_PATH"); return TCL_ERROR; } - z = (ZipEntry *)Tcl_Alloc(sizeof(ZipEntry)); + /* + * 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->name = NULL; - z->tnext = NULL; - z->depth = 0; - z->zipFilePtr = NULL; - z->isDirectory = 0; z->isEncrypted = (passwd ? 1 : 0); - z->offset = pos[0]; + z->offset = headerStartOffset; z->crc32 = crc; z->timestamp = mtime; z->numBytes = nbyte; z->numCompressedBytes = nbytecompr; z->compressMethod = compMeth; - z->data = NULL; - z->name = (char *)Tcl_GetHashKey(fileHash, hPtr); - z->next = NULL; + z->name = (char *) Tcl_GetHashKey(fileHash, hPtr); /* * 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]) { + + 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; @@ -2356,11 +3199,11 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write error: %s", Tcl_PosixError(interp))); return TCL_ERROR; } Tcl_Flush(out); - if (Tcl_Seek(out, pos[1], SEEK_SET) != pos[1]) { + if (Tcl_Seek(out, dataEndOffset, SEEK_SET) != dataEndOffset) { Tcl_DeleteHashEntry(hPtr); Tcl_Free(z); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "seek error: %s", Tcl_PosixError(interp))); return TCL_ERROR; @@ -2369,16 +3212,105 @@ } /* *------------------------------------------------------------------------- * - * ZipFSMkZipOrImgObjCmd -- + * 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 = Tcl_GetStringFromObj(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. + * 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: @@ -2386,99 +3318,109 @@ * *------------------------------------------------------------------------- */ static int -ZipFSMkZipOrImgObjCmd( +ZipFSMkZipOrImg( Tcl_Interp *interp, /* Current interpreter. */ - int isImg, - int isList, - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ + int isImg, /* Are we making an image? */ + Tcl_Obj *targetFile, /* What file are we making? */ + Tcl_Obj *dirRoot, /* What directory do we take files from? Do + * not specify at the same time as + * mappingList (one must be NULL). */ + Tcl_Obj *mappingList, /* What files are we putting in, and with what + * names? Do not specify at the same time as + * dirRoot (one must be NULL). */ + Tcl_Obj *originFile, /* If we're making an image, what file does + * the non-ZIP part of the image come from? */ + Tcl_Obj *stripPrefix, /* Are we going to strip a prefix from + * filenames found beneath dirRoot? If NULL, + * do not strip anything (except for dirRoot + * itself). */ + Tcl_Obj *passwordObj) /* The password for encoding things. NULL if + * there's no password protection. */ { Tcl_Channel out; - int pwlen = 0, count, ret = TCL_ERROR, lobjc; - size_t len, slen = 0, i = 0; - Tcl_WideInt pos[3]; - Tcl_Obj **lobjv, *list = NULL; + int count, ret = TCL_ERROR; + Tcl_Size pwlen = 0, slen = 0, len, i = 0; + Tcl_Size lobjc; + long long directoryStartOffset; + /* The overall file offset of the start of the + * central directory. */ + long long suffixStartOffset;/* The overall file offset of the start of the + * suffix of the central directory (i.e., + * where this data will be written). */ + Tcl_Obj **lobjv, *list = mappingList; ZipEntry *z; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_HashTable fileHash; char *strip = NULL, *pw = NULL, passBuf[264], buf[4096]; + unsigned char *start = (unsigned char *) buf; + unsigned char *end = start + sizeof(buf); /* * Caller has verified that the number of arguments is correct. */ passBuf[0] = 0; - if (objc > (isList ? 3 : 4)) { - pw = TclGetString(objv[isList ? 3 : 4]); - 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); + if (passwordObj != NULL) { + pw = Tcl_GetStringFromObj(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 (TclListObjLengthM(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); - Tcl_SetObjResult(interp, Tcl_NewStringObj("empty archive", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "EMPTY", NULL); + ZIPFS_ERROR(interp, "empty archive"); + ZIPFS_ERROR_CODE(interp, "EMPTY"); + return TCL_ERROR; + } + if (TclListObjGetElementsM(interp, list, &lobjc, &lobjv) != TCL_OK) { + Tcl_DecrRefCount(list); return TCL_ERROR; } - out = Tcl_OpenFileChannel(interp, TclGetString(objv[1]), "wb", 0755); + out = Tcl_FSOpenFileChannel(interp, targetFile, "wb", 0755); if (out == NULL) { Tcl_DecrRefCount(list); return TCL_ERROR; } - if (pwlen <= 0) { - pw = NULL; - pwlen = 0; - } + + /* + * Copy the existing contents from the image if it is an executable image. + * Care must be taken because this might include an existing ZIP, which + * needs to be stripped. + */ + if (isImg) { ZipFile *zf, zf0; int isMounted = 0; const char *imgName; - if (isList) { - imgName = (objc > 4) ? TclGetString(objv[4]) : - Tcl_GetNameOfExecutable(); - } else { - imgName = (objc > 5) ? TclGetString(objv[5]) : - Tcl_GetNameOfExecutable(); - } + // 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]; @@ -2499,29 +3441,35 @@ */ WriteLock(); for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (strcmp(zf->name, imgName) == 0) { isMounted = 1; zf->numOpen++; break; } } Unlock(); + if (!isMounted) { zf = &zf0; + memset(&zf0, 0, sizeof(ZipFile)); } if (isMounted || ZipFSOpenArchive(interp, imgName, 0, zf) == TCL_OK) { - if (Tcl_Write(out, (char *) zf->data, + /* + * 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_CloseEx(interp, out, 0); + Tcl_Close(interp, out); if (zf == &zf0) { ZipFSCloseArchive(interp, zf); } else { WriteLock(); zf->numOpen--; @@ -2535,173 +3483,108 @@ 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); - } + 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_CloseEx(interp, out, 0); + 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); - 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 (mappingList == NULL && stripPrefix != NULL) { + strip = Tcl_GetStringFromObj(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, path, name, out, pw, buf, sizeof(buf), + if (ZipAddFile(interp, pathObj, name, out, pw, buf, sizeof(buf), &fileHash) != TCL_OK) { goto done; } } - pos[1] = Tcl_Tell(out); + + /* + * Construct the contents of the ZIP central directory. + */ + + directoryStartOffset = Tcl_Tell(out); count = 0; - for (i = 0; i < (size_t) lobjc; i += (isList ? 2 : 1)) { - const char *path, *name; - - path = TclGetString(lobjv[i]); - 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; - } + 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); - 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)) { + z = (ZipEntry *) Tcl_GetHashValue(hPtr); + + name = Tcl_UtfToExternalDString(tclUtf8Encoding, z->name, TCL_INDEX_NONE, &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); - 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); + 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; } @@ -2708,138 +3591,343 @@ Tcl_Flush(out); ret = TCL_OK; done: if (ret == TCL_OK) { - ret = Tcl_CloseEx(interp, out, 0); + ret = Tcl_Close(interp, out); } else { - Tcl_CloseEx(interp, out, 0); + Tcl_Close(interp, out); } Tcl_DecrRefCount(list); for (hPtr = Tcl_FirstHashEntry(&fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - z = (ZipEntry *)Tcl_GetHashValue(hPtr); + z = (ZipEntry *) Tcl_GetHashValue(hPtr); Tcl_Free(z); Tcl_DeleteHashEntry(hPtr); } Tcl_DeleteHashTable(&fileHash); return ret; } + +/* + * --------------------------------------------------------------------- + * + * CopyImageFile -- + * + * A simple file copy function that is used (by ZipFSMkZipOrImg) for + * anything that is not an image with a ZIP appended. + * + * Returns: + * A Tcl result code. + * + * Side effects: + * Writes to an output channel. + * + * --------------------------------------------------------------------- + */ + +static int +CopyImageFile( + Tcl_Interp *interp, /* For error reporting. */ + const char *imgName, /* Where to copy from. */ + Tcl_Channel out) /* Where to copy to; already open for writing + * binary data. */ +{ + Tcl_WideInt i, k; + Tcl_Size m, n; + Tcl_Channel in; + char buf[4096]; + const char *errMsg; + + Tcl_ResetResult(interp); + in = Tcl_OpenFileChannel(interp, imgName, "rb", 0644); + if (!in) { + return TCL_ERROR; + } + + /* + * Get the length of the file (and exclude non-files). + */ + + i = Tcl_Seek(in, 0, SEEK_END); + if (i == -1) { + errMsg = "seek error"; + goto copyError; + } + Tcl_Seek(in, 0, SEEK_SET); + + /* + * Copy the whole file, 8 blocks at a time (reasonably efficient). Note + * that this totally ignores things like Windows's Alternate File Streams. + */ + + for (k = 0; k < i; k += m) { + m = i - k; + if (m > (Tcl_Size) sizeof(buf)) { + m = sizeof(buf); + } + n = Tcl_Read(in, buf, m); + if (n == -1) { + errMsg = "read error"; + goto copyError; + } else if (n == 0) { + break; + } + m = Tcl_Write(out, buf, n); + if (m != n) { + errMsg = "write error"; + goto copyError; + } + } + Tcl_Close(interp, in); + return TCL_OK; + + copyError: + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "%s: %s", errMsg, Tcl_PosixError(interp))); + Tcl_Close(interp, in); + return TCL_ERROR; +} + +/* + * --------------------------------------------------------------------- + * + * SerializeLocalEntryHeader, SerializeCentralDirectoryEntry, + * SerializeCentralDirectorySuffix -- + * + * Create serialized forms of the structures that make up the ZIP + * metadata. Note that the both the local entry and the central directory + * entry need to have the name of the entry written directly afterwards. + * + * We could write these as structs except we need to guarantee that we + * are writing these out as little-endian values. + * + * Side effects: + * Both update their buffer arguments, but otherwise change nothing. + * + * --------------------------------------------------------------------- + */ + +static void +SerializeLocalEntryHeader( + const unsigned char *start, /* The start of writable memory. */ + const unsigned char *end, /* The end of writable memory. */ + unsigned char *buf, /* Where to serialize to */ + ZipEntry *z, /* The description of what to serialize. */ + int nameLength, /* The length of the name. */ + int align) /* The number of alignment bytes. */ +{ + ZipWriteInt(start, end, buf + ZIP_LOCAL_SIG_OFFS, ZIP_LOCAL_HEADER_SIG); + ZipWriteShort(start, end, buf + ZIP_LOCAL_VERSION_OFFS, ZIP_MIN_VERSION); + ZipWriteShort(start, end, buf + ZIP_LOCAL_FLAGS_OFFS, z->isEncrypted); + 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 ZipFSMkZipOrImgCmd(). + * lmkzip] commands. See description of ZipFSMkZipOrImg(). * * Results: * A standard Tcl result. * * Side effects: - * See description of ZipFSMkZipOrImgCmd(). + * See description of ZipFSMkZipOrImg(). * *------------------------------------------------------------------------- */ static int ZipFSMkZipObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + Tcl_Obj *stripPrefix, *password; + if (objc < 3 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "outfile indir ?strip? ?password?"); return TCL_ERROR; } if (Tcl_IsSafe(interp)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "operation not permitted in a safe interpreter", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL); + ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter"); + ZIPFS_ERROR_CODE(interp, "SAFE_INTERP"); return TCL_ERROR; } - return ZipFSMkZipOrImgObjCmd(interp, 0, 0, objc, objv); + + 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(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + Tcl_Obj *password; + if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password?"); return TCL_ERROR; } if (Tcl_IsSafe(interp)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "operation not permitted in a safe interpreter", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL); + ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter"); + ZIPFS_ERROR_CODE(interp, "SAFE_INTERP"); return TCL_ERROR; } - return ZipFSMkZipOrImgObjCmd(interp, 0, 1, objc, objv); + + 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 ZipFSMkZipOrImgCmd(). + * lmkimg] commands. See description of ZipFSMkZipOrImg(). * * Results: * A standard Tcl result. * * Side effects: - * See description of ZipFSMkZipOrImgCmd(). + * See description of ZipFSMkZipOrImg(). * *------------------------------------------------------------------------- */ static int ZipFSMkImgObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + Tcl_Obj *originFile, *stripPrefix, *password; + if (objc < 3 || objc > 6) { Tcl_WrongNumArgs(interp, 1, objv, "outfile indir ?strip? ?password? ?infile?"); return TCL_ERROR; } if (Tcl_IsSafe(interp)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "operation not permitted in a safe interpreter", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL); + ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter"); + ZIPFS_ERROR_CODE(interp, "SAFE_INTERP"); return TCL_ERROR; } - return ZipFSMkZipOrImgObjCmd(interp, 1, 0, objc, objv); + + 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(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + Tcl_Obj *originFile, *password; + if (objc < 3 || objc > 5) { - Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password infile?"); + Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password? ?infile?"); return TCL_ERROR; } if (Tcl_IsSafe(interp)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "operation not permitted in a safe interpreter", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL); + ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter"); + ZIPFS_ERROR_CODE(interp, "SAFE_INTERP"); return TCL_ERROR; } - return ZipFSMkZipOrImgObjCmd(interp, 1, 1, objc, objv); + + originFile = (objc > 4 ? objv[4] : NULL); + password = (objc > 3 ? objv[3] : NULL); + return ZipFSMkZipOrImg(interp, 1, objv[1], NULL, objv[2], + originFile, NULL, password); } /* *------------------------------------------------------------------------- * @@ -2857,43 +3945,39 @@ *------------------------------------------------------------------------- */ static int ZipFSCanonicalObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - char *mntpoint = NULL; - 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)); + 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; } /* *------------------------------------------------------------------------- @@ -2913,36 +3997,32 @@ *------------------------------------------------------------------------- */ static int ZipFSExistsObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { char *filename; int exists; - Tcl_DString ds; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "filename"); return TCL_ERROR; } - /* - * Prepend ZIPFS_VOLUME to filename, eliding the final / - */ - filename = TclGetString(objv[1]); - Tcl_DStringInit(&ds); - Tcl_DStringAppend(&ds, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN - 1); - Tcl_DStringAppend(&ds, filename, -1); - filename = Tcl_DStringValue(&ds); ReadLock(); exists = ZipFSLookup(filename) != NULL; + if (!exists) { + /* An ancestor directory of a file ? */ + exists = ContainsMountPoint(filename, -1); + } + Unlock(); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(exists)); return TCL_OK; } @@ -2950,11 +4030,11 @@ /* *------------------------------------------------------------------------- * * ZipFSInfoObjCmd -- * - * This procedure is invoked to process the [zipfs info] command. On + * This procedure is invoked to process the [zipfs info] command. On * success, it returns a Tcl list made up of name of ZIP archive file, * size uncompressed, size compressed, and archive offset of a file in * the ZIP filesystem. * * Results: @@ -2966,17 +4046,18 @@ *------------------------------------------------------------------------- */ static int ZipFSInfoObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { char *filename; ZipEntry *z; + int ret; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "filename"); return TCL_ERROR; } @@ -2991,15 +4072,25 @@ Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->numBytes)); Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->numCompressedBytes)); Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(z->offset)); + ret = TCL_OK; + } else { + Tcl_SetErrno(ENOENT); + if (interp) { + Tcl_SetObjResult( + interp, + Tcl_ObjPrintf("path \"%s\" not found in any zipfs volume", + filename)); + } + ret = TCL_ERROR; } Unlock(); - return TCL_OK; + return ret; } - + /* *------------------------------------------------------------------------- * * ZipFSListObjCmd -- * @@ -3016,70 +4107,82 @@ *------------------------------------------------------------------------- */ static int ZipFSListObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { char *pattern = NULL; Tcl_RegExp regexp = NULL; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_Obj *result = Tcl_GetObjResult(interp); + const char *options[] = {"-glob", "-regexp", NULL}; + enum list_options { OPT_GLOB, OPT_REGEXP }; + + /* + * Parse arguments. + */ if (objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?(-glob|-regexp)? ?pattern?"); return TCL_ERROR; } if (objc == 3) { - size_t n; - char *what = TclGetStringFromObj(objv[1], &n); + int idx; - if ((n >= 2) && (strncmp(what, "-glob", n) == 0)) { + if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", + 0, &idx) != TCL_OK) { + return TCL_ERROR; + } + switch (idx) { + case OPT_GLOB: pattern = TclGetString(objv[2]); - } else if ((n >= 2) && (strncmp(what, "-regexp", n) == 0)) { + break; + case OPT_REGEXP: regexp = Tcl_RegExpCompile(interp, TclGetString(objv[2])); if (!regexp) { return TCL_ERROR; } - } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "unknown option \"%s\"", what)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_OPT", NULL); - return TCL_ERROR; + break; } } else if (objc == 2) { pattern = TclGetString(objv[1]); } + + /* + * Scan for matching entries. + */ + ReadLock(); if (pattern) { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); if (Tcl_StringMatch(z->name, pattern)) { Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(z->name, -1)); } } } else if (regexp) { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); if (Tcl_RegExpExec(interp, regexp, z->name, z->name)) { Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(z->name, -1)); } } } else { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(z->name, -1)); } } @@ -3104,20 +4207,37 @@ * This cache is never cleared. * *------------------------------------------------------------------------- */ -#ifdef _WIN32 -#define LIBRARY_SIZE 64 -#endif /* _WIN32 */ +/* Utility routine to centralize housekeeping */ +static Tcl_Obj * +ScriptLibrarySetup( + const char *dirName) +{ + Tcl_Obj *libDirObj = Tcl_NewStringObj(dirName, -1); + Tcl_Obj *subDirObj, *searchPathObj; + + TclNewLiteralStringObj(subDirObj, "encoding"); + Tcl_IncrRefCount(subDirObj); + TclNewObj(searchPathObj); + Tcl_ListObjAppendElement(NULL, searchPathObj, + Tcl_FSJoinToPath(libDirObj, 1, &subDirObj)); + Tcl_DecrRefCount(subDirObj); + Tcl_IncrRefCount(searchPathObj); + Tcl_SetEncodingSearchPath(searchPathObj); + Tcl_DecrRefCount(searchPathObj); + return libDirObj; +} Tcl_Obj * TclZipfs_TclLibrary(void) { Tcl_Obj *vfsInitScript; int found; -#ifdef _WIN32 +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(STATIC_BUILD) +# define LIBRARY_SIZE 64 HMODULE hModule; WCHAR wName[MAX_PATH + LIBRARY_SIZE]; char dllName[(MAX_PATH + LIBRARY_SIZE) * 3]; #endif /* _WIN32 */ @@ -3125,11 +4245,11 @@ * Use the cached value if that has been set; we don't want to repeat the * searching and mounting. */ if (zipfs_literal_tcl_library) { - return Tcl_NewStringObj(zipfs_literal_tcl_library, -1); + return ScriptLibrarySetup(zipfs_literal_tcl_library); } /* * Look for the library file system within the executable. */ @@ -3139,58 +4259,51 @@ Tcl_IncrRefCount(vfsInitScript); found = Tcl_FSAccess(vfsInitScript, F_OK); Tcl_DecrRefCount(vfsInitScript); if (found == TCL_OK) { zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library"; - return Tcl_NewStringObj(zipfs_literal_tcl_library, -1); + return ScriptLibrarySetup(zipfs_literal_tcl_library); } /* * Look for the library file system within the DLL/shared library. Note * that we must mount the zip file and dll before releasing to search. */ -#if defined(_WIN32) +#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 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 */ + 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 Tcl_NewStringObj(zipfs_literal_tcl_library, -1); + return ScriptLibrarySetup(zipfs_literal_tcl_library); } return NULL; } /* @@ -3213,11 +4326,11 @@ *------------------------------------------------------------------------- */ static int ZipFSTclLibraryObjCmd( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ TCL_UNUSED(int) /*objc*/, TCL_UNUSED(Tcl_Obj *const *)) /*objv*/ { if (!Tcl_IsSafe(interp)) { @@ -3251,47 +4364,62 @@ ZipChannelClose( void *instanceData, TCL_UNUSED(Tcl_Interp *), int flags) { - ZipChannel *info = (ZipChannel *)instanceData; + ZipChannel *info = (ZipChannel *) instanceData; if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { return EINVAL; } - if (info->iscompr && info->ubuf) { - Tcl_Free(info->ubuf); - info->ubuf = NULL; - } if (info->isEncrypted) { info->isEncrypted = 0; memset(info->keys, 0, sizeof(info->keys)); } - if (info->isWriting) { + WriteLock(); + if (ZipChannelWritable(info)) { + /* + * Copy channel data back into original file in archive. + */ ZipEntry *z = info->zipEntryPtr; - 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(); + 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; } /* @@ -3316,55 +4444,59 @@ char *buf, int toRead, int *errloc) { ZipChannel *info = (ZipChannel *) instanceData; - unsigned long nextpos; + Tcl_Size nextpos; if (info->isDirectory < 0) { /* * Special case: when executable combined with ZIP archive file read * data in front of ZIP, i.e. the executable itself. */ - nextpos = info->numRead + toRead; - if (nextpos > info->zipFilePtr->baseOffset) { - toRead = info->zipFilePtr->baseOffset - info->numRead; + nextpos = info->cursor + toRead; + if ((size_t)nextpos > info->zipFilePtr->baseOffset) { + toRead = info->zipFilePtr->baseOffset - info->cursor; nextpos = info->zipFilePtr->baseOffset; } if (toRead == 0) { return 0; } memcpy(buf, info->zipFilePtr->data, toRead); - info->numRead = nextpos; + info->cursor = nextpos; *errloc = 0; return toRead; } if (info->isDirectory) { *errloc = EISDIR; return -1; } - nextpos = info->numRead + toRead; + nextpos = info->cursor + toRead; if (nextpos > info->numBytes) { - toRead = info->numBytes - info->numRead; + toRead = info->numBytes - info->cursor; nextpos = info->numBytes; } if (toRead == 0) { return 0; } if (info->isEncrypted) { int i; - + /* + * TODO - when is this code ever exercised? Cannot reach it from + * tests. In particular, decryption is always done at channel open + * to allow for seeks and random reads. + */ for (i = 0; i < toRead; i++) { - int ch = info->ubuf[i + info->numRead]; + int ch = info->ubuf[i + info->cursor]; buf[i] = zdecode(info->keys, crc32tab, ch); } } else { - memcpy(buf, info->ubuf + info->numRead, toRead); + memcpy(buf, info->ubuf + info->cursor, toRead); } - info->numRead = nextpos; + info->cursor = nextpos; *errloc = 0; return toRead; } /* @@ -3391,26 +4523,61 @@ int *errloc) { ZipChannel *info = (ZipChannel *) instanceData; unsigned long nextpos; - if (!info->isWriting) { + if (!ZipChannelWritable(info)) { *errloc = EINVAL; return -1; } - nextpos = info->numRead + toWrite; - if (nextpos > info->maxWrite) { - toWrite = info->maxWrite - info->numRead; - nextpos = info->maxWrite; - } + + assert(info->ubuf == info->ubufToFree); + assert(info->ubufToFree && info->ubufSize > 0); + assert(info->ubufSize <= info->maxWrite); + assert(info->numBytes <= info->ubufSize); + assert(info->cursor <= info->numBytes); + if (toWrite == 0) { + *errloc = 0; return 0; } - memcpy(info->ubuf + info->numRead, buf, toWrite); - info->numRead = nextpos; - if (info->numRead > info->numBytes) { - info->numBytes = info->numRead; + + 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; } @@ -3428,21 +4595,21 @@ * File pointer is repositioned according to offset and mode. * *------------------------------------------------------------------------- */ -static Tcl_WideInt +static long long ZipChannelWideSeek( void *instanceData, - Tcl_WideInt offset, + long long offset, int mode, int *errloc) { ZipChannel *info = (ZipChannel *) instanceData; - size_t end; + Tcl_Size end; - if (!info->isWriting && (info->isDirectory < 0)) { + if (!ZipChannelWritable(info) && (info->isDirectory < 0)) { /* * Special case: when executable combined with ZIP archive file, seek * within front of ZIP, i.e. the executable itself. */ end = info->zipFilePtr->baseOffset; @@ -3452,11 +4619,11 @@ } else { end = info->numBytes; } switch (mode) { case SEEK_CUR: - offset += info->numRead; + offset += info->cursor; break; case SEEK_END: offset += end; break; case SEEK_SET: @@ -3463,28 +4630,28 @@ break; default: *errloc = EINVAL; return -1; } - if (offset < 0) { + if (offset < 0 || offset > TCL_SIZE_MAX) { *errloc = EINVAL; return -1; } - if (info->isWriting) { - if ((size_t) offset > info->maxWrite) { + if (ZipChannelWritable(info)) { + if (offset > info->maxWrite) { *errloc = EINVAL; return -1; } - if ((size_t) offset > info->numBytes) { + if (offset > info->numBytes) { info->numBytes = offset; } - } else if ((size_t) offset > end) { + } else if (offset > end) { *errloc = EINVAL; return -1; } - info->numRead = (size_t) offset; - return info->numRead; + info->cursor = (Tcl_Size) offset; + return info->cursor; } /* *------------------------------------------------------------------------- * @@ -3502,11 +4669,11 @@ *------------------------------------------------------------------------- */ static void ZipChannelWatchChannel( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), TCL_UNUSED(int) /*mask*/) { return; } @@ -3527,13 +4694,13 @@ *------------------------------------------------------------------------- */ static int ZipChannelGetFile( - TCL_UNUSED(ClientData), + TCL_UNUSED(void *), TCL_UNUSED(int) /*direction*/, - TCL_UNUSED(ClientData *) /*handlePtr*/) + TCL_UNUSED(void **) /*handlePtr*/) { return TCL_ERROR; } /* @@ -3540,11 +4707,11 @@ *------------------------------------------------------------------------- * * ZipChannelOpen -- * * This function opens a Tcl_Channel on a file from a mounted ZIP archive - * according to given open mode. + * according to given open mode (already parsed by caller). * * Results: * Tcl_Channel on success, or NULL on error. * * Side effects: @@ -3554,348 +4721,523 @@ */ static Tcl_Channel ZipChannelOpen( Tcl_Interp *interp, /* Current interpreter. */ - char *filename, - int mode, - TCL_UNUSED(int) /*permissions*/) + char *filename, /* What are we opening. */ + int mode) /* O_WRONLY O_RDWR O_TRUNC flags */ { ZipEntry *z; ZipChannel *info; - int i, ch, trunc, wr, flags = 0; + int flags = 0; char cname[128]; - if ((mode & O_APPEND) - || ((ZipFS.wrmax <= 0) && (mode & (O_WRONLY | O_RDWR)))) { + 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_NewStringObj("unsupported open mode", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_MODE", NULL); + 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(ENOENT); + 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( - "file not found \"%s\": %s", filename, + "unsupported file type: %s", Tcl_PosixError(interp))); } goto error; } - trunc = (mode & O_TRUNC) != 0; - wr = (mode & (O_WRONLY | O_RDWR)) != 0; if ((z->compressMethod != ZIP_COMPMETH_STORED) && (z->compressMethod != ZIP_COMPMETH_DEFLATED)) { ZIPFS_ERROR(interp, "unsupported compression method"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "COMP_METHOD", NULL); - } - 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); - } + 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; - 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, + 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 -- @@ -3916,11 +5258,11 @@ ZipEntryStat( char *path, Tcl_StatBuf *buf) { ZipEntry *z; - int ret = -1; + int ret; ReadLock(); z = ZipFSLookup(path); if (z) { memset(buf, 0, sizeof(Tcl_StatBuf)); @@ -3932,10 +5274,21 @@ 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; } @@ -3959,48 +5312,67 @@ static int ZipEntryAccess( char *path, int mode) { - ZipEntry *z; - - if (mode & 3) { + if (mode & X_OK) { return -1; } + ReadLock(); - z = ZipFSLookup(path); + 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 (z ? 0 : -1); + return access; } - + /* *------------------------------------------------------------------------- * * ZipFSOpenFileChannelProc -- * + * Open a channel to a file in a mounted ZIP archive. Delegates to + * ZipChannelOpen(). + * * Results: + * Tcl_Channel on success, or NULL on error. * * Side effects: + * Allocates memory. * *------------------------------------------------------------------------- */ static Tcl_Channel ZipFSOpenFileChannelProc( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *pathPtr, int mode, - int permissions) + TCL_UNUSED(int) /* permissions */) { pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (!pathPtr) { return NULL; } - return ZipChannelOpen(interp, TclGetString(pathPtr), mode, - permissions); + + return ZipChannelOpen(interp, Tcl_GetString(pathPtr), mode); } - + /* *------------------------------------------------------------------------- * * ZipFSStatProc -- * @@ -4019,11 +5391,10 @@ static int ZipFSStatProc( Tcl_Obj *pathPtr, Tcl_StatBuf *buf) { - pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (!pathPtr) { return -1; } return ZipEntryStat(TclGetString(pathPtr), buf); @@ -4085,10 +5456,42 @@ } /* *------------------------------------------------------------------------- * + * 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. * @@ -4104,140 +5507,107 @@ */ static int ZipFSMatchInDirectoryProc( TCL_UNUSED(Tcl_Interp *), - Tcl_Obj *result, - Tcl_Obj *pathPtr, - const char *pattern, - Tcl_GlobTypeData *types) + Tcl_Obj *result, /* Where to append matched items to. */ + Tcl_Obj *pathPtr, /* Where we are looking. */ + const char *pattern, /* What names we are looking for. */ + Tcl_GlobTypeData *types) /* What types we are looking for. */ { - Tcl_HashEntry *hPtr; - Tcl_HashSearch search; Tcl_Obj *normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); - int scnt, l, dirOnly = -1, strip = 0; - size_t len, prefixLen; + int scnt, l, dirOnly = -1, mounts = 0; + Tcl_Size prefixLen, len, strip = 0; char *pat, *prefix, *path; - Tcl_DString dsPref; + Tcl_DString dsPref, *prefixBuf = NULL; + int foundInHash, notDuplicate; + ZipEntry *z; if (!normPathPtr) { return -1; } if (types) { dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR; + mounts = (types->type == TCL_GLOB_TYPE_MOUNT); } /* * The prefix that gets prepended to results. */ - prefix = TclGetStringFromObj(pathPtr, &prefixLen); + prefix = Tcl_GetStringFromObj(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); + path = Tcl_GetStringFromObj(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 (mounts) { + ZipFSMatchMountPoints(result, normPathPtr, pattern, prefixBuf); + goto end; + } + + /* 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 ((dirOnly < 0) || (!dirOnly && !z->isDirectory) || + (dirOnly && 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 (dirOnly && 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] != '/')) { @@ -4244,38 +5614,165 @@ 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_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 ((dirOnly >= 0) && ((dirOnly && !z->isDirectory) || + (!dirOnly && z->isDirectory))) { + continue; + } + if ((z->depth == scnt) && + ((z->flags & ZE_F_VOLUME) == 0) /* Bug 14db54d81e */ + && Tcl_StringCaseMatch(z->name, pat, 0)) { + Tcl_CreateHashEntry(&duplicates, z->name + strip, ¬Duplicate); + assert(notDuplicate); + AppendWithPrefix(result, prefixBuf, z->name + strip, -1); + } + } + } + if (dirOnly) { + /* + * 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, ¬Duplicate); + 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 = Tcl_GetStringFromObj(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 -- @@ -4293,60 +5790,27 @@ */ static int ZipFSPathInFilesystemProc( Tcl_Obj *pathPtr, - TCL_UNUSED(ClientData *)) + TCL_UNUSED(void **)) { - Tcl_HashEntry *hPtr; - Tcl_HashSearch search; - int ret = -1; - size_t len; + Tcl_Size 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; + path = Tcl_GetStringFromObj(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; } /* *------------------------------------------------------------------------- * @@ -4384,23 +5848,38 @@ * 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; } @@ -4430,49 +5909,59 @@ Tcl_Interp *interp, /* Current interpreter. */ int index, Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef) { + Tcl_Size len; int ret = TCL_OK; char *path; ZipEntry *z; pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (!pathPtr) { return -1; } - path = TclGetString(pathPtr); + path = Tcl_GetStringFromObj(pathPtr, &len); ReadLock(); z = ZipFSLookup(path); - if (!z) { + if (!z && !ContainsMountPoint(path, -1)) { Tcl_SetErrno(ENOENT); ZIPFS_POSIX_ERROR(interp, "file not found"); ret = TCL_ERROR; goto done; } + /* z == NULL for intermediate directories that are ancestors of mounts */ switch (index) { - case 0: - TclNewIntObj(*objPtrRef, z->numBytes); - 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: + 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(); @@ -4501,14 +5990,12 @@ Tcl_Interp *interp, /* Current interpreter. */ TCL_UNUSED(int) /*index*/, TCL_UNUSED(Tcl_Obj *) /*pathPtr*/, TCL_UNUSED(Tcl_Obj *) /*objPtr*/) { - if (interp) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("unsupported operation", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "UNSUPPORTED_OP", NULL); - } + ZIPFS_ERROR(interp, "unsupported operation"); + ZIPFS_ERROR_CODE(interp, "UNSUPPORTED_OP"); return TCL_ERROR; } /* *------------------------------------------------------------------------- @@ -4606,11 +6093,11 @@ */ if (execName) { const char *p = strrchr(execName, '/'); - if (p > execName + 1) { + if (p && p > execName + 1) { --p; objs[0] = Tcl_NewStringObj(execName, p - execName); } } if (!objs[0]) { @@ -4632,11 +6119,12 @@ } if (objs[1]) { Tcl_DecrRefCount(objs[1]); } - loadFileProc = (Tcl_FSLoadFileProc2 *)(void *)tclNativeFilesystem.loadFileProc; + loadFileProc = (Tcl_FSLoadFileProc2 *) (void *) + tclNativeFilesystem.loadFileProc; if (loadFileProc) { ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); } else { Tcl_SetErrno(ENOENT); ZIPFS_ERROR(interp, Tcl_PosixError(interp)); @@ -4720,13 +6208,17 @@ if (interp) { Tcl_Command ensemble; Tcl_Obj *mapObj; - Tcl_EvalEx(interp, findproc, -1, TCL_EVAL_GLOBAL); - Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax, - TCL_LINK_INT); + Tcl_EvalEx(interp, findproc, TCL_INDEX_NONE, TCL_EVAL_GLOBAL); + if (!Tcl_IsSafe(interp)) { + Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax, + TCL_LINK_INT); + Tcl_LinkVar(interp, "::tcl::zipfs::fallbackEntryEncoding", + (char *) &ZipFS.fallbackEntryEncoding, TCL_LINK_STRING); + } ensemble = TclMakeEnsemble(interp, "zipfs", Tcl_IsSafe(interp) ? (initMap + 4) : initMap); /* * Add the [zipfs find] subcommand. @@ -4735,20 +6227,23 @@ 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); + Tcl_PkgProvide(interp, "tcl::zipfs", "2.0"); } return TCL_OK; #else /* !HAVE_ZLIB */ ZIPFS_ERROR(interp, "no zlib available"); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL); + 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; @@ -4755,11 +6250,11 @@ int found; if (zipfs_literal_tcl_library) { return TCL_ERROR; } - if (TclZipfs_Mount(NULL, ZIPFS_ZIP_MOUNT, archive, NULL)) { + if (TclZipfs_Mount(NULL, archive, ZIPFS_ZIP_MOUNT, NULL)) { /* Either the file doesn't exist or it is not a zip archive */ return TCL_ERROR; } TclNewLiteralStringObj(vfsInitScript, ZIPFS_ZIP_MOUNT "/init.tcl"); @@ -4781,20 +6276,58 @@ 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"); - } +#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(); } /* *------------------------------------------------------------------------- * @@ -4803,11 +6336,11 @@ * Performs the argument munging for the shell * *------------------------------------------------------------------------- */ -int +const char * TclZipfs_AppHook( #ifdef SUPPORT_BUILTIN_ZIP_INSTALL int *argcPtr, /* Pointer to argc */ #else TCL_UNUSED(int *), /*argcPtr*/ @@ -4816,26 +6349,27 @@ TCL_UNUSED(WCHAR ***)) /* argvPtr */ #else /* !_WIN32 */ char ***argvPtr) /* Pointer to argv */ #endif /* _WIN32 */ { - char *archive; + const char *archive; + const char *result; #ifdef _WIN32 - Tcl_FindExecutable(NULL); + result = Tcl_FindExecutable(NULL); #else - Tcl_FindExecutable((*argvPtr)[0]); + result = Tcl_FindExecutable((*argvPtr)[0]); #endif - archive = (char *) Tcl_GetNameOfExecutable(); + archive = Tcl_GetNameOfExecutable(); TclZipfs_Init(NULL); /* * Look for init.tcl in one of the locations mounted later in this * function. */ - if (!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) { + if (!TclZipfs_Mount(NULL, archive, ZIPFS_APP_MOUNT, NULL)) { int found; Tcl_Obj *vfsInitScript; TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl"); Tcl_IncrRefCount(vfsInitScript); @@ -4859,11 +6393,11 @@ Tcl_IncrRefCount(vfsInitScript); found = Tcl_FSAccess(vfsInitScript, F_OK); Tcl_DecrRefCount(vfsInitScript); if (found == TCL_OK) { zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library"; - return TCL_OK; + return result; } } #ifdef SUPPORT_BUILTIN_ZIP_INSTALL } else if (*argcPtr > 1) { /* @@ -4873,11 +6407,11 @@ #ifdef _WIN32 Tcl_DString ds; Tcl_DStringInit(&ds); - archive = Tcl_WCharToUtfDString((*argvPtr)[1], -1, &ds); + archive = Tcl_WCharToUtfDString((*argvPtr)[1], TCL_INDEX_NONE, &ds); #else /* !_WIN32 */ archive = (*argvPtr)[1]; #endif /* _WIN32 */ if (strcmp(archive, "install") == 0) { Tcl_Obj *vfsInitScript; @@ -4892,12 +6426,12 @@ ZIPFS_ZIP_MOUNT "/tcl_library/install.tcl"); Tcl_IncrRefCount(vfsInitScript); if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) { Tcl_SetStartupScript(vfsInitScript, NULL); } - return TCL_OK; - } else if (!TclZipfs_Mount(NULL, ZIPFS_APP_MOUNT, archive, NULL)) { + return result; + } else if (!TclZipfs_Mount(NULL, archive, ZIPFS_APP_MOUNT, NULL)) { int found; Tcl_Obj *vfsInitScript; TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl"); Tcl_IncrRefCount(vfsInitScript); @@ -4916,22 +6450,22 @@ Tcl_IncrRefCount(vfsInitScript); found = Tcl_FSAccess(vfsInitScript, F_OK); Tcl_DecrRefCount(vfsInitScript); if (found == TCL_OK) { zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library"; - return TCL_OK; + return result; } } #ifdef _WIN32 Tcl_DStringFree(&ds); #endif /* _WIN32 */ #endif /* SUPPORT_BUILTIN_ZIP_INSTALL */ } - return TCL_OK; + return result; } -#ifndef HAVE_ZLIB +#else /* !HAVE_ZLIB */ /* *------------------------------------------------------------------------- * * TclZipfs_Mount, TclZipfs_MountBuffer, TclZipfs_Unmount -- @@ -4942,52 +6476,70 @@ */ 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 + 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"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL); - } + ZIPFS_ERROR_CODE(interp, "NO_ZLIB"); 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) + TCL_UNUSED(const void *), + TCL_UNUSED(size_t), + TCL_UNUSED(const char *), /* Mount point path. */ + TCL_UNUSED(int)) { ZIPFS_ERROR(interp, "no zlib available"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL); - } + ZIPFS_ERROR_CODE(interp, "NO_ZLIB"); return TCL_ERROR; } int TclZipfs_Unmount( Tcl_Interp *interp, /* Current interpreter. */ - const char *mountPoint) /* Mount point path. */ + TCL_UNUSED(const char *)) /* Mount point path. */ { ZIPFS_ERROR(interp, "no zlib available"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL); - } + 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 (const char *path) +{ + return 0; +} + #endif /* !HAVE_ZLIB */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tclZlib.c ================================================================== --- generic/tclZlib.c +++ generic/tclZlib.c @@ -1,13 +1,13 @@ /* * tclZlib.c -- * * This file provides the interface to the Zlib library. * - * Copyright (C) 2004-2005 Pascal Scheffers - * Copyright (C) 2005 Unitas Software B.V. - * Copyright (c) 2008-2012 Donal K. Fellows + * Copyright © 2004-2005 Pascal Scheffers + * 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 @@ -62,11 +62,11 @@ z_stream stream; /* The interface to the zlib library. */ int streamEnd; /* If we've got to end-of-stream. */ Tcl_Obj *inData, *outData; /* Input / output buffers (lists) */ Tcl_Obj *currentInput; /* Pointer to what is currently being * inflated. */ - size_t outPos; + Tcl_Size outPos; 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 @@ -287,11 +287,11 @@ codeStr = "VERSION"; break; case Z_NEED_DICT: codeStr = "NEED_DICT"; codeStr2 = codeStrBuf; - sprintf(codeStrBuf, "%lu", adler); + snprintf(codeStrBuf, sizeof(codeStrBuf), "%lu", adler); break; /* * These should _not_ happen! This function is for dealing with error * cases, not non-errors! @@ -308,21 +308,21 @@ */ default: codeStr = "UNKNOWN"; codeStr2 = codeStrBuf; - sprintf(codeStrBuf, "%d", code); + 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, NULL); + Tcl_SetErrorCode(interp, "TCL", "ZLIB", codeStr, codeStr2, (void *)NULL); } static Tcl_Obj * ConvertErrorToList( int code, /* The zlib error code. */ @@ -421,11 +421,11 @@ int *extraSizePtr) /* Variable to add the length of header * strings (filename, comment) to. */ { Tcl_Obj *value; int len, result = TCL_ERROR; - size_t length; + Tcl_Size length; Tcl_WideInt wideValue = 0; const char *valueStr; Tcl_Encoding latin1enc; static const char *const types[] = { "binary", "text" @@ -441,14 +441,28 @@ } 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, + Tcl_EncodingState state; + valueStr = Tcl_GetStringFromObj(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", (void *)NULL); + } else { + Tcl_AppendResult(interp, "Comment too large for zip", (void *)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; } @@ -462,13 +476,29 @@ } 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); + Tcl_EncodingState state; + valueStr = Tcl_GetStringFromObj(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", (void *)NULL); + } else { + Tcl_AppendResult( + interp, "Filename too large for zip", (void *)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; } @@ -545,13 +575,13 @@ if (latin1enc == NULL) { Tcl_Panic("no latin-1 encoding"); } } - Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->comment, -1, + (void)Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->comment, TCL_INDEX_NONE, &tmp); - SetValue(dictObj, "comment", TclDStringToObj(&tmp)); + SetValue(dictObj, "comment", Tcl_DStringToObj(&tmp)); } SetValue(dictObj, "crc", Tcl_NewBooleanObj(headerPtr->hcrc)); if (headerPtr->name != Z_NULL) { if (latin1enc == NULL) { /* @@ -562,13 +592,13 @@ if (latin1enc == NULL) { Tcl_Panic("no latin-1 encoding"); } } - Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->name, -1, + (void)Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->name, TCL_INDEX_NONE, &tmp); - SetValue(dictObj, "filename", TclDStringToObj(&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 */) { @@ -592,13 +622,16 @@ SetInflateDictionary( z_streamp strm, Tcl_Obj *compDictObj) { if (compDictObj != NULL) { - size_t length = 0; - unsigned char *bytes = TclGetByteArrayFromObj(compDictObj, &length); + Tcl_Size length = 0; + unsigned char *bytes = Tcl_GetByteArrayFromObj(compDictObj, &length); + if (bytes == NULL) { + return Z_DATA_ERROR; + } return inflateSetDictionary(strm, bytes, length); } return Z_OK; } @@ -606,13 +639,16 @@ SetDeflateDictionary( z_streamp strm, Tcl_Obj *compDictObj) { if (compDictObj != NULL) { - size_t length = 0; - unsigned char *bytes = TclGetByteArrayFromObj(compDictObj, &length); + Tcl_Size length = 0; + unsigned char *bytes = Tcl_GetByteArrayFromObj(compDictObj, &length); + if (bytes == NULL) { + return Z_DATA_ERROR; + } return deflateSetDictionary(strm, bytes, length); } return Z_OK; } @@ -802,21 +838,21 @@ /* * I could do all this in C, but this is easier. */ if (interp != NULL) { - if (Tcl_EvalEx(interp, "::incr ::tcl::zlib::cmdcounter", -1, 0) != TCL_OK) { + if (Tcl_EvalEx(interp, "::incr ::tcl::zlib::cmdcounter", TCL_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", NULL); + Tcl_SetErrorCode(interp, "TCL", "BUG", "EXISTING_CMD", (void *)NULL); Tcl_DStringFree(&cmdname); goto error; } Tcl_ResetResult(interp); @@ -1152,12 +1188,12 @@ Tcl_ZlibStream zshandle, Tcl_Obj *compressionDictionaryObj) { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; - if (compressionDictionaryObj && (NULL == TclGetBytesFromObj(NULL, - compressionDictionaryObj, NULL))) { + if (compressionDictionaryObj && (NULL == Tcl_GetByteArrayFromObj( + compressionDictionaryObj, (Tcl_Size *)NULL))) { /* Missing or invalid compression dictionary */ compressionDictionaryObj = NULL; } if (compressionDictionaryObj != NULL) { if (Tcl_IsShared(compressionDictionaryObj)) { @@ -1196,23 +1232,24 @@ * TCL_ZLIB_FULLFLUSH, or TCL_ZLIB_FINALIZE */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; char *dataTmp = NULL; int e; - size_t size = 0, outSize, toStore; + 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", NULL); + Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "CLOSED", (void *)NULL); } return TCL_ERROR; } - bytes = TclGetBytesFromObj(zshPtr->interp, data, &size); + bytes = Tcl_GetBytesFromObj(zshPtr->interp, data, &size); if (bytes == NULL) { return TCL_ERROR; } if (zshPtr->mode == TCL_ZLIB_STREAM_DEFLATE) { @@ -1321,34 +1358,34 @@ int Tcl_ZlibStreamGet( Tcl_ZlibStream zshandle, /* As obtained from Tcl_ZlibStreamInit */ Tcl_Obj *data, /* A place to append the data. */ - size_t count) /* Number of bytes to grab as a maximum, you + Tcl_Size count) /* Number of bytes to grab as a maximum, you * may get less! */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; - int e, i, listLen; - size_t itemLen = 0, dataPos = 0; + int e; + Tcl_Size listLen, i, itemLen = 0, dataPos = 0; Tcl_Obj *itemObj; unsigned char *dataPtr, *itemPtr; - size_t existing = 0; + Tcl_Size existing = 0; /* * Getting beyond the of stream, just return empty string. */ if (zshPtr->streamEnd) { return TCL_OK; } - if (NULL == TclGetBytesFromObj(zshPtr->interp, data, &existing)) { + if (NULL == Tcl_GetBytesFromObj(zshPtr->interp, data, &existing)) { return TCL_ERROR; } if (zshPtr->mode == TCL_ZLIB_STREAM_INFLATE) { - if (count == TCL_INDEX_NONE) { + if (count < 0) { /* * The only safe thing to do is restict to 65k. We might cause a * panic for out of memory if we just kept growing the buffer. */ @@ -1371,11 +1408,11 @@ if (zshPtr->currentInput) { Tcl_DecrRefCount(zshPtr->currentInput); zshPtr->currentInput = NULL; } - Tcl_ListObjLength(NULL, zshPtr->inData, &listLen); + TclListObjLengthM(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 @@ -1384,11 +1421,11 @@ Tcl_ListObjIndex(NULL, zshPtr->inData, 0, &itemObj); if (Tcl_IsShared(itemObj)) { itemObj = Tcl_DuplicateObj(itemObj); } - itemPtr = TclGetByteArrayFromObj(itemObj, &itemLen); + itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); Tcl_IncrRefCount(itemObj); zshPtr->currentInput = itemObj; zshPtr->stream.next_in = itemPtr; zshPtr->stream.avail_in = itemLen; @@ -1420,11 +1457,11 @@ if (e == Z_OK) { DictWasSet(zshPtr); e = inflate(&zshPtr->stream, zshPtr->flush); } }; - Tcl_ListObjLength(NULL, zshPtr->inData, &listLen); + TclListObjLengthM(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 @@ -1435,11 +1472,11 @@ if (zshPtr->interp) { Tcl_SetObjResult(zshPtr->interp, Tcl_NewStringObj( "unexpected zlib internal state during" " decompression", -1)); Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "STATE", - NULL); + (void *)NULL); } Tcl_SetByteArrayLength(data, existing); return TCL_ERROR; } @@ -1456,11 +1493,11 @@ Tcl_ListObjIndex(zshPtr->interp, zshPtr->inData, 0, &itemObj); if (Tcl_IsShared(itemObj)) { itemObj = Tcl_DuplicateObj(itemObj); } - itemPtr = TclGetByteArrayFromObj(itemObj, &itemLen); + itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); Tcl_IncrRefCount(itemObj); zshPtr->currentInput = itemObj; zshPtr->stream.next_in = itemPtr; zshPtr->stream.avail_in = itemLen; @@ -1500,16 +1537,16 @@ zshPtr->currentInput = 0; } inflateEnd(&zshPtr->stream); } } else { - Tcl_ListObjLength(NULL, zshPtr->outData, &listLen); - if (count == TCL_INDEX_NONE) { + TclListObjLengthM(NULL, zshPtr->outData, &listLen); + if (count < 0) { count = 0; for (i=0; ioutData, i, &itemObj); - (void) TclGetByteArrayFromObj(itemObj, &itemLen); + (void) Tcl_GetByteArrayFromObj(itemObj, &itemLen); if (i == 0) { count += itemLen - zshPtr->outPos; } else { count += itemLen; } @@ -1522,30 +1559,30 @@ dataPtr = Tcl_SetByteArrayLength(data, existing + count); dataPtr += existing; while ((count > dataPos) && - (Tcl_ListObjLength(NULL, zshPtr->outData, &listLen) == TCL_OK) + (TclListObjLengthM(NULL, zshPtr->outData, &listLen) == TCL_OK) && (listLen > 0)) { /* * Get the next chunk off our list of chunks and grab the data out * of it. */ Tcl_ListObjIndex(NULL, zshPtr->outData, 0, &itemObj); - itemPtr = TclGetByteArrayFromObj(itemObj, &itemLen); - if (itemLen-zshPtr->outPos + dataPos >= count) { - size_t len = count - dataPos; + itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); + if ((itemLen-zshPtr->outPos) >= count-dataPos) { + Tcl_Size len = count - dataPos; memcpy(dataPtr + dataPos, itemPtr + zshPtr->outPos, len); zshPtr->outPos += len; dataPos += len; if (zshPtr->outPos == itemLen) { zshPtr->outPos = 0; } } else { - size_t len = itemLen - zshPtr->outPos; + Tcl_Size len = itemLen - zshPtr->outPos; memcpy(dataPtr + dataPos, itemPtr + zshPtr->outPos, len); dataPos += len; zshPtr->outPos = 0; } @@ -1578,11 +1615,11 @@ Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj) { int wbits = 0, e = 0, extraSize = 0; - size_t inLen = 0; + Tcl_Size inLen = 0; Byte *inData = NULL; z_stream stream; GzipHeader header; gz_header *headerPtr = NULL; Tcl_Obj *obj; @@ -1594,11 +1631,11 @@ /* * Obtain the pointer to the byte array, we'll pass this pointer straight * to the deflate command. */ - inData = TclGetBytesFromObj(interp, data, &inLen); + inData = Tcl_GetBytesFromObj(interp, data, &inLen); if (inData == NULL) { return TCL_ERROR; } /* @@ -1700,11 +1737,11 @@ if (e != Z_OK) { goto error; } /* - * Reduce the bytearray length to the actual data length produced by + * Reduce the ByteArray length to the actual data length produced by * deflate. */ Tcl_SetByteArrayLength(obj, stream.total_out); Tcl_SetObjResult(interp, obj); @@ -1729,15 +1766,15 @@ int Tcl_ZlibInflate( Tcl_Interp *interp, int format, Tcl_Obj *data, - size_t bufferSize, + Tcl_Size bufferSize, Tcl_Obj *gzipHeaderDictObj) { int wbits = 0, e = 0; - size_t inLen = 0, newBufferSize; + Tcl_Size inLen = 0, newBufferSize; Byte *inData = NULL, *outData = NULL, *newOutData = NULL; z_stream stream; gz_header header, *headerPtr = NULL; Tcl_Obj *obj; char *nameBuf = NULL, *commentBuf = NULL; @@ -1744,11 +1781,11 @@ if (!interp) { return TCL_ERROR; } - inData = TclGetBytesFromObj(interp, data, &inLen); + inData = Tcl_GetBytesFromObj(interp, data, &inLen); if (inData == NULL) { return TCL_ERROR; } /* @@ -1918,21 +1955,21 @@ unsigned int Tcl_ZlibCRC32( unsigned int crc, const unsigned char *buf, - size_t len) + Tcl_Size len) { /* Nothing much to do, just wrap the crc32(). */ return crc32(crc, (Bytef *) buf, len); } unsigned int Tcl_ZlibAdler32( unsigned int adler, const unsigned char *buf, - size_t len) + Tcl_Size len) { return adler32(adler, (Bytef *) buf, len); } /* @@ -1950,12 +1987,14 @@ TCL_UNUSED(void *), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - int command, i, option, level = -1; - size_t dlen = 0, start, buffersize = 0; + int i, option, level = -1; + size_t buffersize = 0; + Tcl_Size dlen = 0; + unsigned int start; Tcl_WideInt wideLen; Byte *data; Tcl_Obj *headerDictObj; const char *extraInfoStr = NULL; static const char *const commands[] = { @@ -1964,11 +2003,11 @@ 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; } @@ -1975,18 +2014,18 @@ if (Tcl_GetIndexFromObj(interp, objv[1], commands, "command", 0, &command) != TCL_OK) { return TCL_ERROR; } - switch ((enum zlibCommands) command) { + switch (command) { case CMD_ADLER: /* adler32 str ?startvalue? * -> checksum */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?"); return TCL_ERROR; } - data = TclGetBytesFromObj(interp, objv[2], &dlen); + data = Tcl_GetBytesFromObj(interp, objv[2], &dlen); if (data == NULL) { return TCL_ERROR; } if (objc>3 && Tcl_GetIntFromObj(interp, objv[3], (int *) &start) != TCL_OK) { @@ -2002,11 +2041,11 @@ * -> checksum */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?"); return TCL_ERROR; } - data = TclGetBytesFromObj(interp, objv[2], &dlen); + data = Tcl_GetBytesFromObj(interp, objv[2], &dlen); if (data == NULL) { return TCL_ERROR; } if (objc>3 && Tcl_GetIntFromObj(interp, objv[3], (int *) &start) != TCL_OK) { @@ -2199,20 +2238,20 @@ return TCL_ERROR; badLevel: Tcl_SetObjResult(interp, Tcl_NewStringObj("level must be 0 to 9", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", (void *)NULL); if (extraInfoStr) { Tcl_AddErrorInfo(interp, extraInfoStr); } return TCL_ERROR; badBuffer: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "buffer size must be %d to %d", MIN_NONSTREAM_BUFFER_SIZE, MAX_BUFFER_SIZE)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", (void *)NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -2235,11 +2274,11 @@ 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, @@ -2276,20 +2315,20 @@ if (objc < 3 || !(objc & 1)) { Tcl_WrongNumArgs(interp, 2, objv, "mode ?-option value...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], stream_formats, "mode", 0, - &format) != TCL_OK) { + &fmt) != TCL_OK) { return TCL_ERROR; } /* * The format determines the compression mode and the options that may be * specified. */ - switch ((enum zlibFormats) format) { + switch (fmt) { case FMT_DEFLATE: desc = compressionOpts; mode = TCL_ZLIB_STREAM_DEFLATE; format = TCL_ZLIB_FORMAT_RAW; break; @@ -2343,17 +2382,17 @@ 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_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", (void *)NULL); Tcl_AddErrorInfo(interp, "\n (in -level option)"); return TCL_ERROR; } if (compDictObj) { - if (NULL == TclGetBytesFromObj(interp, compDictObj, NULL)) { + if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL)) { return TCL_ERROR; } } /* @@ -2395,34 +2434,35 @@ NULL }; enum zlibFormats { FMT_COMPRESS, FMT_DECOMPRESS, FMT_DEFLATE, FMT_GUNZIP, FMT_GZIP, FMT_INFLATE - }; + } fmt; Tcl_Channel chan; - int chanMode, format, mode = 0, level, i, option; + int chanMode, format, mode = 0, level, i; static const char *const pushCompressOptions[] = { "-dictionary", "-header", "-level", NULL }; static const char *const pushDecompressOptions[] = { "-dictionary", "-header", "-level", "-limit", NULL }; const char *const *pushOptions = pushDecompressOptions; - enum pushOptionsEnum {poDictionary, poHeader, poLevel, poLimit}; + enum pushOptionsEnum {poDictionary, poHeader, poLevel, poLimit} option; Tcl_Obj *headerObj = NULL, *compDictObj = NULL; - int limit = DEFAULT_BUFFER_SIZE, dummy; + int limit = DEFAULT_BUFFER_SIZE; + Tcl_Size dummy; if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "mode channel ?options...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], stream_formats, "mode", 0, - &format) != TCL_OK) { + &fmt) != TCL_OK) { return TCL_ERROR; } - switch ((enum zlibFormats) format) { + switch (fmt) { case FMT_DEFLATE: mode = TCL_ZLIB_STREAM_DEFLATE; format = TCL_ZLIB_FORMAT_RAW; pushOptions = pushCompressOptions; break; @@ -2461,17 +2501,17 @@ */ 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); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNWRITABLE", (void *)NULL); return TCL_ERROR; } if (mode == TCL_ZLIB_STREAM_INFLATE && !(chanMode & TCL_READABLE)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "decompression may only be applied to readable channels",-1)); - Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNREADABLE", NULL); + "decompression may only be applied to readable channels",TCL_INDEX_NONE)); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNREADABLE", (void *)NULL); return TCL_ERROR; } /* * Parse options. @@ -2484,14 +2524,14 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (void *)NULL); return TCL_ERROR; } - switch ((enum pushOptionsEnum) option) { + switch (option) { case poHeader: headerObj = objv[i]; if (Tcl_DictObjSize(interp, headerObj, &dummy) != TCL_OK) { goto genericOptionError; } @@ -2502,11 +2542,11 @@ } if (level < 0 || level > 9) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "level must be 0 to 9", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", - NULL); + (void *)NULL); goto genericOptionError; } break; case poLimit: if (Tcl_GetIntFromObj(interp, objv[i], (int*) &limit) != TCL_OK) { @@ -2514,28 +2554,28 @@ } if (limit < 1 || limit > MAX_BUFFER_SIZE) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "read ahead limit must be 1 to %d", MAX_BUFFER_SIZE)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOPT", (void *)NULL); goto genericOptionError; } compDictObj = objv[i]; break; } } - if (compDictObj && (NULL == TclGetBytesFromObj(interp, compDictObj, NULL))) { + if (compDictObj && (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL))) { return TCL_ERROR; } if (ZlibStackChannelTransform(interp, mode, format, level, limit, chan, headerObj, compDictObj) == NULL) { @@ -2567,21 +2607,21 @@ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd; - int command, count, code; + 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; } @@ -2589,11 +2629,11 @@ if (Tcl_GetIndexFromObj(interp, objv[1], cmds, "option", 0, &command) != TCL_OK) { return TCL_ERROR; } - switch ((enum zlibStreamCommands) command) { + switch (command) { case zs_add: /* $strm add ?$flushopt? $data */ return ZlibStreamAddCmd(zstream, interp, objc, objv); case zs_header: /* $strm header */ return ZlibStreamHeaderCmd(zstream, interp, objc, objv); case zs_put: /* $strm put ?$flushopt? $data */ @@ -2693,26 +2733,26 @@ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd; - int index, code, buffersize = -1, flush = -1, i; + 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= 0) { flush = -2; } else { flush = Z_SYNC_FLUSH; @@ -2735,30 +2775,30 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (void *)NULL); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[++i], &buffersize) != TCL_OK) { return TCL_ERROR; } if (buffersize < 1 || buffersize > MAX_BUFFER_SIZE) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "buffer size must be 1 to %d", MAX_BUFFER_SIZE)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (void *)NULL); return TCL_ERROR; } compDictObj = objv[++i]; break; } @@ -2765,11 +2805,11 @@ if (flush == -2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-flush\", \"-fullflush\" and \"-finalize\" options" " are mutually exclusive", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", NULL); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", (void *)NULL); return TCL_ERROR; } } if (flush == -1) { flush = 0; @@ -2778,13 +2818,13 @@ /* * Set the compression dictionary if requested. */ if (compDictObj != NULL) { - size_t len = 0; + Tcl_Size len = 0; - if (NULL == TclGetBytesFromObj(interp, compDictObj, &len)) { + if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, &len)) { return TCL_ERROR; } if (len == 0) { compDictObj = NULL; @@ -2820,26 +2860,26 @@ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd; - int index, flush = -1, i; + 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= 0) { flush = -2; } else { flush = Z_SYNC_FLUSH; @@ -2862,21 +2902,21 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (void *)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); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", (void *)NULL); return TCL_ERROR; } } if (flush == -1) { flush = 0; @@ -2885,13 +2925,13 @@ /* * Set the compression dictionary if requested. */ if (compDictObj != NULL) { - size_t len = 0; + Tcl_Size len = 0; - if (NULL == TclGetBytesFromObj(interp, compDictObj, &len)) { + if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, &len)) { return TCL_ERROR; } if (len == 0) { compDictObj = NULL; } @@ -2920,11 +2960,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOP", (void *)NULL); return TCL_ERROR; } TclNewObj(resultObj); ExtractHeader(&zshPtr->gzHeaderPtr->header, resultObj); @@ -3328,11 +3368,11 @@ Tcl_Obj *compDictObj; int code; TclNewStringObj(compDictObj, value, strlen(value)); Tcl_IncrRefCount(compDictObj); - if (NULL == TclGetBytesFromObj(interp, compDictObj, NULL)) { + if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL)) { Tcl_DecrRefCount(compDictObj); return TCL_ERROR; } if (cd->compDictObj) { TclDecrRefCount(cd->compDictObj); @@ -3365,11 +3405,11 @@ flushType = Z_SYNC_FLUSH; } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown -flush type \"%s\": must be full or sync", value)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "FLUSH", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "FLUSH", (void *)NULL); return TCL_ERROR; } /* * Try to actually do the flush now. @@ -3384,11 +3424,11 @@ 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); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "READLIMIT", (void *)NULL); return TCL_ERROR; } } } @@ -3452,11 +3492,11 @@ crc = cd->outStream.adler; } else { crc = cd->inStream.adler; } - sprintf(buf, "%lu", crc); + snprintf(buf, sizeof(buf), "%lu", crc); if (optionName == NULL) { Tcl_DStringAppendElement(dsPtr, "-checksum"); Tcl_DStringAppendElement(dsPtr, buf); } else { Tcl_DStringAppend(dsPtr, buf, -1); @@ -3478,12 +3518,12 @@ } else { Tcl_DStringAppendElement(dsPtr, ""); } } else { if (cd->compDictObj) { - size_t length; - const char *str = TclGetStringFromObj(cd->compDictObj, &length); + Tcl_Size length; + const char *str = Tcl_GetStringFromObj(cd->compDictObj, &length); Tcl_DStringAppend(dsPtr, str, length); } return TCL_OK; } @@ -3719,11 +3759,11 @@ } if (compDictObj != NULL) { cd->compDictObj = Tcl_DuplicateObj(compDictObj); Tcl_IncrRefCount(cd->compDictObj); - Tcl_GetByteArrayFromObj(cd->compDictObj, NULL); + Tcl_GetByteArrayFromObj(cd->compDictObj, (Tcl_Size *)NULL); } if (format == TCL_ZLIB_FORMAT_RAW) { wbits = WBITS_RAW; } else if (format == TCL_ZLIB_FORMAT_ZLIB) { @@ -3937,11 +3977,11 @@ * This does two things. It creates a counter used in the creation of * stream commands, and it creates the namespace that will contain those * commands. */ - Tcl_EvalEx(interp, "namespace eval ::tcl::zlib {variable cmdcounter 0}", -1, 0); + Tcl_EvalEx(interp, "namespace eval ::tcl::zlib {variable cmdcounter 0}", TCL_INDEX_NONE, 0); /* * Create the public scripted interface to this file's functionality. */ @@ -3967,11 +4007,11 @@ /* * Formally provide the package as a Tcl built-in. */ - return Tcl_PkgProvideEx(interp, "zlib", TCL_ZLIB_VERSION, NULL); + return Tcl_PkgProvideEx(interp, "tcl::zlib", TCL_ZLIB_VERSION, NULL); } /* *---------------------------------------------------------------------- * Stubs used when a suitable zlib installation was not found during @@ -4079,22 +4119,22 @@ return TCL_ERROR; } unsigned int Tcl_ZlibCRC32( - unsigned int crc, - const unsigned char *buf, - size_t len) + TCL_UNUSED(unsigned int), + TCL_UNUSED(const unsigned char *), + TCL_UNUSED(size_t)) { return 0; } unsigned int Tcl_ZlibAdler32( - unsigned int adler, - const unsigned char *buf, - size_t len) + TCL_UNUSED(unsigned int), + TCL_UNUSED(const unsigned char *), + TCL_UNUSED(size_t)) { return 0; } void Index: library/auto.tcl ================================================================== --- library/auto.tcl +++ library/auto.tcl @@ -1,12 +1,12 @@ # auto.tcl -- # # utility procs formerly in init.tcl dealing with auto execution of commands # and can be auto loaded themselves. # -# Copyright (c) 1991-1993 The Regents of the University of California. -# Copyright (c) 1994-1998 Sun Microsystems, Inc. +# Copyright © 1991-1993 The Regents of the University of California. +# Copyright © 1994-1998 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # @@ -68,64 +68,74 @@ # 1. From an environment variable, if it exists. Placing this first # gives the end-user ultimate control to work-around any bugs, or # to customize. - if {[info exists env($enVarName)]} { - lappend dirs $env($enVarName) - } + if {[info exists env($enVarName)]} { + lappend dirs $env($enVarName) + } catch { - set found 0 + set found 0 set root [zipfs root] - set mountpoint [file join $root lib [string tolower $basename]] - lappend dirs [file join $root app ${basename}_library] - lappend dirs [file join $root lib $mountpoint ${basename}_library] - lappend dirs [file join $root lib $mountpoint] + set mountpoint [file join $root lib $basename] + lappend dirs [file join $root app ${basename}_library] + lappend dirs [file join $root lib ${basename} ${basename}_library] + lappend dirs [file join $root lib ${basename}] if {![zipfs exists [file join $root app ${basename}_library]] \ - && ![zipfs exists $mountpoint]} { - set found 0 - foreach pkgdat [info loaded] { - lassign $pkgdat dllfile dllpkg - if {[string tolower $dllpkg] ne [string tolower $basename]} continue - if {$dllfile eq {}} { - # Loaded statically - break - } - set found 1 - zipfs mount $mountpoint $dllfile - break - } - if {!$found} { - set paths {} - lappend paths [file join $root app] - lappend paths [::${basename}::pkgconfig get libdir,runtime] - lappend paths [::${basename}::pkgconfig get bindir,runtime] - if {[catch {::${basename}::pkgconfig get zipfile,runtime} zipfile]} { - 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} - } - } - } - } - } + && ![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 { @@ -156,23 +166,23 @@ # ../../foo1.0.1/library # (From unix directory in parallel build hierarchy) # ../../../foo1.0.1/library # (From unix/arch directory in parallel build hierarchy) - set parentDir [file dirname [file dirname [info nameofexecutable]]] - set grandParentDir [file dirname $parentDir] - lappend dirs [file join $parentDir lib $basename$version] - lappend dirs [file join $grandParentDir lib $basename$version] - lappend dirs [file join $parentDir library] + set parentDir [file dirname [file dirname [info nameofexecutable]]] + set grandParentDir [file dirname $parentDir] + lappend dirs [file join $parentDir lib $basename$version] + lappend dirs [file join $grandParentDir lib $basename$version] + lappend dirs [file join $parentDir library] if {0} { lappend dirs [file join $grandParentDir library] lappend dirs [file join $grandParentDir $basename$patch library] lappend dirs [file join [file dirname $grandParentDir] \ $basename$patch library] } } - # uniquify $dirs in order + # make $dirs unique, preserving order array set seen {} foreach i $dirs { # Make sure $i is unique under normalization. Avoid repeated [source]. if {[interp issafe]} { # Safe interps have no [file normalize]. @@ -183,23 +193,23 @@ if {[info exists seen($norm)]} { continue } set seen($norm) {} - set the_library $i - set file [file join $i $initScript] + set the_library $i + set file [file join $i $initScript] # source everything when in a safe interpreter because we have a # source command, but no file exists command - if {[interp issafe] || [file exists $file]} { - if {![catch {uplevel #0 [list source $file]} msg opts]} { - return - } + if {[interp issafe] || [file exists $file]} { + if {![catch {uplevel #0 [list source $file]} msg opts]} { + return + } append errors "$file: $msg\n" append errors [dict get $opts -errorinfo]\n - } + } } unset -nocomplain the_library set msg "Can't find a usable $initScript in the following directories: \n" append msg " $dirs\n\n" append msg "$errors\n\n" @@ -234,11 +244,11 @@ # within dir. If no additional are given auto_mkindex will look # for *.tcl. proc auto_mkindex {dir args} { if {[interp issafe]} { - error "can't generate index within safe interpreter" + error "can't generate index within safe interpreter" } set oldDir [pwd] cd $dir @@ -290,11 +300,11 @@ } foreach file [lsort [glob -- {*}$args]] { set f "" set error [catch { set f [open $file] - fconfigure $f -encoding utf-8 -eofchar \032 + fconfigure $f -encoding utf-8 -eofchar \x1A while {[gets $f line] >= 0} { if {[regexp {^proc[ ]+([^ ]*)} $line match procName]} { set procName [lindex [auto_qualify $procName "::"] 0] append index "set [list auto_index($procName)]" append index " \[list source \[file join \$dir [list $file]\]\]\n" @@ -368,11 +378,11 @@ $parser expose namespace $parser invokehidden rename namespace _%@namespace $parser expose eval $parser invokehidden rename eval _%@eval - # Install all the registered psuedo-command implementations + # Install all the registered pseudo-command implementations foreach cmd $initCommands { eval $cmd } } @@ -402,11 +412,11 @@ variable imports set scriptFile $file set fid [open $file] - fconfigure $fid -encoding utf-8 -eofchar \032 + fconfigure $fid -encoding utf-8 -eofchar \x1A set contents [read $fid] close $fid # There is one problem with sourcing files into the safe interpreter: # references like "$x" will fail since code is not really being executed @@ -422,11 +432,11 @@ set imports "" $parser eval $contents foreach name $imports { - catch {$parser eval [list _%@namespace forget $name]} + catch {$parser eval [list _%@namespace forget $name]} } return $index } # auto_mkindex_parser::hook command @@ -492,23 +502,23 @@ variable parser set ns [namespace qualifiers $name] set tail [namespace tail $name] if {$ns eq ""} { - set fakeName [namespace current]::_%@fake_$tail + set fakeName [namespace current]::_%@fake_$tail } else { - set fakeName [namespace current]::[string map {:: _} _%@fake_$name] + set fakeName [namespace current]::[string map {:: _} _%@fake_$name] } proc $fakeName $arglist $body # YUK! Tcl won't let us alias fully qualified command names, so we can't # handle names like "::itcl::class". Instead, we have to build procs with # the fully qualified names, and have the procs point to the aliases. if {[string match *::* $name]} { - set exportCmd [list _%@namespace export [namespace tail $name]] - $parser eval [list _%@namespace eval $ns $exportCmd] + set exportCmd [list _%@namespace export [namespace tail $name]] + $parser eval [list _%@namespace eval $ns $exportCmd] # The following proc definition does not work if you want to tolerate # space or something else diabolical in the procedure name, (i.e., # space in $alias). The following does not work: # "_%@eval {$alias} \$args" @@ -516,15 +526,15 @@ # because $cmd is somehow undefined # "set cmd {$alias} \; _%@eval {\$cmd} \$args" # A gold star to someone that can make test autoMkindex-3.3 work # properly - set alias [namespace tail $fakeName] - $parser invokehidden proc $name {args} "_%@eval {$alias} \$args" - $parser alias $alias $fakeName + set alias [namespace tail $fakeName] + $parser invokehidden proc $name {args} "_%@eval {$alias} \$args" + $parser alias $alias $fakeName } else { - $parser alias $name $fakeName + $parser alias $name $fakeName } return } # auto_mkindex_parser::fullname -- @@ -542,22 +552,22 @@ proc auto_mkindex_parser::fullname {name} { variable contextStack if {![string match ::* $name]} { - foreach ns $contextStack { - set name "${ns}::$name" - if {[string match ::* $name]} { - break - } - } + foreach ns $contextStack { + set name "${ns}::$name" + if {[string match ::* $name]} { + break + } + } } if {[namespace qualifiers $name] eq ""} { - set name [namespace tail $name] + set name [namespace tail $name] } elseif {![string match ::* $name]} { - set name "::$name" + set name "::$name" } # Earlier, mkindex replaced all $'s with \0. Now, we have to reverse that # replacement. return [string map [list \0 \$] $name] @@ -621,11 +631,11 @@ auto_load tbcload::bcproc } load {} tbcload $auto_mkindex_parser::parser # AUTO MKINDEX: tbcload::bcproc name arglist body - # Adds an entry to the auto index list for the given pre-compiled + # Adds an entry to the auto index list for the given precompiled # procedure name. auto_mkindex_parser::commandInit tbcload::bcproc {name args} { indexEntry $name } @@ -643,31 +653,31 @@ # 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] + 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"} - } + 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] ::] @@ -676,11 +686,11 @@ if {![string match ::* $name]} { set name ::[join [lreverse $contextStack] ::]$name } regsub -all ::+ $name :: name } - # create artifical proc to force an entry in the tclIndex + # create artificial proc to force an entry in the tclIndex $parser eval [list ::proc $name {} {}] } } } } Index: library/clock.tcl ================================================================== --- library/clock.tcl +++ library/clock.tcl @@ -7,11 +7,11 @@ # the [clock] command and its subcommands. # # #---------------------------------------------------------------------- # -# Copyright (c) 2004,2005,2006,2007 by Kevin B. Kenny +# Copyright © 2004-2007 Kevin B. Kenny # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #---------------------------------------------------------------------- @@ -221,11 +221,11 @@ # Russia ::msgcat::mcset ru GREGORIAN_CHANGE_DATE 2421639 - # Romania (Transylvania changed earler - perhaps de_RO should show the + # Romania (Transylvania changed earlier - perhaps de_RO should show the # earlier date?) ::msgcat::mcset ro GREGORIAN_CHANGE_DATE 2422063 # Greece @@ -308,55 +308,55 @@ variable WinZoneInfo [dict create {*}{ {-43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Kwajalein {-39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Midway {-36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Honolulu - {-32400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Anchorage - {-28800 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Los_Angeles - {-28800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Tijuana - {-25200 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Denver - {-25200 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Chihuahua + {-32400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Anchorage + {-28800 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Los_Angeles + {-28800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Tijuana + {-25200 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Denver + {-25200 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Chihuahua {-25200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Phoenix {-21600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Regina {-21600 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Chicago - {-21600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Mexico_City + {-21600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Mexico_City {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/New_York {-18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Indianapolis {-14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Caracas - {-14400 0 3600 0 3 6 2 23 59 59 999 0 10 6 2 23 59 59 999} + {-14400 0 3600 0 3 6 2 23 59 59 999 0 10 6 2 23 59 59 999} :America/Santiago - {-14400 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Manaus - {-14400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Halifax + {-14400 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Manaus + {-14400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Halifax {-12600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/St_Johns {-10800 0 3600 0 2 0 2 2 0 0 0 0 10 0 3 2 0 0 0} :America/Sao_Paulo {-10800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Godthab {-10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Buenos_Aires - {-10800 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Bahia - {-10800 0 3600 0 3 0 2 2 0 0 0 0 10 0 1 2 0 0 0} :America/Montevideo + {-10800 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Bahia + {-10800 0 3600 0 3 0 2 2 0 0 0 0 10 0 1 2 0 0 0} :America/Montevideo {-7200 0 3600 0 9 0 5 2 0 0 0 0 3 0 5 2 0 0 0} :America/Noronha {-3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Atlantic/Azores {-3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Atlantic/Cape_Verde {0 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :UTC {0 0 3600 0 10 0 5 2 0 0 0 0 3 0 5 1 0 0 0} :Europe/London {3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Kinshasa {3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :CET - {7200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Harare - {7200 0 3600 0 9 4 5 23 59 59 0 0 4 4 5 23 59 59 0} + {7200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Harare + {7200 0 3600 0 9 4 5 23 59 59 0 0 4 4 5 23 59 59 0} :Africa/Cairo {7200 0 3600 0 10 0 5 4 0 0 0 0 3 0 5 3 0 0 0} :Europe/Helsinki - {7200 0 3600 0 9 0 3 2 0 0 0 0 3 5 5 2 0 0 0} :Asia/Jerusalem + {7200 0 3600 0 9 0 3 2 0 0 0 0 3 5 5 2 0 0 0} :Asia/Jerusalem {7200 0 3600 0 9 0 5 1 0 0 0 0 3 0 5 0 0 0 0} :Europe/Bucharest {7200 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Athens - {7200 0 3600 0 9 5 5 1 0 0 0 0 3 4 5 0 0 0 0} :Asia/Amman - {7200 0 3600 0 10 6 5 23 59 59 999 0 3 0 5 0 0 0 0} + {7200 0 3600 0 9 5 5 1 0 0 0 0 3 4 5 0 0 0 0} :Asia/Amman + {7200 0 3600 0 10 6 5 23 59 59 999 0 3 0 5 0 0 0 0} :Asia/Beirut - {7200 0 -3600 0 4 0 1 2 0 0 0 0 9 0 1 2 0 0 0} :Africa/Windhoek + {7200 0 -3600 0 4 0 1 2 0 0 0 0 9 0 1 2 0 0 0} :Africa/Windhoek {10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Riyadh {10800 0 3600 0 10 0 1 4 0 0 0 0 4 0 1 3 0 0 0} :Asia/Baghdad {10800 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Moscow {12600 0 3600 0 9 2 4 2 0 0 0 0 3 0 1 2 0 0 0} :Asia/Tehran - {14400 0 3600 0 10 0 5 5 0 0 0 0 3 0 5 4 0 0 0} :Asia/Baku + {14400 0 3600 0 10 0 5 5 0 0 0 0 3 0 5 4 0 0 0} :Asia/Baku {14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Muscat {14400 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Tbilisi {16200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Kabul {18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Karachi {18000 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Yekaterinburg @@ -582,12 +582,12 @@ jt +0730 \ cct +0800 \ jst +0900 \ kst +0900 \ cast +0930 \ - jdt +1000 \ - kdt +1000 \ + jdt +1000 \ + kdt +1000 \ cadt +1030 \ east +1000 \ eadt +1030 \ gst +1000 \ nzt +1200 \ @@ -1156,12 +1156,12 @@ append retval %%O } } proc $procName {clockval timezone} " - $preFormatCode - return \[::format [list $formatString] $substituents\] + $preFormatCode + return \[::format [list $formatString] $substituents\] " # puts [list $procName [info args $procName] [info body $procName]] return $procName @@ -1171,11 +1171,11 @@ # # 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 +# The 'clock scan' command scans times of day on input. Refer to the user # documentation to see what it does. # #---------------------------------------------------------------------- proc ::tcl::clock::scan { args } { @@ -1187,14 +1187,14 @@ 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?\"" + \"$cmdName string\ + ?-base seconds?\ + ?-format string? ?-gmt boolean?\ + ?-locale LOCALE? ?-timezone ZONE?\"" } # Set defaults set base [clock seconds] @@ -1205,32 +1205,35 @@ 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 saw(-format) {} set format $value } -g - -gm - -gmt { + set saw(-gmt) {} set gmt $value } -l - -lo - -loc - -loca - -local - -locale { + set saw(-locale) {} set locale [string tolower $value] } -t - -ti - -tim - -time - -timez - -timezo - -timezon - -timezone { + set saw(-timezone) {} set timezone $value } default { return -code error \ -errorcode [list CLOCK badOption $flag] \ "bad option \"$flag\",\ - must be -base, -format, -gmt, -locale or -timezone" + must be -base, -format, -gmt, -locale or -timezone" } } } # Check options for validity @@ -1973,11 +1976,11 @@ # 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] } { + && ![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" } @@ -2296,11 +2299,11 @@ # # Results: # Returns the locale that was previously current. # # Side effects: -# Does [mclocale]. If necessary, loades the designated locale's files. +# Does [mclocale]. If necessary, loads the designated locale's files. # #---------------------------------------------------------------------- proc ::tcl::clock::EnterLocale { locale } { if { $locale eq {system} } { @@ -2377,12 +2380,12 @@ MMM %b MM %m M %N yyyy %Y yy %y - y %y - gg {} + y %y + gg {} } $unquoted] if { $quoted eq {} } { set quote ' } else { set quote $quoted @@ -2407,12 +2410,12 @@ MMM %b MM %m M %N yyyy %Y yy %y - y %y - gg {} + y %y + gg {} } $unquoted] if { $quoted eq {} } { set quote ' } else { set quote $quoted @@ -2603,11 +2606,11 @@ # # Parses a StarDate # # Parameters: # year - Year from the Roddenberry epoch -# fractYear - Fraction of a year specifiying the day of year. +# fractYear - Fraction of a year specifying the day of year. # fractDay - Fraction of a day # # Results: # Returns a count of seconds from the Posix epoch. # @@ -2973,11 +2976,11 @@ # # Results: # Returns the system time zone. # # Side effects: -# Stores the sustem time zone in the 'CachedSystemTimeZone' +# Stores the system time zone in the 'CachedSystemTimeZone' # variable, since determining it may be an expensive process. # #---------------------------------------------------------------------- proc ::tcl::clock::GetSystemTimeZone {} { @@ -2986,25 +2989,24 @@ 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 - } + } else { + # 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}] } @@ -3400,11 +3402,11 @@ fconfigure $f -translation binary set d [read $f] close $f # The file begins with a magic number, sixteen reserved bytes, and then - # six 4-byte integers giving counts of fileds in the file. + # six 4-byte integers giving counts of fields in the file. binary scan $d a4a1x15IIIIII \ magic version nIsGMT nIsStd nLeap nTime nType nChar set seek 44 set ilen 4 @@ -3607,47 +3609,47 @@ ([[:digit:]]{1,2}) (?: # 4 - Standard time zone offset, minutes : ([[:digit:]]{1,2}) (?: - # 5 - Standard time zone offset, seconds + # 5 - Standard time zone offset, seconds : ([[:digit:]]{1,2} ) )? )? (?: # 6 - DST time zone name ([[:alpha:]]+ | <[-+[:alnum:]]+>) (?: - (?: + (?: # 7 - DST time zone offset, signum ([-+]?) # 8 - DST time zone offset, hours ([[:digit:]]{1,2}) (?: # 9 - DST time zone offset, minutes : ([[:digit:]]{1,2}) (?: - # 10 - DST time zone offset, seconds + # 10 - DST time zone offset, seconds : ([[:digit:]]{1,2}) )? )? )? - (?: + (?: , (?: # 11 - Optional J in n and Jn form 12 - Day of year - ( J ? ) ( [[:digit:]]+ ) - | M + ( J ? ) ( [[:digit:]]+ ) + | M # 13 - Month number 14 - Week of month 15 - Day of week ( [[:digit:]] + ) [.] ( [[:digit:]] + ) [.] ( [[:digit:]] + ) ) (?: # 16 - Start time of DST - hours / ( [[:digit:]]{1,2} ) - (?: + (?: # 17 - Start time of DST - minutes : ( [[:digit:]]{1,2} ) (?: # 18 - Start time of DST - seconds : ( [[:digit:]]{1,2} ) @@ -3655,32 +3657,32 @@ )? )? , (?: # 19 - Optional J in n and Jn form 20 - Day of year - ( J ? ) ( [[:digit:]]+ ) - | M + ( J ? ) ( [[:digit:]]+ ) + | M # 21 - Month number 22 - Week of month 23 - Day of week ( [[:digit:]] + ) [.] ( [[:digit:]] + ) [.] ( [[:digit:]] + ) ) (?: # 24 - End time of DST - hours / ( [[:digit:]]{1,2} ) - (?: + (?: # 25 - End time of DST - minutes : ( [[:digit:]]{1,2} ) (?: # 26 - End time of DST - seconds : ( [[:digit:]]{1,2} ) )? )? )? - )? + )? )? - )? + )? $ } $tz -> x(stdName) x(stdSignum) x(stdHours) x(stdMinutes) x(stdSeconds) \ x(dstName) x(dstSignum) x(dstHours) x(dstMinutes) x(dstSeconds) \ x(startJ) x(startDayOfYear) \ x(startMonth) x(startWeekOfMonth) x(startDayOfWeek) \ @@ -4242,12 +4244,12 @@ 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?\"" + \"$cmdName clockval ?number units?...\ + ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?\"" } if { [catch { expr {wide($clockval)} } result] } { return -code error $result } @@ -4260,23 +4262,25 @@ if { [string is integer -strict $a] } { lappend offsets $a $b } else { switch -exact -- $a { -g - -gm - -gmt { + set saw(-gmt) {} set gmt $b } -l - -lo - -loc - -loca - -local - -locale { set locale [string tolower $b] } -t - -ti - -tim - -time - -timez - -timezo - -timezon - -timezone { + set saw(-timezone) {} set timezone $b } default { throw [list CLOCK badOption $a] \ "bad option \"$a\",\ - must be -gmt, -locale or -timezone" + must be -gmt, -locale or -timezone" } } } } @@ -4337,11 +4341,11 @@ } default { throw [list CLOCK badUnit $unit] \ "unknown unit \"$unit\", must be \ - years, months, weeks, days, hours, minutes or seconds" + years, months, weeks, days, hours, minutes or seconds" } } } return $clockval } trap CLOCK {result opts} { @@ -4497,14 +4501,14 @@ variable LocaleNumeralCache variable CachedSystemTimeZone variable TimeZoneBad foreach p [info procs [namespace current]::scanproc'*'current] { - rename $p {} + rename $p {} } foreach p [info procs [namespace current]::formatproc'*'current] { - rename $p {} + rename $p {} } catch {array unset FormatProc *'current} set LocaleNumeralCache {} } Index: library/cookiejar/cookiejar.tcl ================================================================== --- library/cookiejar/cookiejar.tcl +++ library/cookiejar/cookiejar.tcl @@ -55,13 +55,13 @@ # Keep this in sync with pkgIndex.tcl and with the install directories in # Makefiles variable version 0.2.0 variable domainlist \ - http://publicsuffix.org/list/effective_tld_names.dat + https://publicsuffix.org/list/public_suffix_list.dat variable domainfile \ - [file join [file dirname [info script]] effective_tld_names.txt.gz] + [file join [file dirname [info script]] public_suffix_list.dat.gz] # The list is directed to from http://publicsuffix.org/list/ variable loglevel info variable vacuumtrigger 200 variable retainlimit 100 variable offline false @@ -130,11 +130,11 @@ [set [info object namespace ::http::cookiejar]::version] # The implementation of the cookiejar package ::oo::define ::http::cookiejar { self { - method configure {{optionName "\u0000\u0000"} {optionValue "\u0000\u0000"}} { + method configure {{optionName "\x00\x00"} {optionValue "\x00\x00"}} { set tbl { -domainfile {domainfile set} -domainlist {domainlist set} -domainrefresh {refreshinterval setInterval} -loglevel {loglevel setLog} @@ -147,18 +147,18 @@ my IntervalTrigger PostponeRefresh }] dict lappend tbl -purgeold [namespace code { my IntervalTrigger PostponePurge }] - if {$optionName eq "\u0000\u0000"} { + if {$optionName eq "\x00\x00"} { return [dict keys $tbl] } set opt [::tcl::prefix match -message "option" \ [dict keys $tbl] $optionName] set setter [lassign [dict get $tbl $opt] varname] namespace upvar [namespace current] $varname var - if {$optionValue ne "\u0000\u0000"} { + if {$optionValue ne "\x00\x00"} { {*}$setter var $optionValue } return $var } DELETED library/cookiejar/effective_tld_names.txt.gz Index: library/cookiejar/effective_tld_names.txt.gz ================================================================== --- library/cookiejar/effective_tld_names.txt.gz +++ /dev/null cannot compute difference between binary files Index: library/cookiejar/idna.tcl ================================================================== --- library/cookiejar/idna.tcl +++ library/cookiejar/idna.tcl @@ -1,15 +1,15 @@ -# cookiejar.tcl -- +# idna.tcl -- # # Implementation of IDNA (Internationalized Domain Names for # Applications) encoding/decoding system, built on a punycode engine # developed directly from the code in RFC 3492, Appendix C (with # substantial modifications). # # This implementation includes code from that RFC, translated to Tcl; the # other parts are: -# Copyright (c) 2014 Donal K. Fellows +# Copyright © 2014 Donal K. Fellows # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. namespace eval ::tcl::idna { @@ -25,13 +25,13 @@ } proc IDNAencode hostname { set parts {} # Split term from RFC 3490, Sec 3.1 - foreach part [split $hostname "\u002E\u3002\uFF0E\uFF61"] { + foreach part [split $hostname "\x2E\u3002\uFF0E\uFF61"] { if {[regexp {[^-A-Za-z0-9]} $part]} { - if {[regexp {[^-A-Za-z0-9\u00a1-\uffff]} $part ch]} { + if {[regexp {[^-A-Za-z0-9\xA1-\uFFFF]} $part ch]} { scan $ch %c c if {$ch < "!" || $ch > "~"} { set ch [format "\\u%04x" $c] } throw [list IDNA INVALID_NAME_CHARACTER $ch] \ @@ -49,11 +49,11 @@ return [join $parts .] } proc IDNAdecode hostname { set parts {} # Split term from RFC 3490, Sec 3.1 - foreach part [split $hostname "\u002E\u3002\uFF0E\uFF61"] { + foreach part [split $hostname "\x2E\u3002\uFF0E\uFF61"] { if {[string match -nocase "xn--*" $part]} { set part [punydecode [string range $part 4 end]] } lappend parts $part } @@ -114,11 +114,11 @@ set delta 0 set bias $initial_bias # Handle the basic code points: foreach ch $string { - if {$ch < "\u0080"} { + if {$ch < "\x80"} { if {$case eq ""} { append output $ch } elseif {[string is true $case]} { append output [string toupper $ch] } elseif {[string is false $case]} { ADDED library/cookiejar/public_suffix_list.dat.gz Index: library/cookiejar/public_suffix_list.dat.gz ================================================================== --- /dev/null +++ library/cookiejar/public_suffix_list.dat.gz cannot compute difference between binary files Index: library/dde/pkgIndex.tcl ================================================================== --- library/dde/pkgIndex.tcl +++ library/dde/pkgIndex.tcl @@ -1,3 +1,12 @@ -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] +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] +} Index: library/encoding/ascii.enc ================================================================== --- library/encoding/ascii.enc +++ library/encoding/ascii.enc @@ -7,11 +7,11 @@ 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F -0070007100720073007400750076007700780079007A007B007C007D007E0000 +0070007100720073007400750076007700780079007A007B007C007D007E007F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 Index: library/encoding/big5.enc ================================================================== --- library/encoding/big5.enc +++ library/encoding/big5.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080008100820083008400850086008700880089008A008B008C008D008E008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 ADDED library/encoding/cns11643.enc Index: library/encoding/cns11643.enc ================================================================== --- /dev/null +++ library/encoding/cns11643.enc @@ -0,0 +1,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 Index: library/encoding/cp1250.enc ================================================================== --- library/encoding/cp1250.enc +++ library/encoding/cp1250.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -20AC0081201A0083201E2026202020210088203001602039015A0164017D0179 -009020182019201C201D202220132014009821220161203A015B0165017E017A +20AC0000201A0000201E2026202020210000203001602039015A0164017D0179 +000020182019201C201D202220132014000021220161203A015B0165017E017A 00A002C702D8014100A4010400A600A700A800A9015E00AB00AC00AD00AE017B 00B000B102DB014200B400B500B600B700B80105015F00BB013D02DD013E017C 015400C100C2010200C40139010600C7010C00C9011800CB011A00CD00CE010E 01100143014700D300D4015000D600D70158016E00DA017000DC00DD016200DF 015500E100E2010300E4013A010700E7010D00E9011900EB011B00ED00EE010F Index: library/encoding/cp1251.enc ================================================================== --- library/encoding/cp1251.enc +++ library/encoding/cp1251.enc @@ -9,11 +9,11 @@ 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 04020403201A0453201E20262020202120AC203004092039040A040C040B040F -045220182019201C201D202220132014009821220459203A045A045C045B045F +045220182019201C201D202220132014000021220459203A045A045C045B045F 00A0040E045E040800A4049000A600A7040100A9040400AB00AC00AD00AE0407 00B000B104060456049100B500B600B704512116045400BB0458040504550457 0410041104120413041404150416041704180419041A041B041C041D041E041F 0420042104220423042404250426042704280429042A042B042C042D042E042F 0430043104320433043404350436043704380439043A043B043C043D043E043F Index: library/encoding/cp1252.enc ================================================================== --- library/encoding/cp1252.enc +++ library/encoding/cp1252.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -20AC0081201A0192201E20262020202102C62030016020390152008D017D008F -009020182019201C201D20222013201402DC21220161203A0153009D017E0178 +20AC0000201A0192201E20262020202102C620300160203901520000017D0000 +000020182019201C201D20222013201402DC21220161203A01530000017E0178 00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF 00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF 00D000D100D200D300D400D500D600D700D800D900DA00DB00DC00DD00DE00DF 00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF Index: library/encoding/cp1253.enc ================================================================== --- library/encoding/cp1253.enc +++ library/encoding/cp1253.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -20AC0081201A0192201E20262020202100882030008A2039008C008D008E008F -009020182019201C201D20222013201400982122009A203A009C009D009E009F +20AC0000201A0192201E20262020202100002030000020390000000000000000 +000020182019201C201D202220132014000021220000203A0000000000000000 00A00385038600A300A400A500A600A700A800A9000000AB00AC00AD00AE2015 00B000B100B200B3038400B500B600B703880389038A00BB038C00BD038E038F 0390039103920393039403950396039703980399039A039B039C039D039E039F 03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF 03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF Index: library/encoding/cp1254.enc ================================================================== --- library/encoding/cp1254.enc +++ library/encoding/cp1254.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -20AC0081201A0192201E20262020202102C62030016020390152008D008E008F -009020182019201C201D20222013201402DC21220161203A0153009D009E0178 +20AC0000201A0192201E20262020202102C62030016020390152000000000000 +000020182019201C201D20222013201402DC21220161203A0153000000000178 00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF 00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF 011E00D100D200D300D400D500D600D700D800D900DA00DB00DC0130015E00DF 00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF Index: library/encoding/cp1255.enc ================================================================== --- library/encoding/cp1255.enc +++ library/encoding/cp1255.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -20AC0081201A0192201E20262020202102C62030008A2039008C008D008E008F -009020182019201C201D20222013201402DC2122009A203A009C009D009E009F +20AC0000201A0192201E20262020202102C62030000020390000000000000000 +000020182019201C201D20222013201402DC21220000203A0000000000000000 00A000A100A200A320AA00A500A600A700A800A900D700AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900F700BB00BC00BD00BE00BF 05B005B105B205B305B405B505B605B705B805B9000005BB05BC05BD05BE05BF 05C005C105C205C305F005F105F205F305F40000000000000000000000000000 05D005D105D205D305D405D505D605D705D805D905DA05DB05DC05DD05DE05DF Index: library/encoding/cp1257.enc ================================================================== --- library/encoding/cp1257.enc +++ library/encoding/cp1257.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -20AC0081201A0083201E20262020202100882030008A2039008C00A802C700B8 -009020182019201C201D20222013201400982122009A203A009C00AF02DB009F +20AC0000201A0000201E2026202020210000203000002039000000A802C700B8 +000020182019201C201D202220132014000021220000203A000000AF02DB0000 00A0000000A200A300A4000000A600A700D800A9015600AB00AC00AD00AE00C6 00B000B100B200B300B400B500B600B700F800B9015700BB00BC00BD00BE00E6 0104012E0100010600C400C501180112010C00C90179011601220136012A013B 01600143014500D3014C00D500D600D701720141015A016A00DC017B017D00DF 0105012F0101010700E400E501190113010D00E9017A011701230137012B013C Index: library/encoding/cp1258.enc ================================================================== --- library/encoding/cp1258.enc +++ library/encoding/cp1258.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -20AC0081201A0192201E20262020202102C62030008A20390152008D008E008F -009020182019201C201D20222013201402DC2122009A203A0153009D009E0178 +20AC0000201A0192201E20262020202102C62030000020390152000000000000 +000020182019201C201D20222013201402DC21220000203A0153000000000178 00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF 00C000C100C2010200C400C500C600C700C800C900CA00CB030000CD00CE00CF 011000D1030900D300D401A000D600D700D800D900DA00DB00DC01AF030300DF 00E000E100E2010300E400E500E600E700E800E900EA00EB030100ED00EE00EF Index: library/encoding/cp864.enc ================================================================== --- library/encoding/cp864.enc +++ library/encoding/cp864.enc @@ -9,11 +9,11 @@ 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00B000B72219221A259225002502253C2524252C251C25342510250C25142518 -03B2221E03C600B100BD00BC224800AB00BBFEF7FEF8009B009CFEFBFEFC009F +03B2221E03C600B100BD00BC224800AB00BBFEF7FEF800000000FEFBFEFC0000 00A000ADFE8200A300A4FE8400000000FE8EFE8FFE95FE99060CFE9DFEA1FEA5 0660066106620663066406650666066706680669FED1061BFEB1FEB5FEB9061F 00A2FE80FE81FE83FE85FECAFE8BFE8DFE91FE93FE97FE9BFE9FFEA3FEA7FEA9 FEABFEADFEAFFEB3FEB7FEBBFEBFFEC1FEC5FECBFECF00A600AC00F700D7FEC9 0640FED3FED7FEDBFEDFFEE3FEE7FEEBFEEDFEEFFEF3FEBDFECCFECEFECDFEE1 Index: library/encoding/cp869.enc ================================================================== --- library/encoding/cp869.enc +++ library/encoding/cp869.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080008100820083008400850386008700B700AC00A620182019038820150389 -038A03AA038C00930094038E03AB00A9038F00B200B303AC00A303AD03AE03AF +0000000000000000000000000386000000B700AC00A620182019038820150389 +038A03AA038C00000000038E03AB00A9038F00B200B303AC00A303AD03AE03AF 03CA039003CC03CD039103920393039403950396039700BD0398039900AB00BB 25912592259325022524039A039B039C039D256325512557255D039E039F2510 25142534252C251C2500253C03A003A1255A25542569256625602550256C03A3 03A403A503A603A703A803A903B103B203B32518250C2588258403B403B52580 03B603B703B803B903BA03BB03BC03BD03BE03BF03C003C103C303C203C40384 Index: library/encoding/cp874.enc ================================================================== --- library/encoding/cp874.enc +++ library/encoding/cp874.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -20AC008100820083008420260086008700880089008A008B008C008D008E008F -009020182019201C201D20222013201400980099009A009B009C009D009E009F +20AC000000000000000020260000000000000000000000000000000000000000 +000020182019201C201D20222013201400000000000000000000000000000000 00A00E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F 0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F 0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F 0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F 0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F Index: library/encoding/cp932.enc ================================================================== --- library/encoding/cp932.enc +++ library/encoding/cp932.enc @@ -8,11 +8,11 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080000000000000000000850086000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F Index: library/encoding/cp949.enc ================================================================== --- library/encoding/cp949.enc +++ library/encoding/cp949.enc @@ -8,11 +8,11 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 Index: library/encoding/cp950.enc ================================================================== --- library/encoding/cp950.enc +++ library/encoding/cp950.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080008100820083008400850086008700880089008A008B008C008D008E008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 Index: library/encoding/dingbats.enc ================================================================== --- library/encoding/dingbats.enc +++ library/encoding/dingbats.enc @@ -8,12 +8,12 @@ 2710271127122713271427152716271727182719271A271B271C271D271E271F 2720272127222723272427252726272726052729272A272B272C272D272E272F 2730273127322733273427352736273727382739273A273B273C273D273E273F 2740274127422743274427452746274727482749274A274B25CF274D25A0274F 27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F -0080008100820083008400850086008700880089008A008B008C008D008E008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000276127622763276427652766276726632666266526602460246124622463 2464246524662467246824692776277727782779277A277B277C277D277E277F 2780278127822783278427852786278727882789278A278B278C278D278E278F 2790279127922793279421922194219527982799279A279B279C279D279E279F 27A027A127A227A327A427A527A627A727A827A927AA27AB27AC27AD27AE27AF Index: library/encoding/ebcdic.enc ================================================================== --- library/encoding/ebcdic.enc +++ library/encoding/ebcdic.enc @@ -1,5 +1,6 @@ +# Encoding file: ebcdic, single-byte S 006F 0 1 00 0000000100020003008500090086007F0087008D008E000B000C000D000E000F 0010001100120013008F000A0008009700180019009C009D001C001D001E001F Index: library/encoding/euc-cn.enc ================================================================== --- library/encoding/euc-cn.enc +++ library/encoding/euc-cn.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080008100820083008400850086008700880089008A008B008C008D008E008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 Index: library/encoding/euc-jp.enc ================================================================== --- library/encoding/euc-jp.enc +++ library/encoding/euc-jp.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080008100820083008400850086008700880089008A008B008C008D0000008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 Index: library/encoding/euc-kr.enc ================================================================== --- library/encoding/euc-kr.enc +++ library/encoding/euc-kr.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080008100820083008400850086008700880089008A008B008C008D008E008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 Index: library/encoding/gb1988.enc ================================================================== --- library/encoding/gb1988.enc +++ library/encoding/gb1988.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D203E007F -0080008100820083008400850086008700880089008A008B008C008D008E008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F 0000000000000000000000000000000000000000000000000000000000000000 ADDED library/encoding/iso8859-11.enc Index: library/encoding/iso8859-11.enc ================================================================== --- /dev/null +++ library/encoding/iso8859-11.enc @@ -0,0 +1,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 Index: library/encoding/iso8859-7.enc ================================================================== --- library/encoding/iso8859-7.enc +++ library/encoding/iso8859-7.enc @@ -10,11 +10,11 @@ 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F -00A02018201900A30000000000A600A700A800A9000000AB00AC00AD00002015 +00A02018201900A320AC20AF00A600A700A800A9037A00AB00AC00AD00002015 00B000B100B200B303840385038600B703880389038A00BB038C00BD038E038F 0390039103920393039403950396039703980399039A039B039C039D039E039F 03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF 03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000 Index: library/encoding/jis0201.enc ================================================================== --- library/encoding/jis0201.enc +++ library/encoding/jis0201.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D203E007F -0080008100820083008400850086008700880089008A008B008C008D008E008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F 0000000000000000000000000000000000000000000000000000000000000000 Index: library/encoding/macDingbats.enc ================================================================== --- library/encoding/macDingbats.enc +++ library/encoding/macDingbats.enc @@ -8,12 +8,12 @@ 2710271127122713271427152716271727182719271A271B271C271D271E271F 2720272127222723272427252726272726052729272A272B272C272D272E272F 2730273127322733273427352736273727382739273A273B273C273D273E273F 2740274127422743274427452746274727482749274A274B25CF274D25A0274F 27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F -F8D7F8D8F8D9F8DAF8DBF8DCF8DDF8DEF8DFF8E0F8E1F8E2F8E3F8E4008E008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +F8D7F8D8F8D9F8DAF8DBF8DCF8DDF8DEF8DFF8E0F8E1F8E2F8E3F8E400000000 +0000000000000000000000000000000000000000000000000000000000000000 0000276127622763276427652766276726632666266526602460246124622463 2464246524662467246824692776277727782779277A277B277C277D277E277F 2780278127822783278427852786278727882789278A278B278C278D278E278F 2790279127922793279421922194219527982799279A279B279C279D279E279F 27A027A127A227A327A427A527A627A727A827A927AA27AB27AC27AD27AE27AF Index: library/encoding/macJapan.enc ================================================================== --- library/encoding/macJapan.enc +++ library/encoding/macJapan.enc @@ -8,11 +8,11 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00A0FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F Index: library/encoding/shiftjis.enc ================================================================== --- library/encoding/shiftjis.enc +++ library/encoding/shiftjis.enc @@ -8,11 +8,11 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F -0080000000000000000000850086008700000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F Index: library/encoding/symbol.enc ================================================================== --- library/encoding/symbol.enc +++ library/encoding/symbol.enc @@ -8,12 +8,12 @@ 0030003100320033003400350036003700380039003A003B003C003D003E003F 22450391039203A70394039503A603930397039903D1039A039B039C039D039F 03A0039803A103A303A403A503C203A9039E03A80396005B2234005D22A5005F F8E503B103B203C703B403B503C603B303B703B903D503BA03BB03BC03BD03BF 03C003B803C103C303C403C503D603C903BE03C803B6007B007C007D223C007F -0080008100820083008400850086008700880089008A008B008C008D008E008F -0090009100920093009400950096009700980099009A009B009C009D009E009F +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 000003D2203222642044221E0192266326662665266021942190219121922193 00B000B12033226500D7221D2202202200F72260226122482026F8E6F8E721B5 21352111211C21182297229522052229222A2283228722842282228622082209 2220220700AE00A92122220F221A22C500AC2227222821D421D021D121D221D3 22C42329F8E8F8E9F8EA2211F8EBF8ECF8EDF8EEF8EFF8F0F8F1F8F2F8F3F8F4 Index: library/encoding/tis-620.enc ================================================================== --- library/encoding/tis-620.enc +++ library/encoding/tis-620.enc @@ -7,11 +7,11 @@ 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F -0070007100720073007400750076007700780079007A007B007C007D007E0000 +0070007100720073007400750076007700780079007A007B007C007D007E007F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F 0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F 0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F Index: library/history.tcl ================================================================== --- library/history.tcl +++ library/history.tcl @@ -1,10 +1,10 @@ # history.tcl -- # # Implementation of the history command. # -# Copyright (c) 1997 Sun Microsystems, Inc. +# Copyright © 1997 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # @@ -266,11 +266,11 @@ } if {$i <= $history(oldest)} { return -code error "event \"$event\" is too far in the past" } if {$i > $history(nextid)} { - return -code error "event \"$event\" hasn't occured yet" + return -code error "event \"$event\" hasn't occurred yet" } return $i } # tcl::HistEvent -- Index: library/http/http.tcl ================================================================== --- library/http/http.tcl +++ library/http/http.tcl @@ -9,11 +9,11 @@ # this file, and for a DISCLAIMER OF ALL WARRANTIES. package require Tcl 8.6- # Keep this in sync with pkgIndex.tcl and with the install directories in # Makefiles -package provide http 2.10.0a1 +package provide http 2.10b1 namespace eval http { # Allow resourcing to not clobber existing data variable http @@ -24,11 +24,14 @@ -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 @@ -68,12 +71,15 @@ 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) @@ -90,25 +96,32 @@ array unset socketMapping array unset socketRdState array unset socketWrState array unset socketRdQueue array unset socketWrQueue + array unset socketPhQueue array unset socketClosing array unset socketPlayCmd + array unset socketCoEvent + array unset socketProxyId array set socketMapping {} array set socketRdState {} array set socketWrState {} array set socketRdQueue {} array set socketWrQueue {} + array set socketPhQueue {} array set socketClosing {} array set socketPlayCmd {} + array set socketCoEvent {} + array set socketProxyId {} + return } init variable urlTypes if {![info exists urlTypes]} { - set urlTypes(http) [list 80 ::socket] + set urlTypes(http) [list 80 ::http::socket] } variable encodings [string tolower [encoding names]] # This can be changed, but iso8859-1 is the RFC standard. variable defaultCharset @@ -138,17 +151,122 @@ \s* ; \s* # LITERAL: semicolon ([^\u0000]+) # Match the options )? } - namespace export geturl config reset wait formatQuery quoteString + 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 - # - 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. + 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. @@ -221,19 +339,53 @@ 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 # @@ -252,37 +404,97 @@ variable socketMapping variable socketRdState variable socketWrState variable socketRdQueue variable socketWrQueue + variable socketPhQueue variable socketClosing variable socketPlayCmd + variable socketCoEvent + variable socketProxyId variable $token upvar 0 $token state global errorInfo errorCode set closeQueue 0 if {$errormsg ne ""} { set state(error) [list $errormsg $errorInfo $errorCode] set state(status) "error" } - if {[info commands ${token}EventCoroutine] ne {}} { - rename ${token}EventCoroutine {} + if {[info commands ${token}--EventCoroutine] ne {}} { + rename ${token}--EventCoroutine {} } + if {[info commands ${token}--SocketCoroutine] ne {}} { + rename ${token}--SocketCoroutine {} + } + if {[info exists state(socketcoro)]} { + Log $token Cancel socket after-idle event (Finish) + after cancel $state(socketcoro) + unset state(socketcoro) + } + + # Is this an upgrade request/response? + set upgradeResponse \ + [expr { [info exists state(upgradeRequest)] + && $state(upgradeRequest) + && [info exists state(http)] + && ([ncode $token] eq {101}) + && [info exists state(connection)] + && ("upgrade" in $state(connection)) + && [info exists state(upgrade)] + && ("" ne $state(upgrade)) + }] + if { ($state(status) eq "timeout") || ($state(status) eq "error") || ($state(status) eq "eof") - || ([info exists state(-keepalive)] && !$state(-keepalive)) - || ([info exists state(connection)] && ($state(connection) eq "close")) + } { + 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) - set sock $state(sock) - CloseSocket $state(sock) $token + 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)] && ($state(connection) ne "close")) + && ([info exists state(connection)] && ("close" ni $state(connection))) } { KeepSocket $token } if {[info exists state(after)]} { after cancel $state(after) @@ -289,11 +501,13 @@ 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 ""} { + if { [catch {namespace eval :: $state(-command) $token} err] + && ($errormsg eq "") + } { set state(error) [list $err $errorInfo $errorCode] set state(status) error } } @@ -300,20 +514,22 @@ if { $closeQueue && [info exists socketMapping($connId)] && ($socketMapping($connId) eq $sock) } { http::CloseQueuedQueries $connId $token + # This calls Unset. Other cases do not need the call. } + return } # http::KeepSocket - # # Keep a socket in the persistent sockets table and connect it to its next # queued task if possible. Otherwise leave it idle and ready for its next # use. # -# If $socketClosing(*), then ($state(connection) eq "close") and therefore +# If $socketClosing(*), then ("close" in $state(connection)) and therefore # this command will not be called by Finish. # # Arguments: # token Connection token. @@ -322,12 +538,15 @@ 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] @@ -358,13 +577,10 @@ } { # 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 @@ -399,12 +615,11 @@ # - The write state is not Wready and therefore appears to be busy, # but because it is "pending" we know that it is reserved for the # first item in the write queue, a non-pipelined request that is # waiting for the read queue to empty. That has now happened: so # give that request read and write access. - variable $token3 - set conn [set ${token3}(tmpConnArgs)] + set conn [set ${token3}(connArgs)] #Log nonpipeline, GRANT r/w access to $token3 in KeepSocket set socketRdState($connId) $token3 set socketWrState($connId) $token3 set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end] # Connect does its own fconfigure. @@ -444,12 +659,11 @@ # write state (tested here) is Wready - there is no "pending" # request. # Code: # - The code is the same as the code below for the nonpipelined # case with a queued request. - variable $token3 - set conn [set ${token3}(tmpConnArgs)] + set conn [set ${token3}(connArgs)] #Log nonpipeline, GRANT r/w access to $token3 in KeepSocket set socketRdState($connId) $token3 set socketWrState($connId) $token3 set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end] # Connect does its own fconfigure. @@ -458,20 +672,19 @@ } elseif { (!$state(-pipeline)) && [info exists socketWrQueue($connId)] && [llength $socketWrQueue($connId)] - && ($state(connection) ne "close") + && ("close" ni $state(connection)) } { # If not pipelined, (socketRdState eq Rready) tells us that we are # ready for the next write - there is no need to check # socketWrState. Write the next request, if one is waiting. # If the next request is pipelined, it receives premature read # access to the socket. This is not a problem. set token3 [lindex $socketWrQueue($connId) 0] - variable $token3 - set conn [set ${token3}(tmpConnArgs)] + set conn [set ${token3}(connArgs)] #Log nonpipeline, GRANT r/w access to $token3 in KeepSocket set socketRdState($connId) $token3 set socketWrState($connId) $token3 set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end] # Connect does its own fconfigure. @@ -486,10 +699,11 @@ } 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. @@ -511,10 +725,11 @@ # 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 @@ -526,12 +741,15 @@ 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 {} @@ -554,22 +772,26 @@ && ($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 @@ -582,13 +804,17 @@ 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 } @@ -608,10 +834,11 @@ # 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 {} @@ -619,13 +846,15 @@ Unset $connId if {$unfinished ne {}} { Log ^R$tk Any unfinished transactions (excluding $token) failed \ - - token $token + - token $token - unfinished $unfinished {*}$unfinished + # Calls ReplayIfClose. } + return } # http::Unset # # The trace on "unset socketRdState(*)" will call CancelReadPipeline @@ -637,20 +866,25 @@ 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. @@ -671,11 +905,13 @@ 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. @@ -687,19 +923,106 @@ # 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::socketForTls. + # - 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::socketForTls into its own "new" + # command, if it wishes to do so. + # - Commands that open a socket: + # - ::socket - basic + # - ::http::socket - can use a thread to avoid blockage by slow DNS + # lookup. See http::config option -threadlevel. + # - ::http::socketForTls - as ::http::socket, but can also open a socket + # for HTTPS/TLS through a proxy. + + if {[info exists ::tls::socketCmd] && ($::tls::socketCmd eq {::socket})} { + set ::tls::socketCmd ::http::socketForTls + } + + 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 @@ -719,55 +1042,70 @@ -headers {} -timeout 0 -type application/x-www-form-urlencoded -queryprogress {} -protocol 1.1 + -guesstype 0 binary 0 state created meta {} method {} coding {} currentsize 0 totalsize 0 querylength 0 queryoffset 0 - type text/html + type application/octet-stream body {} status "" http "" + httpResponse {} + responseCode {} + reasonPhrase {} connection keep-alive + tid {} + requestHeaders {} + requestLine {} + transfer {} + proxyUsed none } set state(-keepalive) $defaultKeepalive set state(-strict) $strict # These flags have their types verified [Bug 811170] array set type { -binary boolean -blocksize integer + -guesstype boolean -queryblocksize integer -strict boolean -timeout integer -validate boolean - -headers dict + -headers list } set state(charset) $defaultCharset set options { - -binary -blocksize -channel -command -handler -headers -keepalive + -binary -blocksize -channel -command -guesstype -handler -headers -keepalive -method -myaddr -progress -protocol -query -queryblocksize -querychannel -queryprogress -strict -timeout -type -validate } set usage [join [lsort $options] ", "] set options [string map {- ""} $options] set pat ^-(?:[join $options |])$ foreach {flag value} $args { if {[regexp -- $pat $flag]} { # Validate numbers - if {($flag eq "-headers") ? [catch {dict size $value}] : - ([info exists type($flag)] && ![string is $type($flag) -strict $value]) + if { [info exists type($flag)] + && (![string is $type($flag) -strict $value]) } { unset $token return -code error \ "Bad value for $flag ($value), must be $type($flag)" + } + if {($flag eq "-headers") && ([llength $value] % 2 != 0)} { + unset $token + return -code error "Bad value for $flag ($value), number\ + of list elements must be even" } set state($flag) $value } else { unset $token return -code error "Unknown option $flag, can be: $usage" @@ -815,10 +1153,13 @@ # "/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). @@ -927,10 +1268,13 @@ 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 ""} { @@ -940,31 +1284,30 @@ append url $host if {$port != $defport} { append url : $port } append url $srvurl - # Don't append the fragment! + # Don't append the fragment! RFC 7230 Sec 5.1 set state(url) $url - set sockopts [list -async] - - # If we are using the proxy, we must pass in the full URL that includes - # the server name. - - if {[info exists phost] && ($phost ne "")} { - set srvurl $url - set targetAddr [list $phost $pport] - } else { - set targetAddr [list $host $port] - } # Proxy connections aren't shared among different hosts. set state(socketinfo) $host:$port # Save the accept types at this point to prevent a race condition. [Bug # c11a51c482] set state(accept-types) $http(-accept) + # Check whether this is an Upgrade request. + set connectionValues [SplitCommaSeparatedFieldValue \ + [GetFieldValue $state(-headers) Connection]] + set connectionValues [string tolower $connectionValues] + set upgradeValues [SplitCommaSeparatedFieldValue \ + [GetFieldValue $state(-headers) Upgrade]] + set state(upgradeRequest) [expr { "upgrade" in $connectionValues + && [llength $upgradeValues] >= 1}] + set state(connectionValues) $connectionValues + if {$isQuery || $isQueryChannel} { # It's a POST. # A client wishing to send a non-idempotent request SHOULD wait to send # that request until it has received the response status for the # previous request. @@ -976,12 +1319,17 @@ # Allow -keepalive but do not -pipeline - wait for the previous # transaction to finish. # There is a small risk of a race against server timeout. set state(-pipeline) 0 } + } elseif {$state(upgradeRequest)} { + # It's an upgrade request. Method must be GET (untested). + # Force -keepalive to 0 so the connection is not made over a persistent + # socket, i.e. one used for multiple HTTP requests. + set state(-keepalive) 0 } else { - # It's a GET or HEAD. + # It's a non-upgrade GET or HEAD. set state(-pipeline) $http(-pipeline) } # We cannot handle chunked encodings with -handler, so force HTTP/1.0 # until we can manage this. @@ -993,28 +1341,61 @@ 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::socketForTls 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 "") && (![string match -nocase *tls* $defcmd])} { + 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) + } + + set state(connArgs) [list $proto $phost $srvurl] + set state(openCmd) [list {*}$defcmd {*}$sockopts -type $token {*}$targetAddr] + # See if we are supposed to use a previously opened channel. # - In principle, ANY call to http::geturl could use a previously opened # channel if it is available - the "Connection: keep-alive" header is a # request to leave the channel open AFTER completion of this call. # - In fact, we try to use an existing channel only if -keepalive 1 -- this # means that at most one channel is left open for each value of # $state(socketinfo). This property simplifies the mapping of open # channels. set reusing 0 - set alreadyQueued 0 + set state(alreadyQueued) 0 + set state(ReusingPlaceholder) 0 if {$state(-keepalive)} { variable socketMapping variable socketRdState variable socketWrState variable socketRdQueue variable socketWrQueue + variable socketPhQueue variable socketClosing variable socketPlayCmd + variable socketCoEvent + variable socketProxyId if {[info exists socketMapping($state(socketinfo))]} { # - If the connection is idle, it has a "fileevent readable" binding # to http::CheckEof, in case the server times out and half-closes # the socket (http::CheckEof closes the other half). @@ -1033,18 +1414,25 @@ # 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 state(proxyUsed) $socketProxyId($state(socketinfo)) + Log "reusing closing socket $sock for $state(socketinfo) - token $token" - set alreadyQueued 1 + set state(alreadyQueued) 1 lassign $socketPlayCmd($state(socketinfo)) com0 com1 com2 com3 lappend com3 $token set socketPlayCmd($state(socketinfo)) [list $com0 $com1 $com2 $com3] lappend socketWrQueue($state(socketinfo)) $token - } elseif {[catch {fconfigure $socketMapping($state(socketinfo))}]} { + ##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" @@ -1054,163 +1442,576 @@ # This will call CancelReadPipeline, CancelWritePipeline, and # cancel any queued requests, responses. Unset $state(socketinfo) } else { # Use the persistent socket. - # The socket may not be ready to write: an earlier request might - # still be still writing (in the pipelined case) or - # writing/reading (in the nonpipeline case). This possibility - # is handled by socketWrQueue later in this command. + # - The socket may not be ready to write: an earlier request might + # still be still writing (in the pipelined case) or + # writing/reading (in the nonpipeline case). This possibility + # is handled by socketWrQueue later in this command. + # - The socket may not yet exist, and be defined with a placeholder. set reusing 1 set sock $socketMapping($state(socketinfo)) - Log "reusing socket $sock for $state(socketinfo) - token $token" - + 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 } } - 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 + 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 {![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 { + 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 tcl8 + } ##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)) {} + } + + 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 {![info exists socketWrState($state(socketinfo))]} { - set socketWrState($state(socketinfo)) {} + } + if {[dict get $DoLater -tracewrite]} { 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} { + } + } + + # 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. @@ -1239,57 +2040,82 @@ # 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. + 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. - 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 + + 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 @@ -1309,12 +2135,15 @@ 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] @@ -1325,12 +2154,11 @@ # 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] + 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. @@ -1337,10 +2165,13 @@ # 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 tcl8 + } # The following is disallowed in safe interpreters, but the socket is # already in non-blocking mode in that case. catch {fconfigure $sock -blocking off} @@ -1370,49 +2201,63 @@ 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]} { + 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] - set hostHdr [dict get $state(-headers) Host] - regexp {^[^:]+} $hostHdr state(host) - puts $sock "Host: $hostHdr" + regexp {^[^:]+} $hostValue state(host) + SendHeader $token Host $hostValue } elseif {$port == $defport} { # Don't add port in this case, to handle broken servers. [Bug # #504508] set state(host) $host - puts $sock "Host: $host" + SendHeader $token Host $host } else { set state(host) $host - puts $sock "Host: $host:$port" + SendHeader $token Host "$host:$port" } - puts $sock "User-Agent: $http(-useragent)" + SendHeader $token User-Agent $http(-useragent) if {($state(-protocol) > 1.0) && $state(-keepalive)} { # Send this header, because a 1.1 server is not compelled to treat # this as the default. - puts $sock "Connection: keep-alive" - } - if {($state(-protocol) > 1.0) && !$state(-keepalive)} { - puts $sock "Connection: close" ;# RFC2616 sec 8.1.2.1 - } - if {($state(-protocol) < 1.1)} { + 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". - puts $sock "Connection: close" + set ConnVal close } + # Proxy authorisation (cf. mod by Anders Ramdahl to autoproxy by + # Pat Thoyts). + if {($http(-proxyauth) ne {}) && ($state(proxyUsed) eq {HttpProxy})} { + SendHeader $token Proxy-Authorization $http(-proxyauth) + } # RFC7230 A.1 - "clients are encouraged not to send the # Proxy-Connection header field in any requests" set accept_encoding_seen 0 set content_type_seen 0 - dict for {key value} $state(-headers) { + 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 } @@ -1427,24 +2272,53 @@ } if {[string equal -nocase $key "content-length"]} { set contDone 1 set state(querylength) $value } + if { [string equal -nocase $key "connection"] + && [info exists state(bypass)] + } { + # Value supplied in -headers overrides $ConnVal. + set connection_seen 1 + } elseif {[string equal -nocase $key "connection"]} { + # Remove "close" or "keep-alive" and use our own value. + # In an upgrade request, the upgrade is not guaranteed. + # Value "close" or "keep-alive" tells the server what to do + # if it refuses the upgrade. We send a single "Connection" + # header because some websocket servers, e.g. civetweb, reject + # multiple headers. Bug [d01de3281f] of tcllib/websocket. + set connection_seen 1 + set listVal $state(connectionValues) + if {[set pos [lsearch $listVal close]] != -1} { + set listVal [lreplace $listVal $pos $pos] + } + if {[set pos [lsearch $listVal keep-alive]] != -1} { + set listVal [lreplace $listVal $pos $pos] + } + lappend listVal $ConnVal + set value [join $listVal {, }] + } if {[string length $key]} { - puts $sock "$key: $value" + SendHeader $token $key $value } } # Allow overriding the Accept header on a per-connection basis. Useful # for working with REST services. [Bug c11a51c482] if {!$accept_types_seen} { - puts $sock "Accept: $state(accept-types)" + SendHeader $token Accept $state(accept-types) } if { (!$accept_encoding_seen) && (![info exists state(-handler)]) && $http(-zip) } { - puts $sock "Accept-Encoding: gzip,deflate,compress" + 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 @@ -1465,11 +2339,11 @@ getCookies $proto $host $state(path)] { append cookies $separator $key = $value set separator "; " } if {$cookies ne ""} { - puts $sock "Cookie: $cookies" + SendHeader $token Cookie $cookies } } # Flush the request header and set up the fileevent that will either # push the POST data or read the response. @@ -1489,14 +2363,14 @@ # response. if {$isQuery || $isQueryChannel} { # POST method. if {!$content_type_seen} { - puts $sock "Content-Type: $state(-type)" + SendHeader $token Content-Type $state(-type) } if {!$contDone} { - puts $sock "Content-Length: $state(querylength)" + SendHeader $token Content-Length $state(querylength) } puts $sock "" flush $sock # Flush flushes the error in the https case with a bad handshake: # else the socket never becomes writable again, and hangs until @@ -1546,11 +2420,12 @@ # This is NOT a persistent socket that has been closed since its # last use. # If any other requests are in flight or pipelined/queued, they will # be discarded. } elseif {$state(status) eq ""} { - # ...https handshake errors come here. + # https handshake errors come here, for + # Tcl 8.7 without http::SecureProxyConnect, and for Tcl 8.6. set msg [registerError $sock] registerError $sock {} if {$msg eq {}} { set msg {failed to use socket} } @@ -1557,10 +2432,11 @@ Finish $token $msg } elseif {$state(status) ne "error"} { Finish $token $err } } + return } # http::registerError # # Called (for example when processing TclTLS activity) to register @@ -1602,12 +2478,15 @@ 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) @@ -1662,10 +2541,11 @@ # 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. @@ -1678,17 +2558,20 @@ #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 tcl8 + } Log ^D$tk begin receiving response - token $token - coroutine ${token}EventCoroutine http::Event $sock $token + coroutine ${token}--EventCoroutine http::Event $sock $token if {[info exists state(-handler)] || [info exists state(-progress)]} { fileevent $sock readable [list http::EventGateway $sock $token] } else { - fileevent $sock readable ${token}EventCoroutine + fileevent $sock readable ${token}--EventCoroutine } return } @@ -1708,18 +2591,18 @@ 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 {}} { + 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. + # http::MakeTransformationChunked. # # Catch in case the coroutine has closed the socket. catch {fileevent $sock readable [list http::EventGateway $sock $token]} } @@ -1777,11 +2660,11 @@ ] ) } { # - The usual case for a pipelined connection, ready for a new request. #Log pipelined, GRANT write access to $token2 in NextPipelinedWrite - set conn [set ${token2}(tmpConnArgs)] + set conn [set ${token2}(connArgs)] set socketWrState($connId) $token2 set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end] # Connect does its own fconfigure. fileevent $state(sock) writable [list http::Connect $token2 {*}$conn] #Log ---- $connId << conn to $token2 for HTTP request (b) @@ -1802,13 +2685,11 @@ && ($socketRdState($connId) eq "Rready") } { # The case in which the next request will be non-pipelined, and the read # and write queues is ready: which is the condition for a non-pipelined # write. - variable $token3 - upvar 0 $token3 state3 - set conn [set ${token3}(tmpConnArgs)] + set conn [set ${token3}(connArgs)] #Log nonpipeline, GRANT r/w access to $token3 in NextPipelinedWrite set socketRdState($connId) $token3 set socketWrState($connId) $token3 set socketWrQueue($connId) [lrange $socketWrQueue($connId) 1 end] # Connect does its own fconfigure. @@ -1836,10 +2717,11 @@ # 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. @@ -1868,10 +2750,11 @@ set ${token}(status) eof Finish $token ;#$msg } set socketRdQueue($connId) {} } + return } # http::CancelWritePipeline # # Cancel queued events on a closing "Keep-Alive" socket. @@ -1901,10 +2784,11 @@ 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, @@ -1923,110 +2807,114 @@ # token Connection token. # # Side Effects: # Use the same token, but try to open a new socket. -proc http::ReplayIfDead {tokenArg doing} { +proc http::ReplayIfDead {token doing} { variable socketMapping variable socketRdState variable socketWrState variable socketRdQueue variable socketWrQueue + variable socketPhQueue variable socketClosing variable socketPlayCmd + variable socketCoEvent + variable socketProxyId - variable $tokenArg - upvar 0 $tokenArg stateArg + variable $token + upvar 0 $token state - Log running http::ReplayIfDead for $tokenArg $doing + Log running http::ReplayIfDead for $token $doing # 1. Merge the tokens for transactions in flight, the read (response) queue, # and the write (request) queue. set InFlightR {} set InFlightW {} # Obtain the tokens for transactions in flight. - if {$stateArg(-pipeline)} { + if {$state(-pipeline)} { # Two transactions may be in flight. The "read" transaction was first. # It is unlikely that the server would close the socket if a response # was pending; however, an earlier request (as well as the present # request) may have been sent and ignored if the socket was half-closed # by the server. - if { [info exists socketRdState($stateArg(socketinfo))] - && ($socketRdState($stateArg(socketinfo)) ne "Rready") + if { [info exists socketRdState($state(socketinfo))] + && ($socketRdState($state(socketinfo)) ne "Rready") } { - lappend InFlightR $socketRdState($stateArg(socketinfo)) + lappend InFlightR $socketRdState($state(socketinfo)) } elseif {($doing eq "read")} { - lappend InFlightR $tokenArg + lappend InFlightR $token } - if { [info exists socketWrState($stateArg(socketinfo))] - && $socketWrState($stateArg(socketinfo)) ni {Wready peNding} + if { [info exists socketWrState($state(socketinfo))] + && $socketWrState($state(socketinfo)) ni {Wready peNding} } { - lappend InFlightW $socketWrState($stateArg(socketinfo)) + lappend InFlightW $socketWrState($state(socketinfo)) } elseif {($doing eq "write")} { - lappend InFlightW $tokenArg + lappend InFlightW $token } - # Report any inconsistency of $tokenArg with socket*state. + # Report any inconsistency of $token with socket*state. if { ($doing eq "read") - && [info exists socketRdState($stateArg(socketinfo))] - && ($tokenArg ne $socketRdState($stateArg(socketinfo))) + && [info exists socketRdState($state(socketinfo))] + && ($token ne $socketRdState($state(socketinfo))) } { - Log WARNING - ReplayIfDead pipelined tokenArg $tokenArg $doing \ - ne socketRdState($stateArg(socketinfo)) \ - $socketRdState($stateArg(socketinfo)) + Log WARNING - ReplayIfDead pipelined token $token $doing \ + ne socketRdState($state(socketinfo)) \ + $socketRdState($state(socketinfo)) } elseif { ($doing eq "write") - && [info exists socketWrState($stateArg(socketinfo))] - && ($tokenArg ne $socketWrState($stateArg(socketinfo))) + && [info exists socketWrState($state(socketinfo))] + && ($token ne $socketWrState($state(socketinfo))) } { - Log WARNING - ReplayIfDead pipelined tokenArg $tokenArg $doing \ - ne socketWrState($stateArg(socketinfo)) \ - $socketWrState($stateArg(socketinfo)) + Log WARNING - ReplayIfDead pipelined token $token $doing \ + ne socketWrState($state(socketinfo)) \ + $socketWrState($state(socketinfo)) } } else { # One transaction should be in flight. # socketRdState, socketWrQueue are used. # socketRdQueue should be empty. - # Report any inconsistency of $tokenArg with socket*state. - if {$tokenArg ne $socketRdState($stateArg(socketinfo))} { - Log WARNING - ReplayIfDead nonpipeline tokenArg $tokenArg $doing \ - ne socketRdState($stateArg(socketinfo)) \ - $socketRdState($stateArg(socketinfo)) + # Report any inconsistency of $token with socket*state. + if {$token ne $socketRdState($state(socketinfo))} { + Log WARNING - ReplayIfDead nonpipeline token $token $doing \ + ne socketRdState($state(socketinfo)) \ + $socketRdState($state(socketinfo)) } # Report the inconsistency that socketRdQueue is non-empty. - if { [info exists socketRdQueue($stateArg(socketinfo))] - && ($socketRdQueue($stateArg(socketinfo)) ne {}) + if { [info exists socketRdQueue($state(socketinfo))] + && ($socketRdQueue($state(socketinfo)) ne {}) } { - Log WARNING - ReplayIfDead nonpipeline tokenArg $tokenArg $doing \ - has read queue socketRdQueue($stateArg(socketinfo)) \ - $socketRdQueue($stateArg(socketinfo)) ne {} + Log WARNING - ReplayIfDead nonpipeline token $token $doing \ + has read queue socketRdQueue($state(socketinfo)) \ + $socketRdQueue($state(socketinfo)) ne {} } - lappend InFlightW $socketRdState($stateArg(socketinfo)) - set socketRdQueue($stateArg(socketinfo)) {} + lappend InFlightW $socketRdState($state(socketinfo)) + set socketRdQueue($state(socketinfo)) {} } set newQueue {} lappend newQueue {*}$InFlightR - lappend newQueue {*}$socketRdQueue($stateArg(socketinfo)) + lappend newQueue {*}$socketRdQueue($state(socketinfo)) lappend newQueue {*}$InFlightW - lappend newQueue {*}$socketWrQueue($stateArg(socketinfo)) + lappend newQueue {*}$socketWrQueue($state(socketinfo)) - # 2. Tidy up tokenArg. This is a cut-down form of Finish/CloseSocket. + # 2. Tidy up token. This is a cut-down form of Finish/CloseSocket. # Do not change state(status). - # No need to after cancel stateArg(after) - either this is done in + # No need to after cancel state(after) - either this is done in # ReplayCore/ReInit, or Finish is called. - catch {close $stateArg(sock)} + catch {close $state(sock)} + Unset $state(socketinfo) # 2a. Tidy the tokens in the queues - this is done in ReplayCore/ReInit. # - Transactions, if any, that are awaiting responses cannot be completed. # They are listed for re-sending in newQueue. # - All tokens are preserved for re-use by ReplayCore, and their variables @@ -2034,10 +2922,11 @@ # - 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 @@ -2064,19 +2953,20 @@ # 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 @@ -2116,10 +3006,15 @@ 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) @@ -2155,17 +3050,22 @@ # # 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 } @@ -2181,10 +3081,11 @@ 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) @@ -2193,105 +3094,46 @@ 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. + 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 $token {cannot send this request again} + Finish $tok {cannot send this request again} } } - # 7. Configure the socket for newToken to send a request. - set state(sock) $sock - Log "Using $sock for $state(socketinfo) - token $token" \ - [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) + 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::data {token} { +proc http::responseBody {token} { variable $token upvar 0 $token state return $state(body) } proc http::status {token} { @@ -2300,16 +3142,21 @@ } variable $token upvar 0 $token state return $state(status) } -proc http::code {token} { +proc http::responseLine {token} { variable $token upvar 0 $token state return $state(http) } -proc http::ncode {token} { +proc http::requestLine {token} { + variable $token + upvar 0 $token state + return $state(requestLine) +} +proc http::responseCode {token} { variable $token upvar 0 $token state if {[regexp {[0-9]{3}} $state(http) numeric_code]} { return $numeric_code } else { @@ -2319,22 +3166,154 @@ proc http::size {token} { variable $token upvar 0 $token state return $state(currentsize) } -proc http::meta {token} { +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 - return $state(meta) + set result {} + foreach {key origin name} { + stage STATE state + status STATE status + responseCode STATE responseCode + reasonPhrase STATE reasonPhrase + contentType STATE type + binary STATE binary + redirection RESP location + upgrade STATE upgrade + error ERROR - + postError STATE posterror + method STATE method + charset STATE charset + compression STATE coding + httpRequest STATE -protocol + httpResponse STATE httpResponse + url STATE url + connectionRequest REQ connection + connectionResponse RESP connection + connectionActual STATE connection + transferEncoding STATE transfer + totalPost STATE querylength + currentPost STATE queryoffset + totalSize STATE totalsize + currentSize STATE currentsize + proxyUsed STATE proxyUsed + } { + if {$origin eq {STATE}} { + if {[info exists state($name)]} { + dict set result $key $state($name) + } else { + # Should never come here + dict set result $key {} + } + } elseif {$origin eq {REQ}} { + dict set result $key [requestHeaderValue $token $name] + } elseif {$origin eq {RESP}} { + dict set result $key [responseHeaderValue $token $name] + } elseif {$origin eq {ERROR}} { + # Don't flood the dict with data. The command ::http::error is + # available. + if {[info exists state(error)]} { + set msg [lindex $state(error) 0] + } else { + set msg {} + } + dict set result $key $msg + } else { + # Should never come here + dict set result $key {} + } + } + return $result } proc http::error {token} { variable $token upvar 0 $token state if {[info exists state(error)]} { return $state(error) } - return "" + return +} +proc http::postError {token} { + variable $token + upvar 0 $token state + if {[info exists state(postErrorFull)]} { + return $state(postErrorFull) + } + return } # http::cleanup # # Garbage collect the state associated with a transaction @@ -2341,30 +3320,39 @@ # # Arguments # token The token returned from http::geturl # # Side Effects -# unsets the state array +# Unsets the state array. proc http::cleanup {token} { variable $token upvar 0 $token state - if {[info commands ${token}EventCoroutine] ne {}} { - rename ${token}EventCoroutine {} + if {[info commands ${token}--EventCoroutine] ne {}} { + rename ${token}--EventCoroutine {} + } + if {[info commands ${token}--SocketCoroutine] ne {}} { + rename ${token}--SocketCoroutine {} } if {[info exists state(after)]} { after cancel $state(after) unset state(after) } + if {[info exists state(socketcoro)]} { + Log $token Cancel socket after-idle event (cleanup) + after cancel $state(socketcoro) + unset state(socketcoro) + } if {[info exists state]} { unset state } + return } # http::Connect # -# This callback is made when an asyncronous connection completes. +# This callback is made when an asynchronous connection completes. # # Arguments # token The token returned from http::geturl # # Side Effects @@ -2373,15 +3361,24 @@ 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 "" - } { + + 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. @@ -2393,16 +3390,12 @@ # 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 - } + Finish $token "connect failed: $err" + return } # http::Write # # Write POST query data to the socket @@ -2418,12 +3411,15 @@ 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) @@ -2480,15 +3476,17 @@ incr state(queryoffset) [string length $outStr] if {[eof $state(-querychannel)]} { set done 1 } } - } err]} { + } err opts]} { # Do not call Finish here, but instead let the read half of the socket # process whatever server reply there is to get. - set state(posterror) $err + set info [dict get $opts -errorinfo] + set code [dict get $opts -code] + set state(postErrorFull) [list $err $info $code] set done 1 } if {$done} { catch {flush $sock} @@ -2500,19 +3498,20 @@ } # Callback to the client after we've completely handled everything. if {[string length $state(-queryprogress)]} { - eval $state(-queryprogress) \ + namespace eval :: $state(-queryprogress) \ [list $token $state(querylength) $state(queryoffset)] } + return } # http::Event # # Handle input on the socket. This command is the core of -# the coroutine commands ${token}EventCoroutine that are +# the coroutine commands ${token}--EventCoroutine that are # bound to "fileevent $sock readable" and process input. # # Arguments # sock The socket receiving input. # token The token returned from http::geturl @@ -2525,12 +3524,15 @@ 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 { @@ -2537,19 +3539,22 @@ yield ##Log Event call - token $token if {![info exists state]} { Log "Event $sock with invalid token '$token' - remote close?" - if {![eof $sock]} { + if {!([catch {eof $sock} tmp] || $tmp)} { if {[set d [read $sock]] ne ""} { Log "WARNING: additional data left on closed socket\ - token $token" + } else { } + } else { } Log ^X$tk end of response (token error) - token $token CloseSocket $sock return + } else { } if {$state(state) eq "connecting"} { ##Log - connecting - token $token if { $state(reusing) && $state(-pipeline) @@ -2556,10 +3561,11 @@ && ($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" @@ -2567,42 +3573,51 @@ # The socket was closed at the server end, and closed at # this end by http::CheckEof. if {[TestForReplay $token read $nsl c]} { return + } else { } - # else: # This is NOT a persistent socket that has been closed since # its last use. # If any other requests are in flight or pipelined/queued, # they will be discarded. } else { + # https handshake errors come here, for + # Tcl 8.7 with http::SecureProxyConnect. + set msg [registerError $sock] + registerError $sock {} + if {$msg eq {}} { + set msg $nsl + } Log ^X$tk end of response (error) - token $token - Finish $token $nsl + Finish $token $msg return } } elseif {$nsl >= 0} { ##Log - connecting 1 - token $token set state(state) "header" - } elseif { [eof $sock] + } elseif { ([catch {eof $sock} tmp] || $tmp) && [info exists state(reusing)] && $state(reusing) } { # The socket was closed at the server end, and we didn't notice. # This is the first read - where the closure is usually first # detected. if {[TestForReplay $token read {} d]} { return + } else { } # else: # This is NOT a persistent socket that has been closed since its # last use. # If any other requests are in flight or pipelined/queued, they # will be discarded. + } else { } } elseif {$state(state) eq "header"} { if {[catch {gets $sock line} nhl]} { ##Log header failed - token $token Log ^X$tk end of response (error) - token $token @@ -2617,15 +3632,29 @@ || ([regexp {^\S+\s(\d+)} $state(http) {} x] && $x == 100) } { set state(state) "connecting" continue # This was a "return" in the pre-coroutine code. + } else { + } + + # We have $state(http) so let's split it into its components. + if {[regexp {^HTTP/(\S+) ([0-9]{3}) (.*)$} $state(http) \ + -> httpResponse responseCode reasonPhrase] + } { + set state(httpResponse) $httpResponse + set state(responseCode) $responseCode + set state(reasonPhrase) $reasonPhrase + } else { + set state(httpResponse) $state(http) + set state(responseCode) $state(http) + set state(reasonPhrase) $state(http) } if { ([info exists state(connection)]) && ([info exists socketMapping($state(socketinfo))]) - && ($state(connection) eq "keep-alive") + && ("keep-alive" in $state(connection)) && ($state(-keepalive)) && (!$state(reusing)) && ($state(-pipeline)) } { # Response headers received for first request on a @@ -2632,10 +3661,11 @@ # 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. # @@ -2643,17 +3673,32 @@ # the Connection header, that request becomes the last one for # the connection. if { ([info exists state(connection)]) && ([info exists socketMapping($state(socketinfo))]) - && ($state(connection) eq "close") + && ("close" in $state(connection)) && ($state(-keepalive)) } { # The server warns that it will close the socket after this # response. ##Log WARNING - socket will close after response for $token # Prepare data for a call to ReplayIfClose. + Log $token socket will close after this transaction + # 1. Cancel socket-assignment coro events that have not yet + # launched, and add the tokens to the write queue. + if {[info exists socketCoEvent($state(socketinfo))]} { + foreach {tok can} $socketCoEvent($state(socketinfo)) { + lappend socketWrQueue($state(socketinfo)) $tok + unset -nocomplain ${tok}(socketcoro) + after cancel $can + Log $tok Cancel socket after-idle event (Event) + Log Move $tok from socketCoEvent to socketWrQueue and cancel its after idle coro + } + set socketCoEvent($state(socketinfo)) {} + } else { + } + if { ($socketRdQueue($state(socketinfo)) ne {}) || ($socketWrQueue($state(socketinfo)) ne {}) || ($socketWrState($state(socketinfo)) ni [list Wready peNding $token]) } { @@ -2662,11 +3707,10 @@ 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))] @@ -2677,30 +3721,88 @@ # - Cancel the state(after) timeout events. foreach tokenVal $socketRdQueue($state(socketinfo)) { if {[info exists ${tokenVal}(after)]} { after cancel [set ${tokenVal}(after)] unset ${tokenVal}(after) + } else { } + # Tokens in the read queue have no (socketcoro) to + # cancel. } - } else { set socketPlayCmd($state(socketinfo)) \ {ReplayIfClose Wready {} {}} } - # Do not allow further connections on this socket. + # Do not allow further connections on this socket (but + # geturl can add new requests to the replay). set socketClosing($state(socketinfo)) 1 + } else { } set state(state) body + + # According to + # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection + # any comma-separated "Connection:" list implies keep-alive, but I + # don't see this in the RFC so we'll play safe and + # scan any list for "close". + # Done here to support combining duplicate header field's values. + if { [info exists state(connection)] + && ("close" ni $state(connection)) + && ("keep-alive" ni $state(connection)) + } { + lappend state(connection) "keep-alive" + } else { + } # If doing a HEAD, then we won't get any body if {$state(-validate)} { Log ^F$tk end of response for HEAD request - token $token set state(state) complete Eot $token return + } elseif { + ($state(method) eq {CONNECT}) + && [string is integer -strict $state(responseCode)] + && ($state(responseCode) >= 200) + && ($state(responseCode) < 300) + } { + # A successful CONNECT response has no body. + # (An unsuccessful CONNECT has headers and body.) + # The code below is abstracted from Eot/Finish, but + # keeps the socket open. + catch {fileevent $state(sock) readable {}} + catch {fileevent $state(sock) writable {}} + set state(state) complete + set state(status) ok + if {[info commands ${token}--EventCoroutine] ne {}} { + rename ${token}--EventCoroutine {} + } + if {[info commands ${token}--SocketCoroutine] ne {}} { + rename ${token}--SocketCoroutine {} + } + if {[info exists state(socketcoro)]} { + Log $token Cancel socket after-idle event (Finish) + after cancel $state(socketcoro) + unset state(socketcoro) + } + if {[info exists state(after)]} { + after cancel $state(after) + unset state(after) + } + if { [info exists state(-command)] + && (![info exists state(done-command-cb)]) + } { + set state(done-command-cb) yes + if {[catch {namespace eval :: $state(-command) $token} err]} { + set state(error) [list $err $errorInfo $errorCode] + set state(status) error + } + } + return + } else { } # - For non-chunked transfer we may have no body - in this case # we may get no further file event if the connection doesn't # close and no more data is sent. We can tell and must finish @@ -2714,23 +3816,24 @@ # the server should close the connection. # - IF (NOT Connection: close) AND (NOT chunked encoding) AND # (totalsize == 0). if { (!( [info exists state(connection)] - && ($state(connection) eq "close") + && ("close" in $state(connection)) ) ) - && (![info exists state(transfer)]) + && ($state(transfer) eq {}) && ($state(totalsize) == 0) } { set msg {body size is 0 and no events likely - complete} Log "$msg - token $token" set msg {(length unknown, set to 0)} Log ^F$tk end of response body {*}$msg - token $token set state(state) complete Eot $token return + } else { } # We have to use binary translation to count bytes properly. lassign [fconfigure $sock -translation] trRead trWrite fconfigure $sock -translation [list binary $trWrite] @@ -2738,28 +3841,33 @@ if { $state(-binary) || [IsBinaryContentType $state(type)] } { # Turn off conversions for non-text data. set state(binary) 1 + } else { } if {[info exists state(-channel)]} { if {$state(binary) || [llength [ContentEncoding $token]]} { fconfigure $state(-channel) -translation binary + } else { } if {![info exists state(-handler)]} { # Initiate a sequence of background fcopies. fileevent $sock readable {} - rename ${token}EventCoroutine {} + rename ${token}--EventCoroutine {} CopyStart $sock $token return + } else { } + } else { } } elseif {$nhl > 0} { # Process header lines. ##Log header - token $token - $line if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} { - switch -- [string tolower $key] { + set key [string tolower $key] + switch -- $key { content-type { set state(type) [string trim [string tolower $value]] # Grab the optional charset information. if {[regexp -nocase \ {charset\s*=\s*\"((?:[^""]|\\\")*)\"} \ @@ -2780,60 +3888,52 @@ 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 + # 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 [eval $state(-handler) [list $sock $token]] + set n [namespace eval :: $state(-handler) [list $sock $token]] ##Log handler $n - token $token # N.B. the protocol has been set to 1.0 because the -handler # logic is not expected to handle chunked encoding. # FIXME Allow -handler with 1.1 on dechunked stacked chan. if {$state(totalsize) == 0} { # We know the transfer is complete only when the server # closes the connection - i.e. eof is not an error. set state(state) complete + } else { } if {![string is integer -strict $n]} { if 1 { # Do not tolerate bad -handler - fail with error # status. @@ -2859,14 +3959,15 @@ # "Connection: keep-alive" or the HTTP/1.0 # equivalent. set n 0 set state(state) complete } + } else { } } elseif {[info exists state(transfer_final)]} { # This code forgives EOF in place of the final CRLF. - set line [getTextLine $sock] + set line [GetTextLine $sock] set n [string length $line] set state(state) complete if {$n > 0} { # - HTTP trailers (late response headers) are permitted # by Chunked Transfer-Encoding, and can be safely @@ -2885,11 +3986,11 @@ } elseif { [info exists state(transfer)] && ($state(transfer) eq "chunked") } { ##Log chunked - token $token set size 0 - set hexLenChunk [getTextLine $sock] + set hexLenChunk [GetTextLine $sock] #set ntl [string length $hexLenChunk] if {[string trim $hexLenChunk] ne ""} { scan $hexLenChunk %x size if {$size != 0} { ##Log chunk-measure $size - token $token @@ -2898,10 +3999,11 @@ 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" @@ -2910,14 +4012,15 @@ Log ^X$tk end of response (chunk error) \ - token $token set msg {error in chunked encoding - fetch\ terminated} Eot $token $msg + } else { } # CRLF that follows chunk. # If eof, this is handled at the end of this proc. - getTextLine $sock + GetTextLine $sock } else { set n 0 set state(transfer_final) {} } } else { @@ -2957,10 +4060,11 @@ 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]} { @@ -2968,10 +4072,11 @@ 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)) @@ -2978,27 +4083,31 @@ } { Log ^F$tk end of response body (unchunked) -\ token $token set state(state) complete Eot $token + } else { } + } else { } } err]} { Log ^X$tk end of response (error ${err}) - token $token Finish $token $err return } else { if {[info exists state(-progress)]} { - eval $state(-progress) \ + namespace eval :: $state(-progress) \ [list $token $state(totalsize) $state(currentsize)] + } else { } } } # catch as an Eot above may have closed the socket already # $state(state) may be connecting, header, body, or complete - if {![set cc [catch {eof $sock} eof]] && $eof} { + if {(![catch {eof $sock} eof]) && $eof} { + # [eof sock] succeeded and the result was 1 ##Log eof - token $token if {[info exists $token]} { set state(connection) close if {$state(state) eq "complete"} { # This includes all cases in which the transaction @@ -3016,14 +4125,16 @@ } else { # open connection closed on a token that has been cleaned up. Log ^X$tk end of response (token error) - token $token CloseSocket $sock } - } elseif {$cc} { - return + } else { + # EITHER [eof sock] failed - presumed done by Eot + # OR [eof sock] succeeded and the result was 0 } } + return } # http::TestForReplay # # Command called if eof is discovered when a socket is first used for a @@ -3186,24 +4297,25 @@ dict set realopts key $cookiename dict set realopts value $cookieval {*}$http(-cookiejar) storeCookie $realopts } -# http::getTextLine -- +# http::GetTextLine -- # # Get one line with the stream in crlf mode. -# Used if Transfer-Encoding is chunked. +# Used if Transfer-Encoding is chunked, to read the line that +# reports the size of the following chunk. # Empty line is not distinguished from eof. The caller must # be able to handle this. # # Arguments # sock The socket receiving input. # # Results: # The line of text, without trailing newline -proc http::getTextLine {sock} { +proc http::GetTextLine {sock} { set tr [fconfigure $sock -translation] lassign $tr trRead trWrite fconfigure $sock -translation [list crlf $trWrite] set r [BlockingGets $sock] fconfigure $sock -translation $tr @@ -3212,20 +4324,22 @@ # http::BlockingRead # # Replacement for a blocking read. # The caller must be a coroutine. +# Used when we expect to read a chunked-encoding +# chunk of known size. proc http::BlockingRead {sock size} { if {$size < 1} { return } set result {} while 1 { set need [expr {$size - [string length $result]}] set block [read $sock $need] - set eof [eof $sock] + set eof [expr {[catch {eof $sock} tmp] || $tmp}] append result $block if {[string length $result] >= $size || $eof} { return $result } else { yield @@ -3241,11 +4355,11 @@ # be able to handle this. proc http::BlockingGets {sock} { while 1 { set count [gets $sock line] - set eof [eof $sock] + set eof [expr {[catch {eof $sock} tmp] || $tmp}] if {$count >= 0 || $eof} { return $line } else { yield } @@ -3262,20 +4376,32 @@ # # Side Effects # This closes the connection upon error proc http::CopyStart {sock token {initial 1}} { - upvar #0 $token state + upvar 0 $token state if {[info exists state(transfer)] && $state(transfer) eq "chunked"} { foreach coding [ContentEncoding $token] { - lappend state(zlib) [zlib stream $coding] + if {$coding eq {deflateX}} { + # Use the standards-compliant choice. + set coding2 decompress + } else { + set coding2 $coding + } + lappend state(zlib) [zlib stream $coding2] } - make-transformation-chunked $sock [namespace code [list CopyChunk $token]] + MakeTransformationChunked $sock [namespace code [list CopyChunk $token]] } else { if {$initial} { foreach coding [ContentEncoding $token] { - zlib push $coding $sock + 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 @@ -3285,10 +4411,11 @@ [list http::CopyDone $token] } err]} { Finish $token $err } } + return } proc http::CopyChunk {token chunk} { upvar 0 $token state if {[set count [string length $chunk]]} { @@ -3298,35 +4425,41 @@ set chunk [$stream add $chunk] } } puts -nonewline $state(-channel) $chunk if {[info exists state(-progress)]} { - eval [linsert $state(-progress) end \ + namespace eval :: [linsert $state(-progress) end \ $token $state(totalsize) $state(currentsize)] } } else { Log "CopyChunk Finish - token $token" if {[info exists state(zlib)]} { set excess "" foreach stream $state(zlib) { - catch {set excess [$stream add -finalize $excess]} + 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 transfered +# count The amount transferred # # Side Effects # Invokes callbacks proc http::CopyDone {token count {error {}}} { @@ -3333,11 +4466,11 @@ variable $token upvar 0 $token state set sock $state(sock) incr state(currentsize) $count if {[info exists state(-progress)]} { - eval $state(-progress) \ + namespace eval :: $state(-progress) \ [list $token $state(totalsize) $state(currentsize)] } # At this point the token may have been reset. if {[string length $error]} { Finish $token $error @@ -3344,10 +4477,11 @@ } elseif {[catch {eof $sock} iseof] || $iseof} { Eot $token } else { CopyStart $sock $token 0 } + return } # http::Eot # # Called when either: @@ -3365,11 +4499,11 @@ # token The token returned from http::geturl # force (previously) optional, has no effect # reason - "eof" means premature EOF (not EOF as the natural end of # the response) # - "" means completion of response, with or without EOF -# - anything else describes an error confition other than +# - anything else describes an error condition other than # premature EOF. # # Side Effects # Clean up the socket @@ -3389,11 +4523,24 @@ } if {[string length $state(body)] > 0} { if {[catch { foreach coding [ContentEncoding $token] { - set state(body) [zlib $coding $state(body)] + 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 @@ -3405,19 +4552,109 @@ # 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)] + if {[package vsatisfies [package provide Tcl] 9.0-]} { + set state(body) [encoding convertfrom -profile tcl8 $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 "?" +# (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. { ...} + + if {![regexp -nocase -- {^<[?]xml[[:space:]][^>?]*[?]>} $body match]} { + return 0 + } + # e.g. {} + + 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 tcl8 $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. # @@ -3459,52 +4696,45 @@ {Incorrect number of arguments, must be an even number.} } set result "" set sep "" foreach i $args { - append result $sep [mapReply $i] + append result $sep [quoteString $i] if {$sep eq "="} { set sep & } else { set sep = } } return $result } -# http::mapReply -- +# http::quoteString -- # # Do x-www-urlencoded character mapping # # Arguments: # string The string the needs to be encoded # # Results: # The encoded string -proc http::mapReply {string} { +proc http::quoteString {string} { variable http variable formMap # The spec says: "non-alphanumeric characters are replaced by '%HH'". Use # a pre-computed map and [string map] to do the conversion (much faster # than [regsub]/[subst]). [Bug 1020491] - if {$http(-urlencoding) ne ""} { + if {[package vsatisfies [package provide Tcl] 9.0-]} { + set string [encoding convertto -profile tcl8 $http(-urlencoding) $string] + } else { 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 + } + return [string map $formMap $string] +} # http::ProxyRequired -- # Default proxy filter. # # Arguments: @@ -3513,19 +4743,27 @@ # 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)] - } + 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 @@ -3538,11 +4776,11 @@ set charset [string tolower $charset] if {[regexp {iso-?8859-([0-9]+)} $charset -> num]} { set encoding "iso8859-$num" } elseif {[regexp {iso-?2022-(jp|kr)} $charset -> ext]} { set encoding "iso2022-$ext" - } elseif {[regexp {shift[-_]?js} $charset]} { + } elseif {[regexp {shift[-_]?jis} $charset]} { set encoding "shiftjis" } elseif {[regexp {(?:windows|cp)-?([0-9]+)} $charset -> num]} { set encoding "cp$num" } elseif {$charset eq "us-ascii"} { set encoding "ascii" @@ -3550,10 +4788,13 @@ 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 } @@ -3563,23 +4804,52 @@ } else { return "binary" } } + +# ------------------------------------------------------------------------------ +# Proc http::ContentEncoding +# ------------------------------------------------------------------------------ # Return the list of content-encoding transformations we need to do in order. +# + # -------------------------------------------------------------------------- + # Options for Accept-Encoding, Content-Encoding: the switch command + # -------------------------------------------------------------------------- + # The symbol deflateX allows http to attempt both versions of "deflate", + # unless there is a -channel - for a -channel, only "decompress" is tried. + # Alternative/extra lines for switch: + # The standards-compliant version of "deflate" can be chosen with: + # deflate { lappend r decompress } + # The Microsoft non-compliant version of "deflate" can be chosen with: + # deflate { lappend r inflate } + # The previously used implementation of "compress", which appears to be + # incorrect and is rarely used by web servers, can be chosen with: + # compress - x-compress { lappend r decompress } + # -------------------------------------------------------------------------- +# +# Arguments: +# token - Connection token. +# +# Return Value: list +# ------------------------------------------------------------------------------ + proc http::ContentEncoding {token} { upvar 0 $token state set r {} if {[info exists state(coding)]} { foreach coding [split $state(coding) ,] { switch -exact -- $coding { - deflate { lappend r inflate } + deflate { lappend r deflateX } gzip - x-gzip { lappend r gunzip } - compress - x-compress { lappend r decompress } identity {} + br { + return -code error\ + "content-encoding \"br\" not implemented" + } default { - return -code error "unsupported content-encoding \"$coding\"" + Log "unknown content-encoding \"$coding\" ignored" } } } } return $r @@ -3613,13 +4883,575 @@ return } } } -proc http::make-transformation-chunked {chan command} { +# 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::socketForTls +# ------------------------------------------------------------------------------ +# Command to use in place of ::socket as the value of ::tls::socketCmd. +# This command does the same as http::socket, 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::socketForTls {args} { + variable http + set host [lindex $args end-1] + set port [lindex $args end] + if { ($http(-proxyfilter) ne {}) + && (![catch {$http(-proxyfilter) $host} proxy]) + } { + set phost [lindex $proxy 0] + set pport [lindex $proxy 1] + } else { + set phost {} + set pport {} + } + if {$phost eq ""} { + set sock [::http::socket {*}$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::socket +# ------------------------------------------------------------------------------ +# This command is a drop-in replacement for ::socket. +# Arguments and return value as for ::socket. +# +# Notes. +# - http::socket 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::socket in the child, run http::socket in the parent, +# and then transfer the socket to the child. +# - The http::socket 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. +# ------------------------------------------------------------------------------ + +proc http::socket {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)} { + # 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::socket 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 +# +# Arguments: none +# Return Value: none +# ------------------------------------------------------------------------------ + +proc http::LoadThreadIfNeeded {} { + variable http + if {$http(usingThread) || ($http(-threadlevel) == 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 + } + return + } + set http(usingThread) 1 + return +} + + +# ------------------------------------------------------------------------------ +# Proc http::SockInThread +# ------------------------------------------------------------------------------ +# Command http::socket 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: Index: library/http/pkgIndex.tcl ================================================================== --- library/http/pkgIndex.tcl +++ library/http/pkgIndex.tcl @@ -1,2 +1,2 @@ if {![package vsatisfies [package provide Tcl] 8.6-]} {return} -package ifneeded http 2.10.0a1 [list tclPkgSetup $dir http 2.10.0a1 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}] +package ifneeded http 2.10b1 [list tclPkgSetup $dir http 2.10b1 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}] Index: library/init.tcl ================================================================== --- library/init.tcl +++ library/init.tcl @@ -1,15 +1,15 @@ # init.tcl -- # # Default system startup file for Tcl-based applications. Defines # "unknown" procedure and auto-load facilities. # -# Copyright (c) 1991-1993 The Regents of the University of California. -# Copyright (c) 1994-1996 Sun Microsystems, Inc. -# Copyright (c) 1998-1999 Scriptics Corporation. -# Copyright (c) 2004 by Kevin B. Kenny. -# Copyright (c) 2018 by Sean Woods +# Copyright © 1991-1993 The Regents of the University of California. +# Copyright © 1994-1996 Sun Microsystems, Inc. +# Copyright © 1998-1999 Scriptics Corporation. +# Copyright © 2004 Kevin B. Kenny. +# Copyright © 2018 Sean Woods # # All rights reserved. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -17,11 +17,11 @@ # This test intentionally written in pre-7.5 Tcl if {[info commands package] == ""} { error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]" } -package require -exact Tcl 9.0a2 +package require -exact tcl 9.0a4 # Compute the auto path to use in this interpreter. # The values on the path come from several locations: # # The environment variable TCLLIBPATH @@ -45,11 +45,19 @@ # ::auto_path (other than to {} if it is undefined). The caller, typically # a Safe Base command, is responsible for setting ::auto_path. if {![info exists auto_path]} { if {[info exists env(TCLLIBPATH)] && (![interp issafe])} { - set auto_path $env(TCLLIBPATH) + set auto_path [apply {{} { + lmap path $::env(TCLLIBPATH) { + # Paths relative to unresolvable home dirs are ignored + if {[catch {file tildeexpand $path} expanded_path]} { + continue + } + set expanded_path + } + }}] } else { set auto_path "" } } namespace eval tcl { @@ -130,11 +138,11 @@ # platforms, safe interpreters do not have exec. set auto_noexec 1 } -# Define a log command (which can be overwitten to log errors +# Define a log command (which can be overwritten to log errors # differently, specially when stderr is not available) if {[namespace which -command tclLog] eq ""} { proc tclLog {string} { catch {puts stderr $string} @@ -212,13 +220,13 @@ # construct the stack trace. # set errInfo [dict get $opts -errorinfo] set errCode [dict get $opts -errorcode] set cinfo $args - if {[string bytelength $cinfo] > 150} { + if {[string length [encoding convertto utf-8 $cinfo]] > 150} { set cinfo [string range $cinfo 0 150] - while {[string bytelength $cinfo] > 150} { + while {[string length [encoding convertto utf-8 $cinfo]] > 150} { set cinfo [string range $cinfo 0 end-1] } append cinfo ... } set tail "\n (\"uplevel\" body line 1)\n invoked\ @@ -440,11 +448,11 @@ catch {source [file join $dir tclIndex]} } elseif {[catch {set f [open [file join $dir tclIndex]]}]} { continue } else { set error [catch { - fconfigure $f -eofchar \032 + fconfigure $f -encoding utf-8 -eofchar \x1A set id [gets $f] if {$id eq "# Tcl autoload index file, version 2.0"} { eval [read $f] } elseif {$id eq "# Tcl autoload index file: each line identifies a Tcl"} { while {[gets $f line] >= 0} { @@ -589,11 +597,11 @@ if {[info exists auto_execs($name)]} { return $auto_execs($name) } set auto_execs($name) "" - set shellBuiltins [list assoc cls copy date del dir echo erase ftype \ + set shellBuiltins [list assoc cls copy date del dir echo erase exit ftype \ md mkdir mklink move rd ren rename rmdir start time type ver vol] if {[info exists env(PATHEXT)]} { # Add an initial ; to have the {} extension check first. set execExtensions [split ";$env(PATHEXT)" ";"] } else { @@ -724,11 +732,11 @@ # exists, then we should only call this function if -force # is true, which means we just want to over-write. So, # the following code is now commented out. # # return -code error "error $action \"$src\" to\ - # \"$dest\": file already exists" + # \"$dest\": file exists" } else { # Depending on the platform, and on the current # working directory, the directories '.', '..' # can be returned in various combinations. Anyway, # if any other file is returned, we must signal an error. @@ -736,11 +744,11 @@ lappend existing {*}[glob -nocomplain -directory $dest \ -type hidden * .*] foreach s $existing { if {[file tail $s] ni {. ..}} { return -code error "error $action \"$src\" to\ - \"$dest\": file already exists" + \"$dest\": file exists" } } } } else { if {[string first $nsrc $ndest] >= 0} { Index: library/install.tcl ================================================================== --- library/install.tcl +++ library/install.tcl @@ -33,11 +33,11 @@ set version [lindex [split $fname -] 1] ### # Read the file, and override assumptions as needed ### set fin [open $file r] - fconfigure $fin -encoding utf-8 -eofchar \032 + fconfigure $fin -encoding utf-8 -eofchar \x1A set dat [read $fin] close $fin # Look for a teapot style Package statement foreach line [split $dat \n] { set line [string trim $line] @@ -57,11 +57,11 @@ append buffer "package ifneeded $package $version \[list source \[file join \$dir [file tail $file]\]\]" \n } foreach file [glob -nocomplain $path/*.tcl] { if { [file tail $file] == "version_info.tcl" } continue set fin [open $file r] - fconfigure $fin -encoding utf-8 -eofchar \032 + fconfigure $fin -encoding utf-8 -eofchar \x1A set dat [read $fin] close $fin if {![regexp "package provide" $dat]} continue set fname [file rootname [file tail $file]] # Look for a package provide statement @@ -77,11 +77,11 @@ } } return $buffer } set fin [open $pkgidxfile r] - fconfigure $fin -encoding utf-8 -eofchar \032 + fconfigure $fin -encoding utf-8 -eofchar \x1A set dat [read $fin] close $fin set trace 0 #if {[file tail $path] eq "tool"} { # set trace 1 @@ -200,19 +200,19 @@ if {[file isdirectory $f] && [string compare CVS $ftail]} { installDir $f [file join $d2 $ftail] } elseif {[file isfile $f]} { file copy -force $f [file join $d2 $ftail] if {$::tcl_platform(platform) eq {unix}} { - file attributes [file join $d2 $ftail] -permissions 0644 + file attributes [file join $d2 $ftail] -permissions 0o644 } else { file attributes [file join $d2 $ftail] -readonly 1 } } } if {$::tcl_platform(platform) eq {unix}} { - file attributes $d2 -permissions 0755 + file attributes $d2 -permissions 0o755 } else { file attributes $d2 -readonly 1 } } Index: library/manifest.txt ================================================================== --- library/manifest.txt +++ library/manifest.txt @@ -3,18 +3,18 @@ ### apply {{dir} { set ::test [info script] set isafe [interp issafe] foreach {safe package version file} { - 0 http 2.10.0a1 {http http.tcl} + 0 http 2.10b1 {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 1.0.19 {platform platform.tcl} 0 platform::shell 1.1.4 {platform shell.tcl} - 1 tcltest 2.5.3 {tcltest tcltest.tcl} + 1 tcltest 2.5.6 {tcltest tcltest.tcl} } { if {$isafe && !$safe} continue package ifneeded $package $version [list source [file join $dir {*}$file]] } }} $dir Index: library/msgcat/msgcat.tcl ================================================================== --- library/msgcat/msgcat.tcl +++ library/msgcat/msgcat.tcl @@ -2,13 +2,13 @@ # # This file defines various procedures which implement a # message catalog facility for Tcl programs. It should be # loaded with the command "package require msgcat". # -# Copyright (c) 2010-2018 by Harald Oehlmann. -# Copyright (c) 1998-2000 by Ajuba Solutions. -# Copyright (c) 1998 by Mark Harrison. +# Copyright © 2010-2018 Harald Oehlmann. +# Copyright © 1998-2000 Ajuba Solutions. +# Copyright © 1998 Mark Harrison. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # We use oo::define::self, which is new in Tcl 8.7 @@ -32,11 +32,11 @@ # 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 "