From d7c57a0c14b306a099a03885326e544df594db08 Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 22 Jul 2025 18:18:41 +0000 Subject: improve interpreter creation speed, if there is no zipfs tcl-library (avoid performance penalty [62019f8aa9f5ec73]) --- generic/tclZipfs.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index 7530cc2..503e22c 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -398,6 +398,7 @@ static const char pwrot[17] = "\x00\x80\x40\xC0\x20\xA0\x60\xE0" "\x10\x90\x50\xD0\x30\xB0\x70\xF0"; +static int zipfs_tcl_library_init = 0; static const char *zipfs_literal_tcl_library = NULL; /* Function prototypes */ @@ -4340,6 +4341,7 @@ ScriptLibrarySetup( Tcl_DecrRefCount(searchPathObj); /* Bug [fccb9f322f]. Reinit system encoding after setting search path */ TclpSetInitialEncodings(); + zipfs_tcl_library_init = 1; return libDirObj; } @@ -4357,10 +4359,13 @@ TclZipfs_TclLibrary(void) /* * Use the cached value if that has been set; we don't want to repeat the - * searching and mounting. + * searching and mounting. Even if it is not found, see [62019f8aa9f5ec73]. */ - - if (zipfs_literal_tcl_library) { + + if (zipfs_tcl_library_init) { + if (!zipfs_literal_tcl_library) { + return NULL; + } return ScriptLibrarySetup(zipfs_literal_tcl_library); } @@ -4417,6 +4422,11 @@ TclZipfs_TclLibrary(void) if (zipfs_literal_tcl_library) { return ScriptLibrarySetup(zipfs_literal_tcl_library); } + /* + * No zipfs tcl-library, mark it to avoid performance penalty [62019f8aa9f5ec73], + * by future calls (child interpreters, threads, etc). + */ + zipfs_tcl_library_init = 1; return NULL; } -- cgit v0.12 From 1be1ad4d27ac35b00026ce4587c3ecce731078b7 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Wed, 30 Jul 2025 10:26:34 +0000 Subject: Fix test errors for -singleproc 1 runs on Windows --- tests/encoding.test | 4 ++++ tests/exec.test | 2 +- tests/fCmd.test | 30 ++++++++++++++++++++++-------- tests/fileName.test | 12 ++++++++---- tests/fileSystem.test | 1 + 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/tests/encoding.test b/tests/encoding.test index 9d1351c..66a60a8 100644 --- a/tests/encoding.test +++ b/tests/encoding.test @@ -84,6 +84,7 @@ test encoding-2.2 {Tcl_FreeEncoding: refcount != 0} -setup { encoding system iso8859-1 encoding dirs $path encoding system $system + unset -nocomplain path } -result "\x8C\xC1 1 {unknown encoding \"shiftjis\"}" test encoding-3.1 {Tcl_GetEncodingName, NULL} -setup { @@ -138,6 +139,7 @@ test encoding-4.1 {Tcl_GetEncodingNames} -constraints {testencoding} -setup { removeFile [file join tmp encoding junk.enc] removeDirectory [file join tmp encoding] removeDirectory tmp + unset -nocomplain path } -result {junk junk2} test encoding-5.1 {Tcl_SetSystemEncoding} -setup { @@ -236,6 +238,7 @@ test encoding-11.1 {LoadEncodingFile: unknown encoding} {testencoding} { llength jis0208 ;# Shimmer any cached Tcl_Encoding in shared literal set x [list [catch {encoding convertto jis0208 乎} msg] $msg] encoding dirs $path + unset -nocomplain path encoding system $system lappend x [encoding convertto jis0208 乎] } {1 {unknown encoding "jis0208"} 8C} @@ -275,6 +278,7 @@ test encoding-11.6 {LoadEncodingFile: invalid file} -constraints {testencoding} cd [workingDirectory] encoding dirs $path encoding system $system + unset -nocomplain path } -result {invalid encoding file "splat"} test encoding-11.8 {encoding: extended Unicode UTF-16} { encoding convertto utf-16le 😹 diff --git a/tests/exec.test b/tests/exec.test index 576f97d..53006d3 100644 --- a/tests/exec.test +++ b/tests/exec.test @@ -828,7 +828,7 @@ unset cmdBuiltin foreach file {gorp.file gorp.file2 echo echo2 echobin cat wc sh sh2 sleep exit err} { removeFile $file } -unset -nocomplain path +unset -nocomplain path tmp ::tcltest::cleanupTests return diff --git a/tests/fCmd.test b/tests/fCmd.test index 1557120..1d7cfef 100644 --- a/tests/fCmd.test +++ b/tests/fCmd.test @@ -2708,6 +2708,7 @@ test fCmd-30.3 {file readable on 'pagefile.sys'} -constraints {win notInCIenv} - lappend r exists [file exists $path] lappend r readable [file readable $path] lappend r stat [catch {file stat $path a} e] $e + unset -nocomplain path } return $r } -result {exists 1 readable 0 stat 0 {}} @@ -2716,17 +2717,20 @@ test fCmd-31.1 {file home} -body { file home } -result [file join $::env(HOME)] test fCmd-31.2 {file home - obeys env} -setup { + set temp $::env(HOME) set ::env(HOME) $::env(HOME)/xxx } -cleanup { - set ::env(HOME) [file dirname $::env(HOME)] + set ::env(HOME) $temp + unset temp } -body { file home } -result [file join $::env(HOME) xxx] test fCmd-31.3 {file home - \ -> /} -constraints win -setup { - set saved $::env(HOME) + set temp $::env(HOME) set ::env(HOME) C:\\backslash\\path } -cleanup { - set ::env(HOME) $saved + set ::env(HOME) $temp + unset temp } -body { file home } -result C:/backslash/path @@ -2735,6 +2739,7 @@ test fCmd-31.4 {file home - error} -setup { unset ::env(HOME) } -cleanup { set ::env(HOME) $saved + unset saved } -body { file home } -returnCodes error -result {couldn't find HOME environment variable to expand path} @@ -2746,6 +2751,7 @@ test fCmd-31.5 { set ::env(HOME) relative/path } -cleanup { set ::env(HOME) $saved + unset saved } -body { file home } -result relative/path @@ -2762,9 +2768,11 @@ test fCmd-31.8 {file home extra arg} -body { file home $::tcl_platform(user) arg } -returnCodes error -result {wrong # args: should be "file home ?user?"} test fCmd-31.9 {file home USER does not follow env(HOME)} -setup { + set saved $::env(HOME) set ::env(HOME) [file join $::env(HOME) foo] } -cleanup { - set ::env(HOME) [file dirname $::env(HOME)] + set ::env(HOME) $saved + unset saved } -body { string tolower [file home $::tcl_platform(user)] } -match glob -result [gethomedirglob $::tcl_platform(user)] @@ -2779,16 +2787,20 @@ test fCmd-32.1.1 {Tcl_FSTildeExpand ~} -constraints testfstildeexpand -body { testfstildeexpand ~ } -result [file join $::env(HOME)] test fCmd-32.2 {file tildeexpand ~ - obeys env} -setup { + set saved $::env(HOME) set ::env(HOME) $::env(HOME)/xxx } -cleanup { - set ::env(HOME) [file dirname $::env(HOME)] + set ::env(HOME) $saved + unset saved } -body { file tildeexpand ~ } -result [file join $::env(HOME) xxx] test fCmd-32.2.1 {Tcl_FSTildeExpand ~ - obeys env} -setup { + set saved $::env(HOME) set ::env(HOME) $::env(HOME)/xxx } -cleanup { - set ::env(HOME) [file dirname $::env(HOME)] + set ::env(HOME) $saved + unset saved } -constraints testfstildeexpand -body { testfstildeexpand ~ } -result [file join $::env(HOME) xxx] @@ -2921,16 +2933,18 @@ test fCmd-32.16.1 {Tcl_FSTildeExpand ~USER\\bar} -constraints testfstildeexpand string tolower [testfstildeexpand ~$::tcl_platform(user)\\bar] } -constraints win -match glob -result [file join [gethomedirglob $::tcl_platform(user)] bar] test fCmd-32.17 {file tildeexpand ~USER does not mirror HOME} -setup { + set oldHome $::env(HOME) set ::env(HOME) [file join $::env(HOME) foo] } -cleanup { - set ::env(HOME) [file dirname $::env(HOME)] + set ::env(HOME) $oldHome } -body { string tolower [file tildeexpand ~$::tcl_platform(user)] } -match glob -result [gethomedirglob $::tcl_platform(user)] test fCmd-32.17.1 {Tcl_FSTildeExpand ~USER does not mirror HOME} -setup { + set oldHome $::env(HOME) set ::env(HOME) [file join $::env(HOME) foo] } -cleanup { - set ::env(HOME) [file dirname $::env(HOME)] + set ::env(HOME) $oldHome } -constraints testfstildeexpand -body { string tolower [testfstildeexpand ~$::tcl_platform(user)] } -match glob -result [gethomedirglob $::tcl_platform(user)] diff --git a/tests/fileName.test b/tests/fileName.test index 64213c7..5bd02c7 100644 --- a/tests/fileName.test +++ b/tests/fileName.test @@ -14,7 +14,7 @@ if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } - +set existingGlobals [info globals] ::tcltest::loadTestedCommands catch [list package require -exact tcl::test [info patchlevel]] @@ -1275,10 +1275,10 @@ test filename-14.23 {slash globbing} {unix} { } / test filename-14.23.2 {slash globbing} {win} { glob / -} [file norm /] +} [file normalize /] test filename-14.24 {slash globbing} {win} { glob {\\} -} [file norm /] +} [file normalize /] test filename-14.25 {type specific globbing} {unix} { lsort [glob -dir globTest -types f *] } [lsort [list \ @@ -1697,7 +1697,11 @@ if {[testConstraint testsetplatform]} { testsetplatform $platform catch {unset platform} } -catch {unset oldhome temp result globPreResult} +unset -nocomplain {*}[lmap x [info globals] { + if {$x in $existingGlobals} {continue} + set x +}] + ::tcltest::cleanupTests return diff --git a/tests/fileSystem.test b/tests/fileSystem.test index 62abb51..fb59ae9 100644 --- a/tests/fileSystem.test +++ b/tests/fileSystem.test @@ -334,6 +334,7 @@ test filesystem-1.38 {file normalisation with volume relative} -setup { file norm $path } -cleanup { cd $dir + unset -nocomplain path } -result "[lindex $drives 0]foo" test filesystem-1.39 {file normalisation with volume relative} -setup { set old [pwd] -- cgit v0.12 From 5c1c118b8ad5b01168a7f4515c9c4fb3d4b59b13 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Wed, 30 Jul 2025 16:20:10 +0000 Subject: Workaround for [8c63606802] - testsetplatform / path caching with -singleproc 1 --- tests/fileName.test | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/fileName.test b/tests/fileName.test index 5bd02c7..4f2d595 100644 --- a/tests/fileName.test +++ b/tests/fileName.test @@ -1273,12 +1273,17 @@ test filename-14.22 {asterisks, question marks, and brackets} -body { test filename-14.23 {slash globbing} {unix} { glob / } / + +# NOTE: [The string index x/ 1] construction is a workaround for the +# testsetplatform calls above interacting with normalized path caching +# in -singleproc 1 runs. See ticket [8c63606802]. test filename-14.23.2 {slash globbing} {win} { glob / -} [file normalize /] +} [file normalize [string index x/ 1]] test filename-14.24 {slash globbing} {win} { glob {\\} -} [file normalize /] +} [file normalize [string index x/ 1]] + test filename-14.25 {type specific globbing} {unix} { lsort [glob -dir globTest -types f *] } [lsort [list \ -- cgit v0.12 From b099048f89a846f4ec62ef081ed6ab5c6a86dd74 Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 31 Jul 2025 13:37:02 +0000 Subject: tcltest: output begin/end timestamps locale independently (as ISO 8601 datetime), also it'd help to avoid side effects like [5137b4387019d0e1] (windows may need registry package to get system locale) --- library/tcltest/tcltest.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/tcltest/tcltest.tcl b/library/tcltest/tcltest.tcl index 302ffee..56dca19 100644 --- a/library/tcltest/tcltest.tcl +++ b/library/tcltest/tcltest.tcl @@ -2911,7 +2911,7 @@ proc tcltest::runAllTests { {shell ""} } { "Only running test files that match: [matchFiles]" } - set timeCmd {clock format [clock seconds]} + set timeCmd {clock format now -format "%Y-%m-%d %H:%M:%S %Z" -locale en} puts [outputChannel] "Tests began at [eval $timeCmd]" # Run each of the specified tests -- cgit v0.12 From 7ccad65c742599c9f5aa7363bf388ce433fb1e04 Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 31 Jul 2025 13:43:47 +0000 Subject: clock.test: fixes bug [5137b4387019d0e1] (test clock with -singleproc 1); rewrite clock tests locale, timezone, environment (TZ, TCL_TZ) and also registry independent, also improve several setups/cleanups and usage of test-own registry --- library/clock.tcl | 15 ++- tests/clock.test | 278 +++++++++++++----------------------------------------- 2 files changed, 79 insertions(+), 214 deletions(-) diff --git a/library/clock.tcl b/library/clock.tcl index d3ad63a..dd5a9c9 100644 --- a/library/clock.tcl +++ b/library/clock.tcl @@ -668,14 +668,17 @@ proc ::tcl::clock::EnterLocale { locale } { #---------------------------------------------------------------------- # +# _registryExists -- # _hasRegistry -- # -# Helper that checks whether registry module is available (Windows only) +# Helpers that checks whether registry module is available (Windows only) # and loads it on demand. # +# Side effects: +# _hasRegistry does it only once, and hereafter simply returns 1 or 0. +# #---------------------------------------------------------------------- -proc ::tcl::clock::_hasRegistry {} { - set res 0 +proc ::tcl::clock::_registryExists {} { if { $::tcl_platform(platform) eq {windows} } { if { [catch { package require registry 1.3 }] } { # try to load registry directly from root (if uninstalled / development env): @@ -687,9 +690,13 @@ proc ::tcl::clock::_hasRegistry {} { }} } if { [namespace which -command ::registry] ne "" } { - set res 1 + return 1 } } + return 0 +} +proc ::tcl::clock::_hasRegistry {} { + set res [_registryExists] proc ::tcl::clock::_hasRegistry {} [list return $res] return $res } diff --git a/tests/clock.test b/tests/clock.test index e1bbc88..210239e 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -269,7 +269,6 @@ namespace eval ::testClock { DaylightStart \x00\x00\x03\x00\x02\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00]] } - proc ::testClock::registry { cmd path key } { variable reg if { $cmd ne {get} } { @@ -280,6 +279,50 @@ proc ::testClock::registry { cmd path key } { } return [dict get $reg $path $key] } +proc ::testClock::_setupRegistry {} { + rename ::tcl::clock::_hasRegistry ::tcl::clock::_org_hasRegistry + proc ::tcl::clock::_hasRegistry {} {return 1} + namespace eval ::tcl::clock { + namespace import -force ::testClock::registry + } + ::tcl::clock::ClearCaches +} +proc ::testClock::_cleanupRegistry {} { + if {[namespace which -command ::tcl::clock::registry] ne ""} { + rename ::tcl::clock::registry {} + } + rename ::tcl::clock::_hasRegistry {} + rename ::tcl::clock::_org_hasRegistry ::tcl::clock::_hasRegistry + ::tcl::clock::ClearCaches +} + +proc ::testClock::_setupNoTZ {} { + if { [info exists ::env(TZ)] } { + variable orgTZ $::env(TZ) + unset ::env(TZ) + } + if { [info exists ::env(TCL_TZ)] } { + variable orgTclTZ $::env(TCL_TZ) + unset ::env(TCL_TZ) + } +} +proc ::testClock::_cleanupNoTZ {} { + variable orgTclTZ + if { [info exists orgTclTZ] } { + set ::env(TCL_TZ) $orgTclTZ + } else { + unset -nocomplain ::env(TCL_TZ) + } + variable orgTZ + if { [info exists orgTZ] } { + set ::env(TZ) $orgTZ + } else { + unset -nocomplain ::env(TZ) + } +} + +# Don't confuse all following tests with TZ or TCL_TZ environment vars (unset them here): +::testClock::_setupNoTZ # Base test cases: @@ -35952,22 +35995,13 @@ test clock-30.34 {regression test - clock add jump over DST hole with TZ (1 day test clock-31.1 {system locale} \ -constraints {win noappverifier} \ -setup { - namespace eval ::tcl::clock { - namespace import -force ::testClock::registry - } - set noreg [info exists ::tcl::clock::NoRegistry] - if {$noreg} {unset ::tcl::clock::NoRegistry} - ::tcl::clock::ClearCaches + ::testClock::_setupRegistry } \ -body { clock format 0 -timezone :UTC -locale system -format %x } \ -cleanup { - namespace eval ::tcl::clock { - rename registry {} - } - if {$noreg} {set ::tcl::clock::NoRegistry {}} - ::tcl::clock::ClearCaches + ::testClock::_cleanupRegistry } \ -result [clock format 0 -timezone :UTC -locale current \ -format {%d-%b-%Y}] @@ -35975,22 +36009,13 @@ test clock-31.1 {system locale} \ test clock-31.2 {system locale} \ -constraints {win noappverifier} \ -setup { - namespace eval ::tcl::clock { - namespace import -force ::testClock::registry - } - set noreg [info exists ::tcl::clock::NoRegistry] - if {$noreg} {unset ::tcl::clock::NoRegistry} - ::tcl::clock::ClearCaches + ::testClock::_setupRegistry } \ -body { clock format 0 -timezone :UTC -locale system -format %Ex } \ -cleanup { - namespace eval ::tcl::clock { - rename registry {} - } - if {$noreg} {set ::tcl::clock::NoRegistry {}} - ::tcl::clock::ClearCaches + ::testClock::_cleanupRegistry } \ -result [clock format 0 -timezone :UTC -locale current \ -format {the %d' day of %B %Y}] @@ -35998,22 +36023,13 @@ test clock-31.2 {system locale} \ test clock-31.3 {system locale} \ -constraints {win noappverifier} \ -setup { - namespace eval ::tcl::clock { - namespace import -force ::testClock::registry - } - set noreg [info exists ::tcl::clock::NoRegistry] - if {$noreg} {unset ::tcl::clock::NoRegistry} - ::tcl::clock::ClearCaches + ::testClock::_setupRegistry } \ -body { clock format 0 -timezone :UTC -locale system -format %X } \ -cleanup { - namespace eval ::tcl::clock { - rename registry {} - } - if {$noreg} {set ::tcl::clock::NoRegistry {}} - ::tcl::clock::ClearCaches + ::testClock::_cleanupRegistry } \ -result [clock format 0 -timezone :UTC -locale current \ -format {%l:%M:%S %p}] @@ -36021,36 +36037,13 @@ test clock-31.3 {system locale} \ test clock-31.4 {system locale} \ -constraints {win noappverifier} \ -setup { - namespace eval ::tcl::clock { - namespace import -force ::testClock::registry - } - set noreg [info exists ::tcl::clock::NoRegistry] - if {$noreg} {unset ::tcl::clock::NoRegistry} - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - unset env(TZ) - } - if { [info exists env(TCL_TZ)] } { - set oldTclTZ $env(TCL_TZ) - unset env(TCL_TZ) - } - ::tcl::clock::ClearCaches + ::testClock::_setupRegistry } \ -body { clock format 0 -locale system -format %x } \ -cleanup { - namespace eval ::tcl::clock { - rename registry {} - } - if { [info exists oldTclTZ] } { - set env(TCL_TZ) $oldTclTZ - } - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - } - if {$noreg} {set ::tcl::clock::NoRegistry {}} - ::tcl::clock::ClearCaches + ::testClock::_cleanupRegistry } \ -result [clock format 0 -locale current -timezone EST5 \ -format {%d-%b-%Y}] @@ -36058,36 +36051,13 @@ test clock-31.4 {system locale} \ test clock-31.5 {system locale} \ -constraints {win noappverifier} \ -setup { - namespace eval ::tcl::clock { - namespace import -force ::testClock::registry - } - set noreg [info exists ::tcl::clock::NoRegistry] - if {$noreg} {unset ::tcl::clock::NoRegistry} - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - unset env(TZ) - } - if { [info exists env(TCL_TZ)] } { - set oldTclTZ $env(TCL_TZ) - unset env(TCL_TZ) - } - ::tcl::clock::ClearCaches + ::testClock::_setupRegistry } \ -body { clock format 0 -locale system -format %Ex } \ -cleanup { - namespace eval ::tcl::clock { - rename registry {} - } - if {$noreg} {set ::tcl::clock::NoRegistry {}} - if { [info exists oldTclTZ] } { - set env(TCL_TZ) $oldTclTZ - } - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - } - ::tcl::clock::ClearCaches + ::testClock::_cleanupRegistry } \ -result [clock format 0 -locale current -timezone EST5 \ -format {the %d' day of %B %Y}] @@ -36095,36 +36065,13 @@ test clock-31.5 {system locale} \ test clock-31.6 {system locale} \ -constraints {win noappverifier} \ -setup { - namespace eval ::tcl::clock { - namespace import -force ::testClock::registry - } - set noreg [info exists ::tcl::clock::NoRegistry] - if {$noreg} {unset ::tcl::clock::NoRegistry} - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - unset env(TZ) - } - if { [info exists env(TCL_TZ)] } { - set oldTclTZ $env(TCL_TZ) - unset env(TCL_TZ) - } - ::tcl::clock::ClearCaches + ::testClock::_setupRegistry } \ -body { clock format 0 -locale system -format "%X %Z" } \ -cleanup { - namespace eval ::tcl::clock { - rename registry {} - } - if {$noreg} {set ::tcl::clock::NoRegistry {}} - if { [info exists oldTclTZ] } { - set env(TCL_TZ) $oldTclTZ - } - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - } - ::tcl::clock::ClearCaches + ::testClock::_cleanupRegistry } \ -result [clock format 0 -locale current -timezone EST5 \ -format {%l:%M:%S %p %Z}] @@ -36975,62 +36922,32 @@ test clock-37.3 {%Es gmt testing CEST} { test clock-38.1 {regression - convertUTCToLocalViaC - east of Greenwich} \ -setup { - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - } set env(TZ) CET-01:00CEST-02:00,M3.5.0/02:00,M10.5.0/03:00 } \ -body { clock format 0 -format %H:%M:%S -timezone :localtime } \ -cleanup { - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - unset oldTZ - } else { - unset env(TZ) - } + unset -nocomplain env(TZ) } \ -result {01:00:00} test clock-38.2 {make sure TZ is not cached after unset} \ - -setup { - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - unset env(TZ) - } - if { [info exists env(TCL_TZ)] } { - set oldTCLTZ $env(TCL_TZ) - unset env(TCL_TZ) - } - } \ -body { set t1 [clock format 0] # a time zone that is unlikely to anywhere set env(TZ) "+04:20" set t2 [clock format 0] - unset env(TZ) + unset -nocomplain env(TZ) set t3 [clock format 0] expr {$t1 eq $t3 && $t1 ne $t2} } \ -cleanup { - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - unset oldTZ - } - if { [info exists oldTclTZ] } { - set env(TCL_TZ) $oldTclTZ - unset oldTclTZ - } + unset -nocomplain env(TZ) } \ -result 1 test clock-38.3sc {ensure cache of base is correct for :localtime if TZ-env changing / scan} \ - -setup { - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - } - } \ -body { set res {} foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} \ @@ -37041,20 +36958,10 @@ test clock-38.3sc {ensure cache of base is correct for :localtime if TZ-env chan set res } \ -cleanup { - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - unset oldTZ - } else { - unset env(TZ) - } + unset -nocomplain env(TZ) } \ -result [lrepeat 4 [expr {20*60*60}]] test clock-38.3fm {ensure cache of base is correct for :localtime if TZ-env changing / format} \ - -setup { - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - } - } \ -body { set res {} foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} { @@ -37063,12 +36970,7 @@ test clock-38.3fm {ensure cache of base is correct for :localtime if TZ-env chan set res } \ -cleanup { - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - unset oldTZ - } else { - unset env(TZ) - } + unset -nocomplain env(TZ) } \ -result {{1970-01-02T07:30:00 +1130} {1970-01-02T03:30:00 +0730} {1970-01-01T23:30:00 +0330} {1970-01-01T20:00:00 +0000}} @@ -37078,9 +36980,6 @@ test clock-39.1 {regression - synonym timezones} { test clock-40.1 {regression - bad month with -timezone :localtime} \ -setup { - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - } set env(TZ) UTC0 } \ -body { @@ -37088,12 +36987,7 @@ test clock-40.1 {regression - bad month with -timezone :localtime} \ -format %Y-%m-%dT%H:%M:%S } \ -cleanup { - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - unset oldTZ - } else { - unset env(TZ) - } + unset -nocomplain env(TZ) } \ -result 946684800 @@ -37103,21 +36997,13 @@ test clock-41.1 {regression test - format group %k when hour is 0 } { test clock-42.1 {regression test - %z in :localtime when west of Greenwich } \ -setup { - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - } set env(TZ) EST5 } \ -body { clock format 0 -format %z -timezone :localtime } \ -cleanup { - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - unset oldTZ - } else { - unset env(TZ) - } + unset -nocomplain env(TZ) } \ -result {-0500} @@ -37125,21 +37011,13 @@ test clock-42.1 {regression test - %z in :localtime when west of Greenwich } \ test clock-44.1 {regression test - time zone name containing hyphen } \ -setup { - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - } set env(TZ) US/East-Indiana } \ -body { clock format 1098466496 -format %H:%M:%S%z -timezone US/East-Indiana } \ -cleanup { - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - unset oldTZ - } else { - unset env(TZ) - } + unset -nocomplain env(TZ) } \ -result {12:34:56-0500} @@ -37558,19 +37436,7 @@ test clock-49.2 {regression test - missing time zone file (Bug 1237907)} \ -constraints {win noappverifier} \ -setup { # override the registry so that the test takes place in New York time - namespace eval ::tcl::clock { - namespace import -force ::testClock::registry - } - set noreg [info exists ::tcl::clock::NoRegistry] - if {$noreg} {unset ::tcl::clock::NoRegistry} - if { [info exists env(TZ)] } { - set oldTZ $env(TZ) - unset env(TZ) - } - if { [info exists env(TCL_TZ)] } { - set oldTclTZ $env(TCL_TZ) - unset env(TCL_TZ) - } + ::testClock::_setupRegistry # make it so New York time is a missing file dict set ::tcl::clock::WinZoneInfo \ {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} \ @@ -37584,16 +37450,7 @@ test clock-49.2 {regression test - missing time zone file (Bug 1237907)} \ } \ -cleanup { # restore the registry and environment - namespace eval ::tcl::clock { - rename registry {} - } - if {$noreg} {set ::tcl::clock::NoRegistry {}} - if { [info exists oldTclTZ] } { - set env(TCL_TZ) $oldTclTZ - } - if { [info exists oldTZ] } { - set env(TZ) $oldTZ - } + ::testClock::_cleanupRegistry # put New York back on the map dict set ::tcl::clock::WinZoneInfo \ {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} \ @@ -38625,8 +38482,9 @@ if {!$valid_mode && [info exists ::tcltest::skippedBecause(!valid_off)]} { incr ::tcltest::numTests(Skipped) -$::tcltest::skippedBecause(!valid_off) unset ::tcltest::skippedBecause(!valid_off) } -::tcltest::cleanupTests +::testClock::_cleanupNoTZ namespace delete ::testClock +::tcltest::cleanupTests unset valid_mode return -- cgit v0.12 From a37a480bf571d7a03726479944401d2c7bafbca2 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Thu, 31 Jul 2025 13:57:58 +0000 Subject: Add test for [87b69745be]. --- tests/encoding.test | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/encoding.test b/tests/encoding.test index 66a60a8..79169cd 100644 --- a/tests/encoding.test +++ b/tests/encoding.test @@ -1248,6 +1248,16 @@ test encoding-bug-7346adc50f-tcl8 {OOM on convertfrom truncated iso2022 - tcl8} encoding convertfrom -profile tcl8 iso2022-jp "\x1b\$B\$*;n\$" } -result \u304A\u8A66\uFFFD +test encoding-dirs-bug-87b69745be {encoding dirs reset on interp creation} -setup { + set origEncodingDirs [encoding dirs] +} -cleanup { + encoding dirs $origEncodingDirs + unset -nocomplain origEncodingDirs +} -body { + encoding dirs [linsert [encoding dirs] end /temp] + interp delete [interp create] + encoding dirs +} -result [linsert [encoding dirs] end /temp] # cleanup namespace delete ::tcl::test::encoding -- cgit v0.12 From 3fe5d2c50d9ed7084ced3c8ad567736313d6efce Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 31 Jul 2025 17:08:47 +0000 Subject: more informative result of test clock-38.2 (in failure case it'd output all 3 results of formats as subst of expr) --- tests/clock.test | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/clock.test b/tests/clock.test index 210239e..c932837 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -36934,18 +36934,18 @@ test clock-38.1 {regression - convertUTCToLocalViaC - east of Greenwich} \ test clock-38.2 {make sure TZ is not cached after unset} \ -body { - set t1 [clock format 0] + set t1 [clock format 0 -locale en] # a time zone that is unlikely to anywhere set env(TZ) "+04:20" - set t2 [clock format 0] + set t2 [clock format 0 -locale en] unset -nocomplain env(TZ) - set t3 [clock format 0] - expr {$t1 eq $t3 && $t1 ne $t2} + set t3 [clock format 0 -locale en] + list [expr {$t1 eq $t3 && $t1 ne $t2}] [subst {"$t1" eq "$t3" && "$t1" ne "$t2"}] } \ -cleanup { unset -nocomplain env(TZ) } \ - -result 1 + -match glob -result {1 *} test clock-38.3sc {ensure cache of base is correct for :localtime if TZ-env changing / scan} \ -body { -- cgit v0.12 From 23a39ad85fd04eb882c40ef9deae3f20f2bf285c Mon Sep 17 00:00:00 2001 From: sebres Date: Fri, 1 Aug 2025 11:59:34 +0000 Subject: (windows, noregistry only) invalidate base fields cache for TZ ":localtime", if TZ-epoch changed (without registry module and real TZ name, the local data epoch may be updated, but cache may contain offset of previos TZ, so ensure it'd be invalidated) --- generic/tclClock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index a850058..1f7a1db 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -988,7 +988,11 @@ ClockConfigureObjCmd( TclSetObjRef(dataPtr->systemTimeZone, objv[i]); TclUnsetObjRef(dataPtr->systemSetupTZData); } - dataPtr->lastTZEpoch = lastTZEpoch; + if (dataPtr->lastTZEpoch != lastTZEpoch) { + dataPtr->lastTZEpoch = lastTZEpoch; + /* TZ epoch changed - invalidate base-cache */ + TclUnsetObjRef(dataPtr->lastBase.timezoneObj); + } } if (i + 1 >= objc && dataPtr->systemTimeZone != NULL && dataPtr->lastTZEpoch == lastTZEpoch) { -- cgit v0.12 From 0da7d37ae9e40a473991c87155abf533ae5d45a0 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sun, 3 Aug 2025 11:38:46 +0000 Subject: Move search of zipfs to process initialization, not interp initialization --- generic/tclInt.h | 1 + generic/tclZipfs.c | 47 ++++++++++++++++++++++++++++------------------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/generic/tclInt.h b/generic/tclInt.h index f088545..c227b0c 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3733,6 +3733,7 @@ MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp, MODULE_SCOPE int TclZipfs_Init(Tcl_Interp *interp); MODULE_SCOPE int TclIsZipfsPath(const char *path); MODULE_SCOPE void TclZipfsFinalize(void); +MODULE_SCOPE int TclZipfsLocateTclLibrary(void); /* * Many parsing tasks need a common definition of whitespace. diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index 503e22c..4853376 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -4345,8 +4345,8 @@ ScriptLibrarySetup( return libDirObj; } -Tcl_Obj * -TclZipfs_TclLibrary(void) +int +TclZipfsLocateTclLibrary(void) { Tcl_Obj *vfsInitScript; int found; @@ -4357,17 +4357,7 @@ TclZipfs_TclLibrary(void) char dllName[(MAX_PATH + LIBRARY_SIZE) * 3]; #endif /* _WIN32 */ - /* - * Use the cached value if that has been set; we don't want to repeat the - * searching and mounting. Even if it is not found, see [62019f8aa9f5ec73]. - */ - - if (zipfs_tcl_library_init) { - if (!zipfs_literal_tcl_library) { - return NULL; - } - return ScriptLibrarySetup(zipfs_literal_tcl_library); - } + assert(!zipfs_tcl_library_init); /* * Look for the library file system within the executable. @@ -4380,7 +4370,8 @@ TclZipfs_TclLibrary(void) Tcl_DecrRefCount(vfsInitScript); if (found == TCL_OK) { zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library"; - return ScriptLibrarySetup(zipfs_literal_tcl_library); + zipfs_tcl_library_init = 1; + return TCL_OK; } /* @@ -4399,17 +4390,20 @@ TclZipfs_TclLibrary(void) #endif if (ZipfsAppHookFindTclInit(dllName) == TCL_OK) { - return ScriptLibrarySetup(zipfs_literal_tcl_library); + zipfs_tcl_library_init = 1; + return TCL_OK; } #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); + zipfs_tcl_library_init = 1; + return TCL_OK; } #else if (ZipfsAppHookFindTclInit(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) { - return ScriptLibrarySetup(zipfs_literal_tcl_library); + zipfs_tcl_library_init = 1; + return TCL_OK; } #endif /* _WIN32 */ #endif /* !defined(STATIC_BUILD) */ @@ -4420,13 +4414,27 @@ TclZipfs_TclLibrary(void) */ if (zipfs_literal_tcl_library) { - return ScriptLibrarySetup(zipfs_literal_tcl_library); + return TCL_OK; } /* * No zipfs tcl-library, mark it to avoid performance penalty [62019f8aa9f5ec73], * by future calls (child interpreters, threads, etc). */ zipfs_tcl_library_init = 1; + return TCL_ERROR; +} + +Tcl_Obj * +TclZipfs_TclLibrary(void) +{ + /* + * Assumes TclZipfsLocateTclLibrary has already been called at startup + * through Tcl_InitSubsystems. + */ + assert(zipfs_tcl_library_init); + if (zipfs_literal_tcl_library) { + return ScriptLibrarySetup(zipfs_literal_tcl_library); + } return NULL; } @@ -6529,8 +6537,9 @@ TclZipfs_AppHook( /* * Look for init.tcl in one of the locations mounted later in this - * function. + * function. Errors ignored as other locations may be available. */ + (void) TclZipfsLocateTclLibrary(); if (!TclZipfs_Mount(NULL, archive, ZIPFS_APP_MOUNT, NULL)) { int found; -- cgit v0.12 From b6b37b7c74507c13588740959a178a19f4290469 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sun, 3 Aug 2025 12:07:40 +0000 Subject: Delete dead code --- generic/tclZipfs.c | 60 +++++++++++++++--------------------------------------- 1 file changed, 16 insertions(+), 44 deletions(-) diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index 4853376..8eacf41 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -414,7 +414,6 @@ static int InitWritableChannel(Tcl_Interp *interp, static int ListMountPoints(Tcl_Interp *interp); static int ContainsMountPoint(const char *path, int pathLen); static void CleanupMount(ZipFile *zf); -static Tcl_Obj * ScriptLibrarySetup(const char *dirName); static void SerializeCentralDirectoryEntry( const unsigned char *start, const unsigned char *end, unsigned char *buf, @@ -4303,48 +4302,6 @@ ZipFSListObjCmd( return TCL_OK; } -/* - *------------------------------------------------------------------------- - * - * TclZipfs_TclLibrary -- - * - * This procedure gets (and possibly finds) the root that Tcl's library - * files are mounted under. - * - * Results: - * A Tcl object holding the location (with zero refcount), or NULL if no - * Tcl library can be found. - * - * Side effects: - * May initialise the cache of where such library files are to be found. - * This cache is never cleared. - * - *------------------------------------------------------------------------- - */ - -/* Utility routine to centralize housekeeping */ -static Tcl_Obj * -ScriptLibrarySetup( - const char *dirName) -{ - Tcl_Obj *libDirObj = Tcl_NewStringObj(dirName, -1); - Tcl_Obj *subDirObj, *searchPathObj; - - TclNewLiteralStringObj(subDirObj, "encoding"); - Tcl_IncrRefCount(subDirObj); - TclNewObj(searchPathObj); - Tcl_ListObjAppendElement(NULL, searchPathObj, - Tcl_FSJoinToPath(libDirObj, 1, &subDirObj)); - Tcl_DecrRefCount(subDirObj); - Tcl_IncrRefCount(searchPathObj); - Tcl_SetEncodingSearchPath(searchPathObj); - Tcl_DecrRefCount(searchPathObj); - /* Bug [fccb9f322f]. Reinit system encoding after setting search path */ - TclpSetInitialEncodings(); - zipfs_tcl_library_init = 1; - return libDirObj; -} - int TclZipfsLocateTclLibrary(void) { @@ -4424,6 +4381,21 @@ TclZipfsLocateTclLibrary(void) return TCL_ERROR; } +/* + *------------------------------------------------------------------------- + * + * TclZipfs_TclLibrary -- + * + * This procedure gets the root that Tcl's library + * files are mounted under if they are under a zipfs file system. + * + * Results: + * A Tcl object holding the location (with zero refcount), or NULL if no + * Tcl library can be found. + * + *------------------------------------------------------------------------- + */ + Tcl_Obj * TclZipfs_TclLibrary(void) { @@ -4433,7 +4405,7 @@ TclZipfs_TclLibrary(void) */ assert(zipfs_tcl_library_init); if (zipfs_literal_tcl_library) { - return ScriptLibrarySetup(zipfs_literal_tcl_library); + return Tcl_NewStringObj(zipfs_literal_tcl_library, -1); } return NULL; } -- cgit v0.12 From 4d20eb490b1a3c5c547b93f2f54fb0bd4a3df4f7 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sun, 3 Aug 2025 14:01:28 +0000 Subject: Protect zipfs location with lock --- generic/tclZipfs.c | 77 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index 8eacf41..7d3e6e8 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -646,6 +646,13 @@ ZipWriteShort( } /* + * Need a separate mutex for locating libraries because the search calls + * TclZipfs_Mount which takes out a write lock on the ZipFSMutex. Since + * those cannot be nested, we need a separate mutex. + */ +TCL_DECLARE_MUTEX(ZipFSLocateLibMutex) + +/* *------------------------------------------------------------------------- * * ReadLock, WriteLock, Unlock -- @@ -4302,6 +4309,22 @@ ZipFSListObjCmd( return TCL_OK; } +/* + * TclZipfsLocateTclLibrary -- + * + * This procedure locates the root that Tcl's library files are mounted + * under if they are under a zipfs file system. + * + * Results: + * TCL_OK if the library was found, TCL_ERROR otherwise. + * + * Side effects: + * Initializes the global variable zipfs_literal_tcl_library. Will + * never be cleared. + * + *------------------------------------------------------------------------- + */ + int TclZipfsLocateTclLibrary(void) { @@ -4314,28 +4337,33 @@ TclZipfsLocateTclLibrary(void) char dllName[(MAX_PATH + LIBRARY_SIZE) * 3]; #endif /* _WIN32 */ - assert(!zipfs_tcl_library_init); + if (zipfs_tcl_library_init) { + return zipfs_literal_tcl_library ? TCL_OK : TCL_ERROR; + } - /* - * Look for the library file system within the executable. - */ + Tcl_MutexLock(&ZipFSLocateLibMutex); + if (zipfs_tcl_library_init) { + /* Some other thread won the race */ + Tcl_MutexUnlock(&ZipFSLocateLibMutex); + return zipfs_literal_tcl_library ? TCL_OK : TCL_ERROR; + } - vfsInitScript = Tcl_NewStringObj(ZIPFS_APP_MOUNT "/tcl_library/init.tcl", - -1); + /* Look for the library file system within the executable. */ + vfsInitScript = + Tcl_NewStringObj(ZIPFS_APP_MOUNT "/tcl_library/init.tcl", -1); Tcl_IncrRefCount(vfsInitScript); found = Tcl_FSAccess(vfsInitScript, F_OK); Tcl_DecrRefCount(vfsInitScript); if (found == TCL_OK) { zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library"; - zipfs_tcl_library_init = 1; - return TCL_OK; + goto unlock_and_return; } /* - * Look for the library file system within the DLL/shared library. Note - * that we must mount the zip file and dll before releasing to search. + * Look for the library file system within the DLL/shared + * library. Note that we must mount the zip file and dll before + * releasing to search. */ - #if !defined(STATIC_BUILD) #if defined(_WIN32) || defined(__CYGWIN__) hModule = (HMODULE)TclWinGetTclInstance(); @@ -4347,38 +4375,26 @@ TclZipfsLocateTclLibrary(void) #endif if (ZipfsAppHookFindTclInit(dllName) == TCL_OK) { - zipfs_tcl_library_init = 1; - return TCL_OK; + goto unlock_and_return; } #elif !defined(NO_DLFCN_H) Dl_info dlinfo; if (dladdr((const void *)TclZipfs_TclLibrary, &dlinfo) && (dlinfo.dli_fname != NULL) && (ZipfsAppHookFindTclInit(dlinfo.dli_fname) == TCL_OK)) { - zipfs_tcl_library_init = 1; - return TCL_OK; + goto unlock_and_return; } #else if (ZipfsAppHookFindTclInit(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) { zipfs_tcl_library_init = 1; - return TCL_OK; + goto unlock_and_return; } #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_OK; - } - /* - * No zipfs tcl-library, mark it to avoid performance penalty [62019f8aa9f5ec73], - * by future calls (child interpreters, threads, etc). - */ +unlock_and_return: zipfs_tcl_library_init = 1; - return TCL_ERROR; + Tcl_MutexUnlock(&ZipFSLocateLibMutex); + return zipfs_literal_tcl_library ? TCL_OK : TCL_ERROR; } /* @@ -6506,12 +6522,11 @@ TclZipfs_AppHook( #endif archive = Tcl_GetNameOfExecutable(); TclZipfs_Init(NULL); - /* * Look for init.tcl in one of the locations mounted later in this * function. Errors ignored as other locations may be available. */ - (void) TclZipfsLocateTclLibrary(); + (void)TclZipfsLocateTclLibrary(); if (!TclZipfs_Mount(NULL, archive, ZIPFS_APP_MOUNT, NULL)) { int found; -- cgit v0.12 From 0a57b1e0c760a17b280d00ca3dae8d71c0b4bc7f Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sun, 3 Aug 2025 15:07:31 +0000 Subject: Delete extraneous redundant line --- generic/tclZipfs.c | 1 - 1 file changed, 1 deletion(-) diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index 7d3e6e8..da59cf9 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -4385,7 +4385,6 @@ TclZipfsLocateTclLibrary(void) } #else if (ZipfsAppHookFindTclInit(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) { - zipfs_tcl_library_init = 1; goto unlock_and_return; } #endif /* _WIN32 */ -- cgit v0.12 From 7c308a99f761051b2e32d252e5cafe99d7b6fe37 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sun, 3 Aug 2025 17:42:28 +0000 Subject: Re-fix [fccb9f322f]. Also eliminate bumping of file system epoch on every interp creation introduced in Tcl 9 --- generic/tclInterp.c | 1 - generic/tclZipfs.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/generic/tclInterp.c b/generic/tclInterp.c index 90af06e..b778314 100644 --- a/generic/tclInterp.c +++ b/generic/tclInterp.c @@ -466,7 +466,6 @@ Tcl_Init( " }\n" "}\n" "tclInit", TCL_INDEX_NONE, 0); - TclpSetInitialEncodings(); end: *names = (*names)->nextPtr; return result; diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index da59cf9..bb27ae9 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -6489,6 +6489,37 @@ TclZipfsFinalize(void) } /* + * TclZipfsInitEncodingDirs -- + * + * Sets the encoding directory search path to the encoding directory + * under the tcl_library directory within a ZipFS mount. Overwrites the + * previously set encoding search path so only to be called at + * initialization. + */ +static int +TclZipfsInitEncodingDirs(void) +{ + if (zipfs_literal_tcl_library == NULL) { + return TCL_ERROR; + } + Tcl_Obj *libDirObj = Tcl_NewStringObj(zipfs_literal_tcl_library, -1); + Tcl_Obj *subDirObj, *searchPathObj; + + TclNewLiteralStringObj(subDirObj, "encoding"); + Tcl_IncrRefCount(subDirObj); + TclNewObj(searchPathObj); + Tcl_ListObjAppendElement(NULL, searchPathObj, + Tcl_FSJoinToPath(libDirObj, 1, &subDirObj)); + Tcl_DecrRefCount(subDirObj); + Tcl_IncrRefCount(searchPathObj); + Tcl_SetEncodingSearchPath(searchPathObj); + Tcl_DecrRefCount(searchPathObj); + /* Reinit system encoding after setting search path */ + TclpSetInitialEncodings(); + return TCL_OK; +} + +/* *------------------------------------------------------------------------- * * TclZipfs_AppHook -- @@ -6525,7 +6556,9 @@ TclZipfs_AppHook( * Look for init.tcl in one of the locations mounted later in this * function. Errors ignored as other locations may be available. */ - (void)TclZipfsLocateTclLibrary(); + if (TclZipfsLocateTclLibrary() == TCL_OK) { + (void) TclZipfsInitEncodingDirs(); + } if (!TclZipfs_Mount(NULL, archive, ZIPFS_APP_MOUNT, NULL)) { int found; -- cgit v0.12 From 8b2e59a8c83da300f868d1545a89616fbf6e9575 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Mon, 4 Aug 2025 09:45:38 +0000 Subject: Tweak test failing on macos to report macos result --- tests/unixInit.test | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tests/unixInit.test b/tests/unixInit.test index 899779c..2e797b7 100644 --- a/tests/unixInit.test +++ b/tests/unixInit.test @@ -123,18 +123,12 @@ test unixInit-3.2 {TclpSetInitialEncodings} -setup { puts $f {puts [encoding system]; exit} set enc [gets $f] close $f - set validEncodings [list euc-jp] - if {[string match HP-UX $tcl_platform(os)]} { - # Some older HP-UX systems need us to accept this as valid Bug 453883 - # reports that newer HP-UX systems report euc-jp like everybody else. - lappend validEncodings shiftjis - } - expr {$enc ni $validEncodings} + set enc } -cleanup { unset -nocomplain env(LANG) env(LC_ALL) catch {set env(LC_ALL) $oldlc_all} catch {set env(TCL_LIBRARY) $oldtcl_library} -} -result 0 +} -result {^(euc-jp|shiftjis)$} -match regexp test unixInit-4.1 {TclpSetVariables} {unix} { # just make sure they exist -- cgit v0.12 From 70efeebc57073f0b74fd559fb63f4c4b4fb4ba97 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 4 Aug 2025 15:40:20 +0000 Subject: more tests to cover issue [5137b4387019d0e1] - ensure cache of base is correct for :localtime (system TZ) if TZ-env changing (if there is no registry) --- tests/clock.test | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/clock.test b/tests/clock.test index c932837..24c7a7d 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -36974,6 +36974,55 @@ test clock-38.3fm {ensure cache of base is correct for :localtime if TZ-env chan } \ -result {{1970-01-02T07:30:00 +1130} {1970-01-02T03:30:00 +0730} {1970-01-01T23:30:00 +0330} {1970-01-01T20:00:00 +0000}} +test clock-38.4sc {ensure cache of base is correct for :localtime if TZ-env changing / scan (system TZ, no registry)} \ + -setup { + ::testClock::_setupRegistry + # simulate we have no registry, so system TZ and :localtime get +HHMM format + proc ::tcl::clock::_hasRegistry {} {return 0} + } -body { + # force epoch switch and set first TZ (a time zone that is unlikely to anywhere) and use :localtime + set env(TZ) "+03:20" + clock scan "12:00:00" -format "%H:%M:%S" -base [expr {20*60*60}] -timezone :localtime -locale en + # force epoch switch, with unset TZ, it shall be system timezone now + unset -nocomplain env(TZ) + set t1 [clock scan "12:00:00" -format "%H:%M:%S" -base [expr {20*60*60}] -locale en] + # force epoch switch and set another TZ (a time zone that is unlikely to anywhere) and use system timezone + set env(TZ) "+04:20" + set t2 [clock scan "12:00:00" -format "%H:%M:%S" -base [expr {20*60*60}] -locale en] + # force epoch switch, with unset TZ, it shall be again system timezone + unset -nocomplain env(TZ) + set t3 [clock scan "12:00:00" -format "%H:%M:%S" -base [expr {20*60*60}] -locale en] + # compare scanned values (t1 must be equal t3 and not equal t2): + list [expr {$t1 == $t3 && $t1 != $t2}] [subst {$t1 == $t3 && $t1 != $t2}] + } -cleanup { + unset -nocomplain env(TZ) + ::testClock::_cleanupRegistry + } -match glob -result {1 *} +test clock-38.4fm {ensure cache of base is correct for :localtime if TZ-env changing / format (system TZ, no registry)} \ + -setup { + ::testClock::_setupRegistry + # simulate we have no registry, so system TZ and :localtime get +HHMM format + proc ::tcl::clock::_hasRegistry {} {return 0} + } -body { + # force epoch switch and set first TZ (a time zone that is unlikely to anywhere) and use :localtime + set env(TZ) "+03:20" + clock format 0 -timezone :localtime -locale en + # force epoch switch, with unset TZ, it shall be system timezone now + unset -nocomplain env(TZ) + set t1 [clock format 0 -locale en] + # force epoch switch and set another TZ (a time zone that is unlikely to anywhere) and use system timezone + set env(TZ) "+04:20" + set t2 [clock format 0 -locale en] + # force epoch switch, with unset TZ, it shall be again system timezone + unset -nocomplain env(TZ) + set t3 [clock format 0 -locale en] + # compare formatted values (t1 must be equal t3 and not equal t2): + list [expr {$t1 eq $t3 && $t1 ne $t2}] [subst {"$t1" eq "$t3" && "$t1" ne "$t2"}] + } -cleanup { + unset -nocomplain env(TZ) + ::testClock::_cleanupRegistry + } -match glob -result {1 *} + test clock-39.1 {regression - synonym timezones} { clock format 0 -format {%H:%M:%S} -timezone :US/Eastern } {19:00:00} -- cgit v0.12 From eb1fba12e2552be1c75e7c53bf69ff88cbe28b05 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Wed, 6 Aug 2025 02:06:11 +0000 Subject: Reintroduce TclpSetInitialEncoding for --disable-zipfs case --- generic/tclInterp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/generic/tclInterp.c b/generic/tclInterp.c index b778314..90af06e 100644 --- a/generic/tclInterp.c +++ b/generic/tclInterp.c @@ -466,6 +466,7 @@ Tcl_Init( " }\n" "}\n" "tclInit", TCL_INDEX_NONE, 0); + TclpSetInitialEncodings(); end: *names = (*names)->nextPtr; return result; -- cgit v0.12 From e1d9fc8bc199e1673586a9a4768a775e5ecf3c64 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Wed, 6 Aug 2025 02:17:47 +0000 Subject: Only update file system epoch if system encoding changes --- generic/tclEncoding.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index ce5fda4..d3914da 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -969,9 +969,11 @@ Tcl_GetEncodingNulLength( * unless interp was NULL. * * Side effects: - * The reference count of the new system encoding is incremented. The - * reference count of the old system encoding is decremented and it may - * be freed. All VFS cached information is invalidated. + * If the passed encoding is the same as the current system + * encoding, the call is effectively a no-op. Otherwise, the reference + * count of the new system encoding is incremented. The reference count + * of the old system encoding is decremented and it may be freed. All + * VFS cached information is invalidated. * *------------------------------------------------------------------------ */ @@ -983,25 +985,34 @@ Tcl_SetSystemEncoding( * to reset to default encoding. */ { Tcl_Encoding encoding; - Encoding *encodingPtr; - if (!name || !*name) { - Tcl_MutexLock(&encodingMutex); - encoding = defaultEncoding; - encodingPtr = (Encoding *) encoding; - encodingPtr->refCount++; - Tcl_MutexUnlock(&encodingMutex); + Tcl_MutexLock(&encodingMutex); + if (name == NULL || name[0] == '\0') { + if (defaultEncoding == systemEncoding) { + Tcl_MutexUnlock(&encodingMutex); + return TCL_OK; + } + encoding = defaultEncoding; + ((Encoding *)encoding)->refCount += 1; } else { encoding = Tcl_GetEncoding(interp, name); + if (encoding == systemEncoding) { + FreeEncoding(encoding); + Tcl_MutexUnlock(&encodingMutex); + return TCL_OK; + } if (encoding == NULL) { + Tcl_MutexUnlock(&encodingMutex); return TCL_ERROR; } } - Tcl_MutexLock(&encodingMutex); + assert(encoding != systemEncoding); FreeEncoding(systemEncoding); systemEncoding = encoding; Tcl_MutexUnlock(&encodingMutex); + + /* Checks above ensure this is only called when system encoding changes */ Tcl_FSMountsChanged(NULL); return TCL_OK; -- cgit v0.12 From d702f1dcba8ac99d9db55f5999e1b373f43165eb Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 12 Aug 2025 10:23:07 +0000 Subject: Proposed fix for [31d4fa115b]: Tweak install permissions --- unix/Makefile.in | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/unix/Makefile.in b/unix/Makefile.in index 18b943a..6145e0c 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -154,8 +154,8 @@ INSTALL_STRIP_PROGRAM = strip INSTALL_STRIP_LIBRARY = strip -x INSTALL = $(SHELL) $(UNIX_DIR)/install-sh -c -INSTALL_PROGRAM = ${INSTALL} -INSTALL_LIBRARY = ${INSTALL} +INSTALL_PROGRAM = ${INSTALL} -m 755 +INSTALL_LIBRARY = ${INSTALL} -m 755 INSTALL_DATA = ${INSTALL} -m 644 INSTALL_DATA_DIR = ${INSTALL} -d -m 755 @@ -812,7 +812,6 @@ install-binaries: binaries done @echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/" @@INSTALL_LIB@ - @chmod 555 "$(DLL_INSTALL_DIR)/$(LIB_FILE)" @echo "Installing ${TCL_EXE} as $(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}" @$(INSTALL_PROGRAM) ${TCL_EXE} "$(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}" @echo "Installing tclConfig.sh to $(CONFIG_INSTALL_DIR)/" -- cgit v0.12 From f2fa51ec7342e4e4e484996e5300cccc64b17255 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 13 Aug 2025 08:57:05 +0000 Subject: Update changes.md --- changes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changes.md b/changes.md index 530fd14..5bee6fc 100644 --- a/changes.md +++ b/changes.md @@ -10,7 +10,8 @@ Tcl patch releases have the primary purpose of delivering bug fixes to the userbase. # Bug fixes - - [On Unix, IsTimeNative() always defined but not always used](https://core.tcl-lang.org/tcl/tktview/6b8e3) + - [On Unix, IsTimeNative() always defined but not always used](https://core.tcl-lang.org/tcl/tktview/6b8e39) + - [Tweak install permissions](https://core.tcl-lang.org/tcl/tktview/31d4fa) # Updated bundled packages, libraries, standards, data - sqlite3 3.50.2 -- cgit v0.12 From 4b6e6f5c2c1a3861f2f74d195c6f2a8f1d2698db Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 13 Aug 2025 10:38:41 +0000 Subject: Remove another check for TCL_MINOR_VERSION < 7 --- unix/tclAppInit.c | 6 ++---- win/tclAppInit.c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/unix/tclAppInit.c b/unix/tclAppInit.c index 2a20dc1..761cc57 100644 --- a/unix/tclAppInit.c +++ b/unix/tclAppInit.c @@ -14,13 +14,11 @@ #include "tcl.h" #if TCL_MAJOR_VERSION < 9 -# if defined(USE_TCL_STUBS) +# if defined(USE_TCL_STUBS) # error "Don't build with USE_TCL_STUBS!" -# endif -# if TCL_MINOR_VERSION < 7 +# endif # define Tcl_LibraryInitProc Tcl_PackageInitProc # define Tcl_StaticLibrary Tcl_StaticPackage -# endif #endif #ifdef TCL_TEST diff --git a/win/tclAppInit.c b/win/tclAppInit.c index 326d054..6ba50a7 100644 --- a/win/tclAppInit.c +++ b/win/tclAppInit.c @@ -16,13 +16,11 @@ #include "tcl.h" #if TCL_MAJOR_VERSION < 9 -# if defined(USE_TCL_STUBS) +# if defined(USE_TCL_STUBS) # error "Don't build with USE_TCL_STUBS!" -# endif -# if TCL_MINOR_VERSION < 7 +# endif # define Tcl_LibraryInitProc Tcl_PackageInitProc # define Tcl_StaticLibrary Tcl_StaticPackage -# endif #endif #ifdef TCL_TEST -- cgit v0.12 From 234032f0053f594cfbddc14f56bffb6e03d45d78 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 13 Aug 2025 16:43:39 +0000 Subject: Remove more references to version 8.7 --- generic/tcl.decls | 2 +- generic/tcl.h | 9 +-------- generic/tclDecls.h | 4 ++-- generic/tclOODecls.h | 2 +- generic/tclStringObj.c | 4 ++-- generic/tclTest.c | 2 +- generic/tclTestABSList.c | 4 ++-- generic/tclTestObj.c | 6 +++--- win/makefile.vc | 4 ++-- 9 files changed, 15 insertions(+), 22 deletions(-) diff --git a/generic/tcl.decls b/generic/tcl.decls index d72786b..d225050 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -2379,7 +2379,7 @@ declare 689 { void Tcl_SetWideUIntObj(Tcl_Obj *objPtr, Tcl_WideUInt uwideValue) } -# ----- BASELINE -- FOR -- 8.7.0 / 9.0.0 ----- # +# ----- BASELINE -- FOR -- 9.0.0 ----- # declare 690 { void TclUnusedStubEntry(void) diff --git a/generic/tcl.h b/generic/tcl.h index 9154ee7..e6f0f7f 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2105,7 +2105,7 @@ typedef struct Tcl_EncodingType { * reflected in regcustom.h. */ -#if TCL_UTF_MAX == 4 +#if TCL_UTF_MAX == 4 && TCL_MAJOR_VERSION > 8 /* * int isn't 100% accurate as it should be a strict 4-byte value * (perhaps int32_t). ILP64/SILP64 systems may have troubles. The @@ -2334,17 +2334,10 @@ void * TclStubCall(void *arg); #ifdef USE_TCL_STUBS #if TCL_MAJOR_VERSION < 9 -# if TCL_UTF_MAX < 4 # define Tcl_InitStubs(interp, version, exact) \ (Tcl_InitStubs)(interp, version, \ (exact)|(TCL_MAJOR_VERSION<<8)|(0xFF<<16), \ TCL_STUB_MAGIC) -# else -# define Tcl_InitStubs(interp, version, exact) \ - (Tcl_InitStubs)(interp, "8.7b1", \ - (exact)|(TCL_MAJOR_VERSION<<8)|(0xFF<<16), \ - TCL_STUB_MAGIC) -# endif #else # define Tcl_InitStubs(interp, version, exact) \ (Tcl_InitStubs)(interp, version, \ diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 483a735..473ff9b 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4198,7 +4198,7 @@ extern const TclStubs *tclStubsPtr; #undef TclGetAliasObj #if TCL_MAJOR_VERSION < 9 - /* TIP #627 for 8.7 */ + /* TIP #627 */ # undef Tcl_CreateObjCommand2 # define Tcl_CreateObjCommand2 Tcl_CreateObjCommand # undef Tcl_CreateObjTrace2 @@ -4207,7 +4207,7 @@ extern const TclStubs *tclStubsPtr; # define Tcl_NRCreateCommand2 Tcl_NRCreateCommand # undef Tcl_NRCallObjProc2 # define Tcl_NRCallObjProc2 Tcl_NRCallObjProc - /* TIP #660 for 8.7 */ + /* TIP #660 */ # undef Tcl_GetSizeIntFromObj # define Tcl_GetSizeIntFromObj Tcl_GetIntFromObj diff --git a/generic/tclOODecls.h b/generic/tclOODecls.h index 68c5b2b..e855e69 100644 --- a/generic/tclOODecls.h +++ b/generic/tclOODecls.h @@ -271,7 +271,7 @@ extern const TclOOStubs *tclOOStubsPtr; /* !END!: Do not edit above this line. */ #if TCL_MAJOR_VERSION < 9 - /* TIP #630 for 8.7 */ + /* TIP #630 */ # undef Tcl_MethodIsType2 # define Tcl_MethodIsType2 Tcl_MethodIsType # undef Tcl_NewInstanceMethod2 diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 2b0fbd7..76ad05e 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -391,7 +391,7 @@ Tcl_GetCharLength( * Optimize the case where we're really dealing with a byte-array object; * we don't need to convert to a string to perform the get-length operation. * - * Starting in Tcl 8.7, we check for a "pure" byte-array, because the + * Starting in Tcl 9.0, we check for a "pure" byte-array, because the * machinery behind that test is using a proper byte-array ObjType. We * could also compute length of an improper byte-array without shimmering * but there's no value in that. We *want* to shimmer an improper byte-array @@ -442,7 +442,7 @@ TclGetCharLength( * Optimize the case where we're really dealing with a byte-array object; * we don't need to convert to a string to perform the get-length operation. * - * Starting in Tcl 8.7, we check for a "pure" byte-array, because the + * Starting in Tcl 9.0, we check for a "pure" byte-array, because the * machinery behind that test is using a proper byte-array ObjType. We * could also compute length of an improper byte-array without shimmering * but there's no value in that. We *want* to shimmer an improper byte-array diff --git a/generic/tclTest.c b/generic/tclTest.c index e6c2a94..441b11f 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -528,7 +528,7 @@ TestCommonInit( { Tcl_CmdInfo info; - if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) { + if (Tcl_InitStubs(interp, "9.0-", 0) == NULL) { return TCL_ERROR; } if (Tcl_GetCommandInfo(interp, "::tcl::build-info", &info)) { diff --git a/generic/tclTestABSList.c b/generic/tclTestABSList.c index 8e306c6..f74e224 100644 --- a/generic/tclTestABSList.c +++ b/generic/tclTestABSList.c @@ -1204,7 +1204,7 @@ lGenObjCmd( * lgen package init */ int Lgen_Init(Tcl_Interp *interp) { - if (Tcl_InitStubs(interp, "8.7", 0) == NULL) { + if (Tcl_InitStubs(interp, "9.0-", 0) == NULL) { return TCL_ERROR; } Tcl_CreateObjCommand(interp, "lgen", lGenObjCmd, NULL, NULL); @@ -1247,7 +1247,7 @@ int Lgen_Init(Tcl_Interp *interp) { */ int Tcl_ABSListTest_Init(Tcl_Interp *interp) { - if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) { + if (Tcl_InitStubs(interp, "9.0-", 0) == NULL) { return TCL_ERROR; } Tcl_CreateObjCommand(interp, "lstring", lLStringObjCmd, NULL, NULL); diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index f73483b..4f5ba35 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -105,7 +105,7 @@ TclObjTest_Init( Tcl_Obj **varPtr; #ifndef TCL_WITH_EXTERNAL_TOMMATH - if (Tcl_TomMath_InitStubs(interp, "8.7-") == NULL) { + if (Tcl_TomMath_InitStubs(interp, "9.0-") == NULL) { return TCL_ERROR; } #endif @@ -853,8 +853,8 @@ TestintobjCmd( * 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 + * Following new commands are added for 9.0 as regression tests for + * memory leaks and use-after-free. Unlike 8.6, 9.0 has multiple internal * representations for lists. It has to be ensured that corresponding * implementations obey the invariants of the C list API. The script * level tests do not suffice as Tcl list commands do not execute diff --git a/win/makefile.vc b/win/makefile.vc index 175c4b2..ae859ba 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -152,14 +152,14 @@ TCLLIBRAW=$(TCLLIB:.dll=-raw.dll) DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION) VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION) -# The staticpkg option is not longer supported in Tcl 8.7 +# The staticpkg option is not longer supported in Tcl 9.0 # though extensions may still be using it. If specified together # with "static", ignore it as that is now the default for # static build. For non-static builds, no longer supported # now (was permitted in 8.6) !if $(TCL_USE_STATIC_PACKAGES) !if $(STATIC_BUILD) -!message *** NOTE: The "staticpkg" option redundant in 8.7. +!message *** NOTE: The "staticpkg" option redundant in 9.0. !else !message *** NOTE: The "staticpkg" option ignored for shared library builds. !endif -- cgit v0.12 From 2e55b5dd3a4ccf509c744ab8ed13b4547807a697 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 13 Aug 2025 21:03:13 +0000 Subject: When compiling for Tcl 8.6, make Tcl 9-specific API unavailable. --- generic/tclDecls.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 473ff9b..7ce3ac8 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4244,6 +4244,32 @@ extern const TclStubs *tclStubsPtr; # undef Tcl_GetAliasObj # define Tcl_GetAliasObj(interp, childCmd, targetInterpPtr, targetCmdPtr, objcPtr, objv) \ tclStubsPtr->tclGetAliasObj((interp), (childCmd), (targetInterpPtr), (targetCmdPtr), (objcPtr), (objv)) +# undef Tcl_OpenTcpServerEx +# undef TclZipfs_Mount +# undef TclZipfs_Unmount +# undef TclZipfs_TclLibrary +# undef TclZipfs_MountBuffer +# undef Tcl_FreeInternalRep +# undef Tcl_InitStringRep +# undef Tcl_FetchInternalRep +# undef Tcl_StoreInternalRep +# undef Tcl_HasStringRep +# undef Tcl_LinkArray +# undef Tcl_GetIntForIndex +# undef Tcl_FSTildeExpand +# undef Tcl_ExternalToUtfDStringEx +# undef Tcl_UtfToExternalDStringEx +# undef Tcl_AsyncMarkFromSignal +# undef Tcl_GetBool +# undef Tcl_GetBoolFromObj +# undef Tcl_GetNumberFromObj +# undef Tcl_GetNumber +# undef Tcl_RemoveChannelMode +# undef Tcl_GetEncodingNulLength +# undef Tcl_GetWideUIntFromObj +# undef Tcl_DStringToObj +# undef Tcl_NewWideUIntObj +# undef Tcl_SetWideUIntObj #elif defined(TCL_8_API) # undef Tcl_GetByteArrayFromObj # undef Tcl_GetBytesFromObj -- cgit v0.12 From 8796676d527ab66900f21ea345bcea15bec74f28 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Aug 2025 08:28:13 +0000 Subject: Better not use the old octal notation (even though it still works) --- generic/tclIOUtil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index a488537..124485c 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -3309,14 +3309,14 @@ Tcl_LoadFile( /* * It might be necessary on some systems to set the appropriate permissions * on the file. On Unix we could loop over the file attributes and set any - * that are called "-permissions" to 0700, but just do it directly instead: + * that are called "-permissions" to 0o700, but just do it directly instead: */ { int index; Tcl_Obj *perm; - TclNewLiteralStringObj(perm, "0700"); + TclNewLiteralStringObj(perm, "0o700"); Tcl_IncrRefCount(perm); if (TclFSFileAttrIndex(copyToPtr, "-permissions", &index) == TCL_OK) { Tcl_FSFileAttrsSet(NULL, index, copyToPtr, perm); -- cgit v0.12 From ac81afab4fc765d007215a6c20a8cce7e3e02cca Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Aug 2025 11:49:57 +0000 Subject: Fixed inconsistent indenting, introduced [0433b67adc|here]. See also [87b69745be] --- generic/tclEncoding.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index d3914da..43566ce 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -988,21 +988,21 @@ Tcl_SetSystemEncoding( Tcl_MutexLock(&encodingMutex); if (name == NULL || name[0] == '\0') { - if (defaultEncoding == systemEncoding) { - Tcl_MutexUnlock(&encodingMutex); - return TCL_OK; - } - encoding = defaultEncoding; - ((Encoding *)encoding)->refCount += 1; + if (defaultEncoding == systemEncoding) { + Tcl_MutexUnlock(&encodingMutex); + return TCL_OK; + } + encoding = defaultEncoding; + ((Encoding *)encoding)->refCount += 1; } else { encoding = Tcl_GetEncoding(interp, name); - if (encoding == systemEncoding) { - FreeEncoding(encoding); - Tcl_MutexUnlock(&encodingMutex); - return TCL_OK; - } + if (encoding == systemEncoding) { + FreeEncoding(encoding); + Tcl_MutexUnlock(&encodingMutex); + return TCL_OK; + } if (encoding == NULL) { - Tcl_MutexUnlock(&encodingMutex); + Tcl_MutexUnlock(&encodingMutex); return TCL_ERROR; } } -- cgit v0.12 From aa6bf4e80b76e982484466939bd7b8845e1b3731 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Aug 2025 13:23:27 +0000 Subject: platform version => 1.0.20 --- library/platform/pkgIndex.tcl | 2 +- library/platform/platform.tcl | 2 +- unix/Makefile.in | 4 ++-- win/Makefile.in | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/platform/pkgIndex.tcl b/library/platform/pkgIndex.tcl index 4526c7e..20750be 100644 --- a/library/platform/pkgIndex.tcl +++ b/library/platform/pkgIndex.tcl @@ -1,3 +1,3 @@ -package ifneeded platform 1.0.19 [list source -encoding utf-8 [file join $dir platform.tcl]] +package ifneeded platform 1.0.20 [list source -encoding utf-8 [file join $dir platform.tcl]] package ifneeded platform::shell 1.1.4 [list source -encoding utf-8 [file join $dir shell.tcl]] diff --git a/library/platform/platform.tcl b/library/platform/platform.tcl index 4988fbd..b142ed1 100644 --- a/library/platform/platform.tcl +++ b/library/platform/platform.tcl @@ -466,7 +466,7 @@ proc ::platform::patterns {id} { # ### ### ### ######### ######### ######### ## Ready -package provide platform 1.0.19 +package provide platform 1.0.20 # ### ### ### ######### ######### ######### ## Demo application diff --git a/unix/Makefile.in b/unix/Makefile.in index 3efdfec..886606d 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -875,9 +875,9 @@ install-libraries: libraries @echo "Installing package tcltest 2.5.10 as a Tcl Module" @$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl \ "$(MODULE_INSTALL_DIR)/8.5/tcltest-2.5.10.tm" - @echo "Installing package platform 1.0.19 as a Tcl Module" + @echo "Installing package platform 1.0.20 as a Tcl Module" @$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl \ - "$(MODULE_INSTALL_DIR)/8.4/platform-1.0.19.tm" + "$(MODULE_INSTALL_DIR)/8.4/platform-1.0.20.tm" @echo "Installing package platform::shell 1.1.4 as a Tcl Module" @$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl \ "$(MODULE_INSTALL_DIR)/8.4/platform/shell-1.1.4.tm" diff --git a/win/Makefile.in b/win/Makefile.in index 6b06e2e..4daa827 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -758,8 +758,8 @@ install-libraries: libraries install-tzdata install-msgs @$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl "$(MODULE_INSTALL_DIR)/8.5/msgcat-1.6.1.tm"; @echo "Installing package tcltest 2.5.10 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl "$(MODULE_INSTALL_DIR)/8.5/tcltest-2.5.10.tm"; - @echo "Installing package platform 1.0.19 as a Tcl Module"; - @$(COPY) $(ROOT_DIR)/library/platform/platform.tcl "$(MODULE_INSTALL_DIR)/8.4/platform-1.0.19.tm"; + @echo "Installing package platform 1.0.20 as a Tcl Module"; + @$(COPY) $(ROOT_DIR)/library/platform/platform.tcl "$(MODULE_INSTALL_DIR)/8.4/platform-1.0.20.tm"; @echo "Installing package platform::shell 1.1.4 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/platform/shell.tcl "$(MODULE_INSTALL_DIR)/8.4/platform/shell-1.1.4.tm"; @echo "Installing encodings"; -- cgit v0.12 From f963e962594b9a669b77981bae65fa865eca2934 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Aug 2025 13:27:23 +0000 Subject: Update changes --- changes | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/changes b/changes index 906130c..2639fc3 100644 --- a/changes +++ b/changes @@ -9419,4 +9419,7 @@ Many code fixes to avoid overflow or undefined behavior. Thanks chrstphrchvz. - Released 8.6.17, Aug 15, 2025 - details at https://core.tcl-lang.org/tcl/ - -- (to be) Released 8.6.17, Apr ??, 2026 - details at https://core.tcl-lang.org/tcl/ - +2025-08-18 (new) support for MacOS Tahoe (nijtmans) + => platform 1.0.20 + +- (to be) Released 8.6.18, Apr ??, 2026 - details at https://core.tcl-lang.org/tcl/ - -- cgit v0.12 From b166c166e76a0d2ec5d49f94b6fba90385eabab2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Aug 2025 13:56:44 +0000 Subject: Assume that - one day - MacOS 26.5 will be there --- library/platform/platform.tcl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/platform/platform.tcl b/library/platform/platform.tcl index b142ed1..8e97b94 100644 --- a/library/platform/platform.tcl +++ b/library/platform/platform.tcl @@ -366,6 +366,17 @@ proc ::platform::patterns {id} { foreach {major minor} [split $v .] break set res {} + if {$major gt 26} { + # Add x.0 to x.minor to patterns. + for {set j $minor} {$j >= 0} {incr j -1} { + lappend res macosx${major}.${j}-${cpu} + foreach a $alt { + lappend res macosx${major}.${j}-$a + } + } + incr major -1 + set minor 5; # Assume that (major-1).5 will be there one day. + } if {$major eq 26} { # Add 26.0 to 26.minor to patterns. for {set j $minor} {$j >= 0} {incr j -1} { -- cgit v0.12 From a43258ca2779c25a13c9bf9fd4199a3c1fcafd3d Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Aug 2025 14:08:34 +0000 Subject: Let's not break it with Tcl 8.5 --- library/platform/platform.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/platform/platform.tcl b/library/platform/platform.tcl index 8e97b94..5a1a811 100644 --- a/library/platform/platform.tcl +++ b/library/platform/platform.tcl @@ -366,7 +366,7 @@ proc ::platform::patterns {id} { foreach {major minor} [split $v .] break set res {} - if {$major gt 26} { + if {$major ge 27} { # Add x.0 to x.minor to patterns. for {set j $minor} {$j >= 0} {incr j -1} { lappend res macosx${major}.${j}-${cpu} -- cgit v0.12 From 97e33af67f4179e1b17af0ed4801444034a917db Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Aug 2025 14:18:53 +0000 Subject: Oops, shouldn't use string compare here --- library/platform/platform.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/platform/platform.tcl b/library/platform/platform.tcl index 5a1a811..e6aeab1 100644 --- a/library/platform/platform.tcl +++ b/library/platform/platform.tcl @@ -366,7 +366,7 @@ proc ::platform::patterns {id} { foreach {major minor} [split $v .] break set res {} - if {$major ge 27} { + if {$major > 26} { # Add x.0 to x.minor to patterns. for {set j $minor} {$j >= 0} {incr j -1} { lappend res macosx${major}.${j}-${cpu} -- cgit v0.12 From 88f4b5757c89a525b25ca6834e954931bd4c00b2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 18 Aug 2025 21:49:35 +0000 Subject: Minor corrections, handle Tcl 9 platform reductions --- library/platform/platform.tcl | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/library/platform/platform.tcl b/library/platform/platform.tcl index e6aeab1..3bf1ff6 100644 --- a/library/platform/platform.tcl +++ b/library/platform/platform.tcl @@ -185,7 +185,10 @@ proc ::platform::identify {} { if {$major < 26} { incr major -10 } - append plat $major.[expr {$minor - 1}] + if {$major < 14} { + incr minor -1 + } + append plat $major.$minor } else { incr major -4 append plat 10.$major @@ -386,7 +389,7 @@ proc ::platform::patterns {id} { } } set major 15 - set minor 7 + set minor 6 } if {$major eq 15} { # Add 15.0 to 15.minor to patterns. @@ -397,7 +400,7 @@ proc ::platform::patterns {id} { } } set major 14 - set minor 8 + set minor 6 } if {$major eq 14} { # Add 14.0 to 14.minor to patterns. @@ -408,7 +411,7 @@ proc ::platform::patterns {id} { } } set major 13 - set minor 7 + set minor 5 } if {$major eq 13} { # Add 13.0 to 13.minor to patterns. @@ -419,7 +422,7 @@ proc ::platform::patterns {id} { } } set major 12 - set minor 7 + set minor 5 } if {$major eq 12} { # Add 12.0 to 12.minor to patterns. @@ -443,8 +446,8 @@ proc ::platform::patterns {id} { set major 10 set minor 15 } - # Add 10.5 to 10.minor to patterns. - for {set j $minor} {$j >= 5} {incr j -1} { + # Add 10.9 to 10.minor to patterns. + for {set j $minor} {$j >= 9} {incr j -1} { if {$cpu ne "arm"} { lappend res macosx${major}.${j}-${cpu} } @@ -452,11 +455,21 @@ proc ::platform::patterns {id} { lappend res macosx${major}.${j}-$a } } - - # Add unversioned patterns for 10.3/10.4 builds. - lappend res macosx-${cpu} - foreach a $alt { - lappend res macosx-$a + if {![package vsatisfies [package provide Tcl] 9.0-]} { + # Continue up to 10.5. + for {} {$j >= 5} {incr j -1} { + if {$cpu ne "arm"} { + lappend res macosx${major}.${j}-${cpu} + } + foreach a $alt { + lappend res macosx${major}.${j}-$a + } + } + # Add unversioned patterns for 10.3/10.4 builds. + lappend res macosx-${cpu} + foreach a $alt { + lappend res macosx-$a + } } } else { # No version, just do unversioned patterns. -- cgit v0.12