Tcl Source Code

Changes On Branch tip-689
Login

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

Changes In Branch tip-689 Excluding Merge-Ins

This is equivalent to a diff from 0fe2f4f3ca to 5da6afe216

2024-04-02
20:09
auto load clock facilities (engine-init, C-stubs and helpers) on demand (rebased and rewritten to ti... check-in: e154c94bd2 user: sebres tags: sebres-tip-689-clock-auto-load
13:49
Merge 8.7 (removing some dead libtommath-related code) check-in: f2ebbca7ed user: jan.nijtmans tags: trunk, main
2024-04-01
21:33
Rebase to 9.0 check-in: 6fcec3ca33 user: jan.nijtmans tags: tip-690
21:32
Rebase to 9.0 Leaf check-in: 5da6afe216 user: jan.nijtmans tags: tip-689
21:29
Rebase to 9.0 Leaf check-in: 6fa90bc4b2 user: jan.nijtmans tags: sebres-experimental-tip-688-auto-load
20:48
Merge 9.0 check-in: d4eee66f60 user: jan.nijtmans tags: tip-626
20:14
Merge-mark Closed-Leaf check-in: 2a5c344036 user: jan.nijtmans tags: bug-ac7592e73c10d04b
20:07
Oops, ckalloc -> Tcl_Alloc check-in: 0fe2f4f3ca user: jan.nijtmans tags: trunk, main
19:56
TIP 688: clock command revision and speedup check-in: dd916eacf3 user: jan.nijtmans tags: trunk, main
2024-03-20
10:05
TIP #689: "namespace unknown" independent on caller namespace check-in: 079e517ec6 user: jan.nijtmans tags: tip-689

Changes to generic/tclBasic.c.

4812
4813
4814
4815
4816
4817
4818



4819
4820





































4821
4822
4823



4824
4825
4826
4827
4828
4829
4830
    Tcl_Obj **newObjv, **handlerObjv;
    CallFrame *varFramePtr = iPtr->varFramePtr;
    Namespace *currNsPtr = NULL;/* Used to check for and invoke any registered
				 * unknown command handler for the current
				 * namespace (TIP 181). */
    Namespace *savedNsPtr = NULL;




    currNsPtr = varFramePtr->nsPtr;
    if ((currNsPtr == NULL) || (currNsPtr->unknownHandlerPtr == NULL)) {





































	currNsPtr = iPtr->globalNsPtr;
	if (currNsPtr == NULL) {
	    Tcl_Panic("TEOV_NotFound: NULL global namespace pointer");



	}
    }

    /*
     * Check to see if the resolution namespace has lost its unknown handler.
     * If so, reset it to "::unknown".
     */







>
>
>

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







4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
    Tcl_Obj **newObjv, **handlerObjv;
    CallFrame *varFramePtr = iPtr->varFramePtr;
    Namespace *currNsPtr = NULL;/* Used to check for and invoke any registered
				 * unknown command handler for the current
				 * namespace (TIP 181). */
    Namespace *savedNsPtr = NULL;

    Tcl_Size qualLen;
    const char *qualName = TclGetStringFromObj(objv[0], &qualLen);

    currNsPtr = varFramePtr->nsPtr;
    if ((currNsPtr == NULL) || (currNsPtr->unknownHandlerPtr == NULL) ||
	(qualLen > 2 && memchr(qualName, ':', qualLen)) /* fast check for NS:: */
    ) {
	/*
	 * first try to find namespace unknown handler of the namespace
	 * of executed command if available:
	 */
	Namespace *altNsPtr, *dummyNsPtr;
	const char *simpleName;

	(void) TclGetNamespaceForQualName(interp, qualName, currNsPtr,
	    TCL_FIND_IF_NOT_SIMPLE, &currNsPtr, &altNsPtr,
	    &dummyNsPtr, &simpleName);
	if (!simpleName) {
	    goto globNS;
	}
	if (!currNsPtr || (currNsPtr == iPtr->globalNsPtr)) {
	    if (!altNsPtr || (altNsPtr == iPtr->globalNsPtr)) {
		goto globNS;
	    }
	    currNsPtr = altNsPtr;
	}
	while (currNsPtr->unknownHandlerPtr == NULL ||
	    (currNsPtr->flags & (NS_DYING | NS_DEAD))
	) {
	    /* traverse to alive parent namespace containing handler */
	    if (!(currNsPtr = currNsPtr->parentPtr) ||
		 (currNsPtr == iPtr->globalNsPtr)
	    ) {
		/* continue from alternate NS if available */
		if (!altNsPtr || (altNsPtr == iPtr->globalNsPtr)) {
		    goto globNS;
		}
		currNsPtr = altNsPtr;
		altNsPtr = NULL;
		continue;
	      globNS:
		/* fallback to the global unknown */
		currNsPtr = iPtr->globalNsPtr;
		if (currNsPtr == NULL) {
		    Tcl_Panic("TEOV_NotFound: NULL global namespace pointer");
		}
		break;
	    }
	}
    }

    /*
     * Check to see if the resolution namespace has lost its unknown handler.
     * If so, reset it to "::unknown".
     */

Changes to library/init.tcl.

114
115
116
117
118
119
120












121
122
123
124
125
126
127
	foreach cmd {add clicks format microseconds milliseconds scan seconds} {
	    dict set cmdmap $cmd ::tcl::clock::$cmd
	}
	namespace inscope ::tcl::clock [list namespace ensemble create -command \
	    [uplevel 1 [list ::namespace origin [::lindex [info level 0] 0]]] \
	    -map $cmdmap]
	::tcl::unsupported::clock::configure -init-complete












	uplevel 1 [info level 0]
    }
}

