Index: generic/nsf.c =================================================================== diff -u -r37833d2979f789fc14627e6c1f38ca3cb0ceac01 -rf69d53266ed98cdac54bd60985a26d1694238234 --- generic/nsf.c (.../nsf.c) (revision 37833d2979f789fc14627e6c1f38ca3cb0ceac01) +++ generic/nsf.c (.../nsf.c) (revision f69d53266ed98cdac54bd60985a26d1694238234) @@ -491,7 +491,7 @@ int serial, unsigned int processFlags, ParseContext *pcPtr -) nonnull(1) nonnull(3) nonnull(5) nonnull(6) nonnull(10); +) nonnull(1) nonnull(5) nonnull(6) nonnull(10); static int ArgumentCheck( Tcl_Interp *interp, Tcl_Obj *objPtr, const struct Nsf_Param *pPtr, @@ -24440,7 +24440,6 @@ const Nsf_Param *lastParamPtr; nonnull_assert(interp != NULL); - nonnull_assert(objv != NULL); nonnull_assert(procNameObj != NULL); nonnull_assert(paramPtr != NULL); nonnull_assert(pcPtr != NULL); @@ -24937,7 +24936,14 @@ pcPtr->lastObjc = o; pcPtr->objc = nrParams; - assert(ISOBJ(objv[pcPtr->lastObjc-1])); + /* + * The index "pcPtr->lastObjc-1" can be "-1", which is a problem, when + * called via nsf::parseargs, where the allocated objv array starts at + * position 0. It is fine when just a part of the real objv is passed to + * ArgumentParse(). + * + * assert(ISOBJ(objv[pcPtr->lastObjc-1])); + */ #if defined(PARSE_TRACE_FULL) fprintf(stderr, "..... argv processed o %d lastObjc %d nrParams %d o $max} { - error "value '$value' of parameter $name not between $min and $max" + error "value '$value' of parameter $name not between $min and $max" } return $value } @@ -2491,9 +2491,9 @@ # Test usage of application specific converter in "variable" and # "property"; invalid value ? [list [self] object variable -nocomplain r1:range,arg=1-10 11] \ - {value '11' of parameter value not between 1 and 10} + {value '11' of parameter value not between 1 and 10} ? [list [self] object property -nocomplain [list r2:range,arg=1-10 11]] \ - {value '11' of parameter r2 not between 1 and 10} + {value '11' of parameter r2 not between 1 and 10} # valid value ? [list [self] object variable -nocomplain r1:range,arg=1-10 5] "" @@ -2904,8 +2904,8 @@ nx::Class create Foo { :property -accessor public bar { :public object method value=set { object property value } { - incr ::slotcalls 1 - nsf::var::set $object $property $value + incr ::slotcalls 1 + nsf::var::set $object $property $value } } } @@ -2928,8 +2928,8 @@ nx::Class create Foo { :property -accessor public {baz 1} { :public object method value=set { object property value } { - incr ::slotcalls 1 - nsf::var::set $object $property $value + incr ::slotcalls 1 + nsf::var::set $object $property $value } } } @@ -2960,8 +2960,8 @@ ? {nx::Class create Foo { :property -accessor none bar { :public object method value=set { object property value } { - incr ::slotcalls 1 - nsf::var::set $object $property $value + incr ::slotcalls 1 + nsf::var::set $object $property $value } }} } "::Foo" @@ -2974,8 +2974,8 @@ nx::Class create Foo { :property -accessor none {baz 1} { :public object method value=set { object property value } { - incr ::slotcalls 1 - nsf::var::set $object $property $value + incr ::slotcalls 1 + nsf::var::set $object $property $value } } } @@ -3000,7 +3000,7 @@ ? {nx::Class create Foo { :property bar { :public object method initialize { object property } { - incr ::slotcalls 1 + incr ::slotcalls 1 } }} } "::Foo" @@ -3022,10 +3022,10 @@ nx::Class create Test2 { :property -accessor public list { :public object method value=set { obj var val } { - nsf::var::set $obj $var [list $obj $var $val] + nsf::var::set $obj $var [list $obj $var $val] } :object method unknown { val obj var args } { - return unknown + return unknown } } } @@ -3051,8 +3051,8 @@ ? {catch { o object variable -accessor public -initblock { :public object method value=set args { - incr :assignCalled - next + incr :assignCalled + next } } a 1}} 0 ? {o eval {info exists :a}} 1 @@ -3165,10 +3165,10 @@ # nx::test case parameter-get { nx::Class create C { - :property foo:integer - :property o:object,type=::nx::Object - :property c:class - :property m:metaclass + :property foo:integer + :property o:object,type=::nx::Object + :property c:class + :property m:metaclass } ? {C info lookup parameters create foo} "-foo:integer" @@ -3228,21 +3228,21 @@ :property a { :public object method value=set {object property value} { - incr ::slotset_$property + incr ::slotset_$property nsf::var::set $object $property [expr {$value + 1}] } } :property -trace set b { :public object method value=set {object property value} { - incr ::slotset_$property + incr ::slotset_$property nsf::var::set -notrace $object $property [expr {$value + 1}] } } :property -accessor public -trace set c { :public object method value=set {object property value} { - incr ::slotset_$property + incr ::slotset_$property nsf::var::set -notrace $object $property [expr {$value + 1}] } } @@ -3463,10 +3463,18 @@ ? {nsf::parseargs {a:int} {a}} {expected integer but got "a" for parameter "a"} ? { - nsf::parseargs {-foo:int {-bar:int 2} baz} {hi} - list [info exists foo] [info exists bar] [info exists baz] + nsf::parseargs {-foo:int {-bar:int 2} baz} {hi} + list [info exists foo] [info exists bar] [info exists baz] } "0 1 1" + # + # Test with empty list of actual arguments + # + ? {apply {{} {nsf::parseargs {} {}; llength [info vars]}}} 0 + ? {apply {{} {nsf::parseargs {{x ""}} {}; info vars}}} x + ? {apply {{} {nsf::parseargs {{x ""} {y ""}} {}; lsort [info vars]}}} {x y} + ? {apply {{} {nsf::parseargs {{-a 1} {-b} {x ""} {y ""}} {}; lsort [info vars]}}} {a x y} + ? {set bar} 2 ? {set baz} hi @@ -3475,7 +3483,6 @@ ? {apply {{} {nsf::parseargs {a b args} {1 2 3 4}; expr {[info exists a]+[info exists b]+[info exists args]}}}} "3" ? {apply {{} {nsf::parseargs a 1; expr {"a" in [info vars]};}}} 1 - ? {apply {{} {nsf::parseargs {} {}; llength [info vars];}}} 0 # TODO: Are the below cases intended? #? {apply {{} {nsf::parseargs {a} {}; llength [info vars];}}} 0 @@ -3508,7 +3515,7 @@ nx::Class create A nx::Class create B { :property b1:object,type=A; # rewritten to ::ns1::A (not ::A as previously!). - ? [list [:info slots b1] cget -type] ::ns1::A + ? [list [:info slots b1] cget -type] ::ns1::A :property b2:object,type=ns2::A; # rewritten to ::ns1::ns2::A (not ::ns2::A as previously!). ? [list [:info slots b2] cget -type] ::ns1::ns2::A } @@ -3530,31 +3537,31 @@ ? {catch {::ns1::B create b1 -b1 [::ns1::A new] -b2 [::ns1::ns2::A new]}} 0 } - + nx::test case substdefault-hardening { nx::Class create K { :object property {p2 "$x"} :property {p4 "$y"} :create k } - + ? {::K cget -p2} {$x} ? {::k cget -p4} {$y} - + ? {::K object property {p3:substdefault "[[set _ 1]"}} {substdefault: default '[[set _ 1]' is not a complete script} ? {::K property {p5:substdefault "[[set _ 2]"}} {substdefault: default '[[set _ 2]' is not a complete script} ::K property {p6:substdefault "[set _ 2]]"} ? {[::K new] cget -p6} {2]} ::K object property {p7:substdefault "[set _ 7]]"} ? {::K cget -p7} {7]} - + } nx::test case type-reform { namespace eval :: { - + ::nsf::proc foo {p2:object,type=C} { return [$p2 info class] } @@ -3567,10 +3574,10 @@ return $p1 } } - + ::nsf::method::setter o s1:object,type=C ::nsf::method::setter C s2:object,type=C - + ::proc bar args { ::nsf::parseargs p1:object,type=C $args return [$p1 info class] @@ -3597,21 +3604,21 @@ ::nsf::parseargs p2:object,type=C $args return [$p2 info class] } - + ::proc baz {a} { ::nsf::is object,type=C $a return [$a info class] } - + ::nsf::method::setter A s3:object,type=C ::nsf::method::setter A -per-object s4:object,type=C - + } } } - + set ::C ::ns1::ns2::C - + ## In the intrep (param structure), unqualified names will be qualified; ? {::o foo [::C new]} ::C ? {[::o faa [::C new]] info class} ::C @@ -3622,25 +3629,25 @@ ## the stringrep remains untouched (to allow for cloning, serializing ## method records more easily) ? {nsf::parameter::info type [::o info object method parameters foo p1]} C - + ? {[::ns1::ns2::A new] foo [$::C new]} $::C ? {nsf::parameter::info type [::ns1::ns2::A info method parameters foo p1]} C ? {[[::ns1::ns2::A new] faa [$::C new]] info class} $::C ? {[[::ns1::ns2::A new] s3 [$::C new]] info class} $::C ? {[::ns1::ns2::A s4 [$::C new]] info class} $::C - + ? {::ns1::ns2::foo [$::C new]} $::C - + ? {::foo [::C new]} ::C ? {::bar [::C new]} ::C ? {::baz [::C new]} ::C ? {::ns1::ns2::bar [$::C new]} $::C ? {::ns1::ns2::baz [$::C new]} $::C - + ## error msgs now contain the qualified type names ::C create ::c ? {[::ns1::ns2::A new] foo ::c} \ - "expected object of type ::ns1::ns2::C but got \"::c\" for parameter \"p1\"" + "expected object of type ::ns1::ns2::C but got \"::c\" for parameter \"p1\"" } #