Index: TODO =================================================================== diff -u -r4265c280c2d31f281e33fc0cddd9ebdd798ebc06 -rb252a0a0d40f1125c6ad5fa4269bfb500bfd034f --- TODO (.../TODO) (revision 4265c280c2d31f281e33fc0cddd9ebdd798ebc06) +++ TODO (.../TODO) (revision b252a0a0d40f1125c6ad5fa4269bfb500bfd034f) @@ -2426,6 +2426,8 @@ - added first version of "nsf::methoddelete" - extended regression test - updated TODO +- fixed potential crash with -param:switch +- added "... info method exists ...." TODO: Index: generic/gentclAPI.decls =================================================================== diff -u -r32b1b0210fbe6c5794d9bfe6def1fda904254ea6 -rb252a0a0d40f1125c6ad5fa4269bfb500bfd034f --- generic/gentclAPI.decls (.../gentclAPI.decls) (revision 32b1b0210fbe6c5794d9bfe6def1fda904254ea6) +++ generic/gentclAPI.decls (.../gentclAPI.decls) (revision b252a0a0d40f1125c6ad5fa4269bfb500bfd034f) @@ -303,7 +303,7 @@ {-argName "-type" -required 0 -nrargs 1 -type class} } objectInfoMethod method NsfObjInfoMethodMethod { - {-argName "infomethodsubcmd" -type "args|body|definition|handle|parameter|parametersyntax|type|precondition|postcondition|submethods"} + {-argName "infomethodsubcmd" -type "args|body|definition|exists|handle|parameter|parametersyntax|type|precondition|postcondition|submethods"} {-argName "name" -required 1 -type tclobj} } objectInfoMethod methods NsfObjInfoMethodsMethod { @@ -356,7 +356,7 @@ } classInfoMethod method NsfClassInfoMethodMethod { - {-argName "infomethodsubcmd" -type "args|body|definition|handle|parameter|parametersyntax|type|precondition|postcondition|submethods"} + {-argName "infomethodsubcmd" -type "args|body|definition|exists|handle|parameter|parametersyntax|type|precondition|postcondition|submethods"} {-argName "name" -required 1 -type tclobj} } classInfoMethod methods NsfClassInfoMethodsMethod { Index: generic/nsf.c =================================================================== diff -u -r4265c280c2d31f281e33fc0cddd9ebdd798ebc06 -rb252a0a0d40f1125c6ad5fa4269bfb500bfd034f --- generic/nsf.c (.../nsf.c) (revision 4265c280c2d31f281e33fc0cddd9ebdd798ebc06) +++ generic/nsf.c (.../nsf.c) (revision b252a0a0d40f1125c6ad5fa4269bfb500bfd034f) @@ -12875,6 +12875,12 @@ int bool; Tcl_GetBooleanFromObj(interp, pPtr->defaultValue, &bool); pcPtr->objv[i] = Tcl_NewBooleanObj(!bool); + /* + * incr refcount, otherwise the Tcl_Obj might be shared + */ + INCR_REF_COUNT(pcPtr->objv[i]); + pcPtr->flags[i] |= NSF_PC_MUST_DECR; + pcPtr->status |= NSF_PC_STATUS_MUST_DECR; } } else { /* no valued passed, check if default is available */ @@ -13558,12 +13564,12 @@ int subcmd, int withPer_object) { assert(methodName); + Tcl_ResetResult(interp); - /*fprintf(stderr, "ListMethod %s %s cmd %p subcmd %d per-object %d\n", - ObjectName(regObject), methodName, cmd, subcmd, withPer_object);*/ - if (!cmd) { - Tcl_SetObjResult(interp, NsfGlobalObjs[NSF_EMPTY]); + if (subcmd == InfomethodsubcmdExistsIdx) { + Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); + } } else { Tcl_ObjCmdProc *procPtr = Tcl_Command_objProc(cmd); int outputPerObject = 0; @@ -13583,6 +13589,11 @@ Tcl_SetObjResult(interp, MethodHandleObj(regObject, withPer_object, methodName)); return TCL_OK; } + case InfomethodsubcmdExistsIdx: + { + Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); + return TCL_OK; + } case InfomethodsubcmdArgsIdx: { Tcl_Command importedCmd = GetOriginalCommand(cmd); @@ -18216,7 +18227,7 @@ /* objectInfoMethod method NsfObjInfoMethodMethod { - {-argName "infomethodsubcmd" -type "args|body|definition|handle|parameter|parametersyntax|type|precondition|postcondition|subcommands"} + {-argName "infomethodsubcmd" -type "args|body|exists|definition|handle|parameter|parametersyntax|type|precondition|postcondition|subcommands"} {-argName "name" -required 1 -type tclobj} } */ @@ -18471,7 +18482,7 @@ /* classInfoMethod method NsfClassInfoMethodMethod { - {-argName "infomethodsubcmd" -type "args|body|definition|handle|parameter|parametersyntax|type|precondition|postcondition|subcommands"} + {-argName "infomethodsubcmd" -type "args|body|exists|definition|handle|parameter|parametersyntax|type|precondition|postcondition|subcommands"} {-argName "name" -required 1 -type tclobj} } */ Index: generic/nsf.tcl =================================================================== diff -u -r9246ffdfb2716a6abbf3709990abb9c4453eb461 -rb252a0a0d40f1125c6ad5fa4269bfb500bfd034f --- generic/nsf.tcl (.../nsf.tcl) (revision 9246ffdfb2716a6abbf3709990abb9c4453eb461) +++ generic/nsf.tcl (.../nsf.tcl) (revision b252a0a0d40f1125c6ad5fa4269bfb500bfd034f) @@ -41,12 +41,8 @@ # proc for deleting methods # nsf::proc ::nsf::methoddelete {object:object -per-object:switch methodName} { - if {${per-object}} { - set handle [$object ::nsf::methods::object::info::method handle $methodName] - } else { - set handle [$object ::nsf::methods::class::info::method handle $methodName] - } - if {$handle ne ""} { + set scope [expr {${per-object} ? "object" : "class"}] + if {[$object ::nsf::methods::${scope}::info::method exists $methodName]} { ::nsf::method $object {*}[expr {${per-object} ? "-per-object" : ""}] $methodName "" "" } else { error "Object $object: method $methodName is not defined" Index: generic/predefined.h =================================================================== diff -u -r9246ffdfb2716a6abbf3709990abb9c4453eb461 -rb252a0a0d40f1125c6ad5fa4269bfb500bfd034f --- generic/predefined.h (.../predefined.h) (revision 9246ffdfb2716a6abbf3709990abb9c4453eb461) +++ generic/predefined.h (.../predefined.h) (revision b252a0a0d40f1125c6ad5fa4269bfb500bfd034f) @@ -16,10 +16,8 @@ "eval [linsert $(definition) 1 $object]}} else {\n" "error \"cannot require method $name for $object, method unknown\"}}\n" "nsf::proc ::nsf::methoddelete {object:object -per-object:switch methodName} {\n" -"if {${per-object}} {\n" -"set handle [$object ::nsf::methods::object::info::method handle $methodName]} else {\n" -"set handle [$object ::nsf::methods::class::info::method handle $methodName]}\n" -"if {$handle ne \"\"} {\n" +"set scope [expr {${per-object} ? \"object\" : \"class\"}]\n" +"if {[$object ::nsf::methods::${scope}::info::method exists $methodName]} {\n" "::nsf::method $object {*}[expr {${per-object} ? \"-per-object\" : \"\"}] $methodName \"\" \"\"} else {\n" "error \"Object $object: method $methodName is not defined\"}}\n" "::proc strip_proc_name {name} {\n" Index: generic/tclAPI.h =================================================================== diff -u -r32b1b0210fbe6c5794d9bfe6def1fda904254ea6 -rb252a0a0d40f1125c6ad5fa4269bfb500bfd034f --- generic/tclAPI.h (.../tclAPI.h) (revision 32b1b0210fbe6c5794d9bfe6def1fda904254ea6) +++ generic/tclAPI.h (.../tclAPI.h) (revision b252a0a0d40f1125c6ad5fa4269bfb500bfd034f) @@ -7,12 +7,12 @@ } methodDefinition; -enum InfomethodsubcmdIdx {InfomethodsubcmdNULL, InfomethodsubcmdArgsIdx, InfomethodsubcmdBodyIdx, InfomethodsubcmdDefinitionIdx, InfomethodsubcmdHandleIdx, InfomethodsubcmdParameterIdx, InfomethodsubcmdParametersyntaxIdx, InfomethodsubcmdTypeIdx, InfomethodsubcmdPreconditionIdx, InfomethodsubcmdPostconditionIdx, InfomethodsubcmdSubmethodsIdx}; +enum InfomethodsubcmdIdx {InfomethodsubcmdNULL, InfomethodsubcmdArgsIdx, InfomethodsubcmdBodyIdx, InfomethodsubcmdDefinitionIdx, InfomethodsubcmdExistsIdx, InfomethodsubcmdHandleIdx, InfomethodsubcmdParameterIdx, InfomethodsubcmdParametersyntaxIdx, InfomethodsubcmdTypeIdx, InfomethodsubcmdPreconditionIdx, InfomethodsubcmdPostconditionIdx, InfomethodsubcmdSubmethodsIdx}; static int ConvertToInfomethodsubcmd(Tcl_Interp *interp, Tcl_Obj *objPtr, NsfParam CONST *pPtr, ClientData *clientData, Tcl_Obj **outObjPtr) { int index, result; - static CONST char *opts[] = {"args", "body", "definition", "handle", "parameter", "parametersyntax", "type", "precondition", "postcondition", "submethods", NULL}; + static CONST char *opts[] = {"args", "body", "definition", "exists", "handle", "parameter", "parametersyntax", "type", "precondition", "postcondition", "submethods", NULL}; (void)pPtr; result = Tcl_GetIndexFromObj(interp, objPtr, opts, "infomethodsubcmd", 0, &index); *clientData = (ClientData) INT2PTR(index + 1); @@ -166,7 +166,7 @@ static enumeratorConverterEntry enumeratorConverterEntries[] = { {ConvertToScope, "all|class|object"}, - {ConvertToInfomethodsubcmd, "args|body|definition|handle|parameter|parametersyntax|type|precondition|postcondition|submethods"}, + {ConvertToInfomethodsubcmd, "args|body|definition|exists|handle|parameter|parametersyntax|type|precondition|postcondition|submethods"}, {ConvertToCallprotection, "all|protected|public"}, {ConvertToMethodtype, "all|scripted|builtin|alias|forwarder|object|setter|nsfproc"}, {ConvertToFrame, "method|object|default"}, Index: tests/method-modifiers.test =================================================================== diff -u -r9246ffdfb2716a6abbf3709990abb9c4453eb461 -rb252a0a0d40f1125c6ad5fa4269bfb500bfd034f --- tests/method-modifiers.test (.../method-modifiers.test) (revision 9246ffdfb2716a6abbf3709990abb9c4453eb461) +++ tests/method-modifiers.test (.../method-modifiers.test) (revision b252a0a0d40f1125c6ad5fa4269bfb500bfd034f) @@ -374,10 +374,10 @@ } ? {::nsf::methoddelete C x} "Object C: method x is not defined" - #? {::nsf::methoddelete C -per-object x} "Object C: method x is not defined" + ? {::nsf::methoddelete C -per-object x} "Object C: method x is not defined" ? {::nsf::methoddelete C foo} "" ? {::nsf::methoddelete C foo} "Object C: method foo is not defined" ? {::nsf::methoddelete C bar} "Object C: method bar is not defined" ? {::nsf::methoddelete C -per-object bar} "" - #? {::nsf::methoddelete C -per-object bar} "" + ? {::nsf::methoddelete C -per-object bar} "Object C: method bar is not defined" } \ No newline at end of file