Index: TODO =================================================================== diff -u -r5fa3584b0f682d4103c39af82357713871f1de0c -r70d242f602e1807f7ef67cf9d642bb78f059be44 --- TODO (.../TODO) (revision 5fa3584b0f682d4103c39af82357713871f1de0c) +++ TODO (.../TODO) (revision 70d242f602e1807f7ef67cf9d642bb78f059be44) @@ -1867,9 +1867,11 @@ - improving error messages from argument parser - test "namespace current" and "self" in "contains" and "slots" regression test - - added "nosetter" automatically, when attribute ":method" is used +- fix a bug, where "o configure" (without arguments) resetted + initialied values to the defaults. + TODO: Index: generic/nsf.c =================================================================== diff -u -r1b583476882fea7df04664f551cf87d99c8a0da0 -r70d242f602e1807f7ef67cf9d642bb78f059be44 --- generic/nsf.c (.../nsf.c) (revision 1b583476882fea7df04664f551cf87d99c8a0da0) +++ generic/nsf.c (.../nsf.c) (revision 70d242f602e1807f7ef67cf9d642bb78f059be44) @@ -11373,6 +11373,11 @@ Tcl_Obj *newValue = pPtr->defaultValue; ClientData checkedData; + /* + * Mark that this argument gets the default value + */ + pcPtr->flags[i] |= NSF_PC_IS_DEFAULT; + /* we have a default, do we have to subst it? */ if (pPtr->flags & NSF_ARG_SUBST_DEFAULT) { int result = SubstValue(interp, pcPtr->object, &newValue); @@ -14791,6 +14796,17 @@ for (i=1, paramPtr = paramDefs->paramsPtr; paramPtr->name; paramPtr++, i++) { + /* + * Set the new value always when the object is not yet initialized + * and the new value was specified (was not taken from the default + * value definition). The second part of the test is needed to + * avoid overwriting with default values when e.g. "o configure" + * is called lated without arguments. + */ + if ((object->flags & NSF_INIT_CALLED) && (pc.flags[i-1] & NSF_PC_IS_DEFAULT)) { + continue; + } + newValue = pc.full_objv[i]; /*fprintf(stderr, "new Value of %s = %p '%s', type %s\n", ObjStr(paramPtr->nameObj), @@ -14897,12 +14913,15 @@ continue; } - /* set the variables unless the last argument of the definition is varArgs */ + /* + * Set the instance variable unless the last argument of the + * definition is varArgs. + */ if (i < paramDefs->nrParams || !pc.varArgs) { - /* standard setter */ #if defined(CONFIGURE_ARGS_TRACE) fprintf(stderr, "*** %s SET %s '%s'\n", objectName(object), ObjStr(paramPtr->nameObj), ObjStr(newValue)); #endif + /* Actually set instance variable */ Tcl_ObjSetVar2(interp, paramPtr->nameObj, NULL, newValue, TCL_LEAVE_ERR_MSG|TCL_PARSE_PART1); } } Index: generic/nsfInt.h =================================================================== diff -u -rd884e8166428ad9dae6c39cb16c8324953b69b11 -r70d242f602e1807f7ef67cf9d642bb78f059be44 --- generic/nsfInt.h (.../nsfInt.h) (revision d884e8166428ad9dae6c39cb16c8324953b69b11) +++ generic/nsfInt.h (.../nsfInt.h) (revision 70d242f602e1807f7ef67cf9d642bb78f059be44) @@ -370,13 +370,22 @@ #define NSF_ARG_IS_CONVERTER 0x2000 #define NSF_ARG_IS_ENUMERATION 0x4000 -/* disallowed options */ +/* Disallowed parameter options */ #define NSF_DISALLOWED_ARG_METHOD_PARAMETER (NSF_ARG_METHOD|NSF_ARG_INITCMD|NSF_ARG_RELATION) #define NSF_DISALLOWED_ARG_SETTER (NSF_ARG_SUBST_DEFAULT|NSF_DISALLOWED_ARG_METHOD_PARAMETER) #define NSF_DISALLOWED_ARG_OBJECT_PARAMETER 0 #define NSF_DISALLOWED_ARG_VALUECHECK (NSF_ARG_SUBST_DEFAULT|NSF_ARG_METHOD|NSF_ARG_INITCMD|NSF_ARG_RELATION|NSF_ARG_SWITCH|NSF_ARG_CURRENTLY_UNKNOWN) +/* flags for ParseContext */ +#define NSF_PC_MUST_DECR 0x0001 +#define NSF_PC_IS_DEFAULT 0x0002 + +#define NSF_PC_STATUS_MUST_DECR 0x0001 +#define NSF_PC_STATUS_FREE_OBJV 0x0002 +#define NSF_PC_STATUS_FREE_CD 0x0004 + + /* method types */ #define NSF_METHODTYPE_ALIAS 0x0001 #define NSF_METHODTYPE_SCRIPTED 0x0002 @@ -387,13 +396,7 @@ #define NSF_METHODTYPE_BUILTIN NSF_METHODTYPE_ALIAS|NSF_METHODTYPE_SETTER|NSF_METHODTYPE_FORWARDER|NSF_METHODTYPE_OTHER #define NSF_METHODTYPE_ALL NSF_METHODTYPE_SCRIPTED|NSF_METHODTYPE_BUILTIN|NSF_METHODTYPE_OBJECT -/* flags for ParseContext */ -#define NSF_PC_MUST_DECR 0x0001 -#define NSF_PC_STATUS_MUST_DECR 0x0001 -#define NSF_PC_STATUS_FREE_OBJV 0x0002 -#define NSF_PC_STATUS_FREE_CD 0x0004 - #define NsfObjectSetClass(obj) \ (obj)->flags |= NSF_IS_CLASS #define NsfObjectClearClass(obj) \ Index: tests/parameters.test =================================================================== diff -u -r84c5ee62a46e8fab7b9cc481c87290d387baced9 -r70d242f602e1807f7ef67cf9d642bb78f059be44 --- tests/parameters.test (.../parameters.test) (revision 84c5ee62a46e8fab7b9cc481c87290d387baced9) +++ tests/parameters.test (.../parameters.test) (revision 70d242f602e1807f7ef67cf9d642bb78f059be44) @@ -1314,4 +1314,25 @@ # return enumeration type ? {nx::Class info method parametersyntax "info mixinof"} \ "?-closure? ?-scope all|class|object? ?pattern?" -} \ No newline at end of file +} + +# +# Check whether resetting via method "configure" changes values in the +# initialzed object state. +# +Test case dont-reset-to-defaults { + Class create C { + :attribute {a 1} + :create c1 + } + ? {c1 a} 1 + + # change the value from the default to a different value + ? {c1 a 2} 2 + ? {c1 a} 2 + # call configure ... + c1 configure + # ... and check, it did not reset the value to the default + ? {c1 a} 2 +} +? {::nsf::isobject ::o} 0 \ No newline at end of file