# Conditionalize for presence of exec.

if {[namespace which -command exec] eq ""} {







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







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
	foreach cmd {add clicks format microseconds milliseconds scan seconds} {
	    dict set cmdmap $cmd ::tcl::clock::$cmd
	}
	namespace inscope ::tcl::clock [list namespace ensemble create -command \
	    [uplevel 1 [list ::namespace origin [::lindex [info level 0] 0]]] \
	    -map $cmdmap]
	::tcl::unsupported::clock::configure -init-complete

	# Auto-loading stubs for 'clock.tcl'

	namespace inscope ::tcl::clock {
	    proc _load_stubs args {
		namespace unknown {}
		::source -encoding utf-8 [::file join [info library] clock.tcl]
		tailcall {*}$args
	    }
	    namespace unknown ::tcl::clock::_load_stubs
	}

	uplevel 1 [info level 0]
    }
}

# Conditionalize for presence of exec.

if {[namespace which -command exec] eq ""} {

Changes to library/tclIndex.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
set auto_index(::auto_mkindex_parser::mkindex) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::hook) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::childhook) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::command) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::commandInit) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::fullname) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::indexEntry) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::tcl::clock::Initialize) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::mcget) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::mcMerge) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GetSystemLocale) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::EnterLocale) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::_hasRegistry) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::LoadWindowsDateTimeFormats) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::LocalizeFormat) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GetSystemTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::SetupTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GuessWindowsTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::LoadTimeZoneFile) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::LoadZoneinfoFile) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ReadZoneinfoFile) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ParsePosixTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ProcessPosixTimeZone) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::DeterminePosixDSTTime) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GetJulianDayFromEraYearDay) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::GetJulianDayFromEraYearMonthWeekDay) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::IsGregorianLeapYear) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::WeekdayOnOrBefore) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ChangeCurrentLocale) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(::tcl::clock::ClearCaches) [list ::tcl::Pkg::source [file join $dir clock.tcl]]
set auto_index(foreachLine) [list ::tcl::Pkg::source [file join $dir foreachline.tcl]]
set auto_index(::tcl::history) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(history) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistAdd) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistKeep) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistClear) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistInfo) [list ::tcl::Pkg::source [file join $dir history.tcl]]







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







15
16
17
18
19
20
21























22
23
24
25
26
27
28
set auto_index(::auto_mkindex_parser::mkindex) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::hook) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::childhook) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::command) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::commandInit) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::fullname) [list ::tcl::Pkg::source [file join $dir auto.tcl]]
set auto_index(::auto_mkindex_parser::indexEntry) [list ::tcl::Pkg::source [file join $dir auto.tcl]]























set auto_index(foreachLine) [list ::tcl::Pkg::source [file join $dir foreachline.tcl]]
set auto_index(::tcl::history) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(history) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistAdd) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistKeep) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistClear) [list ::tcl::Pkg::source [file join $dir history.tcl]]
set auto_index(::tcl::HistInfo) [list ::tcl::Pkg::source [file join $dir history.tcl]]

Changes to tests/namespace.test.

3120
3121
3122
3123
3124
3125
3126










































3127
3128
3129
3130
3131
3132
3133
	namespace unknown ok
	catch {namespace unknown {{}{}{}}}
	namespace unknown
    }
} -cleanup {
    namespace delete foo
} -result ok











































# TIP 314 - ensembles with parameters
test namespace-53.1 {ensembles: parameters} {
    namespace eval ns {
	namespace export x
	proc x {para} {list 1 $para}
	namespace ensemble create -parameters {para1}







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







3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
	namespace unknown ok
	catch {namespace unknown {{}{}{}}}
	namespace unknown
    }
} -cleanup {
    namespace delete foo
} -result ok
test namespace-52.13 {unknown: invocation outside of NS doesn't evade namespace unknown, bug 910d67a229fe7f65} -body {
    namespace eval ::foo::bar {
	proc _unknown args {list ::foo:bar:_unknown [uplevel {namespace current}] $args}
	namespace unknown [namespace current]::_unknown
    }
    list [namespace inscope ::foo::bar {xxx}] [namespace inscope ::foo {bar::xxx}] [::foo::bar::xxx] [namespace inscope :: {foo::bar::xxx}]
} -cleanup {
    namespace delete ::foo
} -result {{::foo:bar:_unknown ::foo::bar xxx} {::foo:bar:_unknown ::foo bar::xxx} {::foo:bar:_unknown :: ::foo::bar::xxx} {::foo:bar:_unknown :: foo::bar::xxx}}
test namespace-52.14 {unknown: invocation outside of NS doesn't evade namespace unknown for command with sub-NS, bug 910d67a229fe7f65} -body {
    namespace eval ::foo::bar {
	proc _unknown args {list ::foo:bar:_unknown [uplevel {namespace current}] $args}
	namespace unknown [namespace current]::_unknown
    }
    set res {}
    lappend res [namespace inscope ::foo::bar {xxx::yyy}] [namespace inscope ::foo {bar::xxx::yyy}] [::foo::bar::xxx::yyy] [namespace inscope :: {foo::bar::xxx::yyy}]
    # now with existsing ::foo::bar::xxx, but without unknown handler inside (only parent ::foo::bar has a handler):
    namespace eval ::foo::bar::xxx {}
    lappend res [namespace inscope ::foo::bar {xxx::yyy}] [namespace inscope ::foo {bar::xxx::yyy}] [::foo::bar::xxx::yyy] [namespace inscope :: {foo::bar::xxx::yyy}]
} -cleanup {
    namespace delete ::foo
    unset -nocomplain res
} -result [lrepeat 2 \
  {::foo:bar:_unknown ::foo::bar xxx::yyy} {::foo:bar:_unknown ::foo bar::xxx::yyy} {::foo:bar:_unknown :: ::foo::bar::xxx::yyy} {::foo:bar:_unknown :: foo::bar::xxx::yyy}
]
test namespace-52.14 {unknown: it must consider alternate search path (relative global NS), bug 910d67a229fe7f65} -body {
    namespace eval ::foo::bar {}
    namespace eval ::xxx::yyy {
	proc _unknown args {list ::xxx:yyy:_unknown [uplevel {namespace current}] $args}
	namespace unknown [namespace current]::_unknown
    }
    set res {}
    lappend res [namespace inscope ::foo::bar {xxx::yyy::cmd}] [namespace inscope ::foo {xxx::yyy::cmd}]
    namespace eval ::foo::bar::xxx {}
    lappend res [namespace inscope ::foo::bar {xxx::yyy::cmd}] [namespace inscope ::foo {xxx::yyy::cmd}]
    namespace eval ::foo::bar::xxx::yyy {}
    lappend res [namespace inscope ::foo::bar {xxx::yyy::cmd}] [namespace inscope ::foo {xxx::yyy::cmd}]
} -cleanup {
    namespace delete ::foo
    namespace delete ::xxx
    unset -nocomplain res
} -result [lrepeat 3 {::xxx:yyy:_unknown ::foo::bar xxx::yyy::cmd} {::xxx:yyy:_unknown ::foo xxx::yyy::cmd}]

# TIP 314 - ensembles with parameters
test namespace-53.1 {ensembles: parameters} {
    namespace eval ns {
	namespace export x
	proc x {para} {list 1 $para}
	namespace ensemble create -parameters {para1}