Index: TODO =================================================================== diff -u -rd4c3a709884f94a12e97a2dd95f438caf7863800 -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- TODO (.../TODO) (revision d4c3a709884f94a12e97a2dd95f438caf7863800) +++ TODO (.../TODO) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -1764,9 +1764,21 @@ to nsf.c, fixed order - documented a few functions +- enabled nsf::__db_run_assertions in nx::test + (lead before to false posigives in destroy-test) +- eliminated deleted objects and objects from deleted + namespaces in GetAllInstances() +- added handling of unstacked csc entries (removed all DEBUG warnings). + TODO: +- handling of unstacked entries should be made optional +- NsfClassListAdd() and friends should be made generic +- check, whether all CscListRemove() are needed for handling unstacked csc entries +- finsh up CscListAdd() and CscListRemove() +- cleanup method-modifiers.tcl + - "-returns" * leave syntax as is for method? * add flag to alias and forward? Index: generic/nsf.c =================================================================== diff -u -rd4c3a709884f94a12e97a2dd95f438caf7863800 -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- generic/nsf.c (.../nsf.c) (revision d4c3a709884f94a12e97a2dd95f438caf7863800) +++ generic/nsf.c (.../nsf.c) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -3944,20 +3944,49 @@ */ static void GetAllInstances(Tcl_Interp *interp, Tcl_HashTable *destTablePtr, NsfClass *startCl) { - Tcl_HashTable *tablePtr = &startCl->instances; NsfClasses *sc; Tcl_HashSearch search; Tcl_HashEntry *hPtr; + Tcl_HashTable *tablePtr = &startCl->instances; for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { NsfObject *inst = (NsfObject *)Tcl_GetHashKey(tablePtr, hPtr); + Command *cmdPtr; int new; + if (inst->flags & NSF_TCL_DELETE) { + if (RUNTIME_STATE(interp)->debugLevel > 1) { + fprintf(stderr, "Warning: Object %s is apparently deleted\n", objectName(inst)); + } + continue; + } + + cmdPtr = (Command *)inst->id; + assert(cmdPtr); + + if (cmdPtr && (cmdPtr->nsPtr->flags & NS_DYING)) { + if (RUNTIME_STATE(interp)->debugLevel > 0) { + fprintf(stderr, "Warning: Namespace of %s is apparently deleted\n", objectName(inst)); + } + continue; + } + +#if !defined(NDEBUG) + { + NsfObject *object = GetObjectFromString(interp, objectName(inst)); + assert(object); + } +#endif + + /*fprintf (stderr, " -- %p flags %.6x activation %d %s id %p id->flags %.6x " + "nsPtr->flags %.6x (instance of %s)\n", + inst, inst->flags, inst->activationCount, + objectName(inst), inst->id, cmdPtr->flags, cmdPtr->nsPtr ? cmdPtr->nsPtr->flags : 0, + ObjStr(startCl->object.cmdName));*/ + Tcl_CreateHashEntry(destTablePtr, objectName(inst), &new); - /* - fprintf (stderr, " -- %s (%s)\n", objectName(inst), ObjStr(startCl->object.cmdName)); - */ + } for (sc = startCl->sub; sc; sc = sc->nextPtr) { GetAllInstances(interp, destTablePtr, sc->cl); @@ -4548,7 +4577,7 @@ if (cmdList->clientData) { if (!RUNTIME_STATE(interp)->guardCount) { - fprintf(stderr, "guardcall\n"); + /*fprintf(stderr, "guardcall\n");*/ result = GuardCall(object, cl, (Tcl_Command) cmd, interp, (Tcl_Obj*)cmdList->clientData, NULL); } @@ -6246,6 +6275,7 @@ * NRE-case, we need a CscFinish for all return codes. */ #if defined(NRE) + CscListRemove(interp, cscPtr); CscFinish(interp, cscPtr, "guard failed"); #endif return result; @@ -6605,6 +6635,8 @@ * CmdMethodDispatch () does not stack a frame. */ + CscListAdd(interp, cscPtr); + /*fprintf(stderr, "cmdMethodDispatch %s.%s, nothing stacked, objflags %.6x\n", objectName(object), methodName, object->flags); */ @@ -6655,6 +6687,7 @@ result = MethodDispatchCsc(clientData, interp, objc, objv, cscPtr, methodName); + CscListRemove(interp, cscPtr); #if defined(NRE) if ((cscPtr->flags & NSF_CSC_CALL_IS_NRE) == 0) { CscFinish(interp, cscPtr, "csc cleanup"); @@ -6951,8 +6984,9 @@ if (object != lastSelf) { if (RUNTIME_STATE(interp)->debugLevel > 0) { - fprintf(stderr, "Warning: method %s is protected; %s.%s is treated as unknown.\n", - methodName, objectName(object), methodName); + fprintf(stderr, "Warning: '%s %s' fails since method %s.%s is protected.\n", + objectName(object), methodName, + cl ? className(cl) : objectName(object), methodName); } /* reset cmd, since it is still unknown */ cmd = NULL; @@ -7007,6 +7041,7 @@ if (!(cscPtr->flags & NSF_CSC_CALL_IS_NRE)) { result = ObjectDispatchFinalize(interp, cscPtr, result, "immediate", methodName); + CscListRemove(interp, cscPtr); CscFinish(interp, cscPtr, "non-scripted finalize"); } @@ -7810,8 +7845,11 @@ cmd = ObjectFindMethod(interp, paramObj, converterNameObj, &pcl); if (cmd == NULL) { if (paramPtr->converter == ConvertViaCmd) { - fprintf(stderr, "**** could not find checker method %s defined on %s\n", - converterNameString, objectName(paramObj)); + + if (RUNTIME_STATE(interp)->debugLevel > 0) { + fprintf(stderr, "Warning: could not find value checker %s defined on %s\n", + converterNameString, objectName(paramObj)); + } paramPtr->flags |= NSF_ARG_CURRENTLY_UNKNOWN; /* TODO: for the time being, we do not return an error here */ } @@ -11766,10 +11804,12 @@ } } else { /* should never happen */ - fprintf(stderr, "should never happen, maybe someone deleted the alias %s for object %s\n", - methodName, objectName(regObject)); - fprintf(stderr, "procPtr %p NsfObjDispatch %p name %s \n", - procPtr, NsfObjDispatch, Tcl_GetCommandName(interp, cmd)); + if (RUNTIME_STATE(interp)->debugLevel > 0) { + fprintf(stderr, "Warning: Could not obtain alias definition for %s. " + "Maybe someone deleted the alias %s for object %s?\n", + methodName, + methodName, objectName(regObject)); + } Tcl_ResetResult(interp); } } @@ -12217,13 +12257,19 @@ char *key = Tcl_GetHashKey(tablePtr, hPtr); NsfObject *object = GetObjectFromString(interp, key); + if (!object) { + fprintf(stderr,"key %s\n", key); + } + assert(object); assert(object->refCount>0); assert(object->cmdName->refCount>0); if (object->activationCount > 0) { Tcl_CallFrame *framePtr; int count = 0; + NsfClasses *unstackedEntries = RUNTIME_STATE(interp)->cscList; + /*fprintf(stderr, "DEBUG obj %p %s activationcount %d\n", object, objectName(object), object->activationCount);*/ @@ -12236,9 +12282,23 @@ if (cscPtr && cscPtr->self == object) count ++; if (cscPtr && (NsfObject*)cscPtr->cl == object) count ++; } + for (; unstackedEntries; unstackedEntries = unstackedEntries->nextPtr) { + NsfCallStackContent *cscPtr = (NsfCallStackContent *)unstackedEntries->cl; + //fprintf(stderr, "unstackedEntry cscPtr %p\n", cscPtr); + //fprintf(stderr, "unstackedEntry object %s class %s\n", + //objectName(cscPtr->self), + // className(cscPtr->cl)); + if (cscPtr && cscPtr->self == object) count ++; + if (cscPtr && (NsfObject*)cscPtr->cl == object) count ++; + } + if (count != object->activationCount) { - fprintf(stderr, "DEBUG obj %p %s activationcount %d on stack %d \n", + fprintf(stderr, "DEBUG obj %p %s activationcount %d on stack %d; " + "might be from non-stacked but active callstack content\n", object, objectName(object), object->activationCount, count); + + fprintf(stderr, "fixed count %d\n", count); + /*NsfShowStack(interp);*/ /* return NsfVarErrMsg(interp, "wrong activation count for object ", objectName(object), (char *) NULL);*/ } @@ -14485,6 +14545,7 @@ varFramePtr to the previous value. */ Nsf_PopFrameCsc(interp, framePtr2); + CscListRemove(interp, cscPtr); CscFinish(interp, cscPtr, "converter object frame"); Tcl_Interp_varFramePtr(interp) = varFramePtr; @@ -15381,8 +15442,7 @@ if (result == TCL_OK) { Tcl_SetObjResult(interp, object->cmdName); } else { - // TODO remove me - fprintf(stderr, "recreate DoObjInitialization returned %d\n", result); + /* fprintf(stderr, "recreate DoObjInitialization returned %d\n", result);*/ } } return result; Index: generic/nsfInt.h =================================================================== diff -u -r39607bed15618248130a1251cc2b1c2a03db93b0 -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- generic/nsfInt.h (.../nsfInt.h) (revision 39607bed15618248130a1251cc2b1c2a03db93b0) +++ generic/nsfInt.h (.../nsfInt.h) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -682,6 +682,7 @@ Tcl_ObjCmdProc *objInterpProc; Tcl_Obj **methodObjNames; struct NsfShadowTclCommandInfo *tclCommands; + NsfClasses *cscList; int errorCount; /* these flags could move into a bitarray, but are used only once per interp*/ int unknown; Index: generic/nsfShadow.c =================================================================== diff -u -r3b75a92f67f6614a7ee823e4d37bc8724f9fb77d -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- generic/nsfShadow.c (.../nsfShadow.c) (revision 3b75a92f67f6614a7ee823e4d37bc8724f9fb77d) +++ generic/nsfShadow.c (.../nsfShadow.c) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -1,4 +1,4 @@ -/* -*- Mode: c++ -*- +/* * * Extended Object Tcl (XOTcl) * Index: generic/nsfStack.c =================================================================== diff -u -r763c2f93238655742da05c5bb5c8d254d704b945 -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- generic/nsfStack.c (.../nsfStack.c) (revision 763c2f93238655742da05c5bb5c8d254d704b945) +++ generic/nsfStack.c (.../nsfStack.c) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -1,3 +1,5 @@ +static int CscListRemove(Tcl_Interp *interp, NsfCallStackContent *cscPtr); + /* *---------------------------------------------------------------------- * NsfShowStack -- @@ -676,6 +678,8 @@ */ static void CallStackPopAll(Tcl_Interp *interp) { + NsfClasses *unstackedEntries = RUNTIME_STATE(interp)->cscList; + NsfShowStack(interp); while (1) { @@ -701,6 +705,12 @@ Tcl_CallFrame_varTablePtr(framePtr) = NULL; } + for (; unstackedEntries; unstackedEntries = unstackedEntries->nextPtr) { + NsfCallStackContent *cscPtr = (NsfCallStackContent *)unstackedEntries->cl; + CscFinish(interp, cscPtr, "unwind"); + CscListRemove(interp, cscPtr); + } + /* pop the Tcl frame */ Tcl_PopCallFrame(interp); } @@ -789,26 +799,29 @@ * track object activations */ object->activationCount ++; - //fprintf(stderr, "activationCount ++ (%s) --> %d\n",objectName(object), object->activationCount); + /*fprintf(stderr, "CscInit %s method %s activationCount ++ (%s) --> %d\n", + msg, cmd ? Tcl_GetCommandName(object->teardown,cmd) : "UNK", + objectName(object), object->activationCount);*/ /* * track class activations */ if (cl && cmd) { Namespace *nsPtr = ((Command *)cmd)->nsPtr; cl->object.activationCount ++; - /*fprintf(stderr, "... %s cmd %s cmd ns %p (%s, refCount %d ++) obj ns %p parent %p\n", - className(cl), - Tcl_GetCommandName(object->teardown, cmd), - nsPtr, nsPtr->fullName, nsPtr->refCount, - cl->object.nsPtr,cl->object.nsPtr ? ((Namespace*)cl->object.nsPtr)->parentPtr : NULL);*/ + /*fprintf(stderr, "CscInit %s %s activationCount %d cmd %s cmd ns %p (%s, refCount %d ++) " + "obj ns %p parent %p\n", + msg, className(cl), cl->object.activationCount, + Tcl_GetCommandName(object->teardown, cmd), + nsPtr, nsPtr->fullName, nsPtr->refCount, + cl->object.nsPtr,cl->object.nsPtr ? ((Namespace*)cl->object.nsPtr)->parentPtr : NULL);*/ /* incremement the namespace ptr in case tcl tries to delete this namespace during the invocation */ nsPtr->refCount ++; } } - cscPtr->flags |= flags & NSF_CSC_COPY_FLAGS; + cscPtr->flags |= flags & NSF_CSC_COPY_FLAGS; cscPtr->self = object; cscPtr->cl = cl; cscPtr->cmdPtr = cmd; @@ -858,8 +871,8 @@ */ if ((flags & NSF_CSC_OBJECT_ACTIVATED)) { /* - tracking activations of objects - */ + * Tracking activations of objects + */ object->activationCount --; /*fprintf(stderr, "... activationCount -- (%s) --> %d\n",objectName(object), @@ -872,11 +885,13 @@ );*/ assert(object->activationCount > -1); - // TODO remove block + /* if (((object->flags & NSF_DESTROY_CALLED_SUCCESS)>0) != ((object->flags & NSF_DESTROY_CALLED)>0)) { fprintf(stderr, "*** flags differ for obj %p\n", object); } + */ + if (object->activationCount < 1 && object->flags & NSF_DESTROY_CALLED_SUCCESS && allowDestroy) { CallStackDoDestroy(interp, object); } @@ -942,3 +957,40 @@ } +extern NsfClasses ** +NsfClassListAdd(NsfClasses **cList, NsfClass *cl, ClientData clientData); + +static void +CscListAdd(Tcl_Interp *interp, NsfCallStackContent *cscPtr) { + NsfClassListAdd(&RUNTIME_STATE(interp)->cscList, (NsfClass *)cscPtr, NULL); + //fprintf(stderr, "added %p, cscList %p\n", cscPtr, RUNTIME_STATE(interp)->cscList); +} + +static int +CscListRemove(Tcl_Interp *interp, NsfCallStackContent *cscPtr) { + NsfClasses *entries = RUNTIME_STATE(interp)->cscList, *nextPtr, *prevPtr; + int success = 0; + + //fprintf(stderr, "remove %p, cscList %p\n", cscPtr, RUNTIME_STATE(interp)->cscList); + prevPtr = entries; + for (; entries; entries = entries->nextPtr) { + nextPtr = entries->nextPtr; + //fprintf(stderr, "remove checks %p\n", entries->cl); + if ((NsfCallStackContent *)entries->cl == cscPtr) { + //fprintf(stderr, "+++ found entry %p\n", cscPtr); + prevPtr->nextPtr = entries->nextPtr; + FREE(NsfClasses, entries); + success = 1; + + if (RUNTIME_STATE(interp)->cscList == entries) { + //fprintf(stderr, "apparently first entry %p\n", entries); + RUNTIME_STATE(interp)->cscList = nextPtr; + } + + break; + } + prevPtr = entries; + } + + return success; +} Index: generic/nsfUtil.c =================================================================== diff -u -r8eddf67371ec031084a6ef98fdec21e38dff85ff -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- generic/nsfUtil.c (.../nsfUtil.c) (revision 8eddf67371ec031084a6ef98fdec21e38dff85ff) +++ generic/nsfUtil.c (.../nsfUtil.c) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -1,4 +1,4 @@ -/* -*- Mode: c++ -*- +/* * * Extended Object Tcl (XOTcl) * Index: library/lib/test.tcl =================================================================== diff -u -r77104533a2105611e79a6723ece344e0ae6dc016 -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- library/lib/test.tcl (.../test.tcl) (revision 77104533a2105611e79a6723ece344e0ae6dc016) +++ library/lib/test.tcl (.../test.tcl) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -148,7 +148,7 @@ } $t expected $expected $t run - #nsf::__db_run_assertions + nsf::__db_run_assertions } Index: library/xotcl/tests/slottest.xotcl =================================================================== diff -u -rc5d841d4cd001b85e95e01202b4fc0afe75df6a8 -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- library/xotcl/tests/slottest.xotcl (.../slottest.xotcl) (revision c5d841d4cd001b85e95e01202b4fc0afe75df6a8) +++ library/xotcl/tests/slottest.xotcl (.../slottest.xotcl) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -323,8 +323,8 @@ # redefine setter for foo of class A #A slot foo method assign {domain var val} ... A::slot::foo public method assign {domain var val} { - # Do something with [self] that isn't valid pre-init - puts setter-[self proc] + # Do something with [self] that isn't valid before init + #puts setter-[self proc] $domain set $var $val } Index: tests/destroytest.tcl =================================================================== diff -u -rc5d841d4cd001b85e95e01202b4fc0afe75df6a8 -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- tests/destroytest.tcl (.../destroytest.tcl) (revision c5d841d4cd001b85e95e01202b4fc0afe75df6a8) +++ tests/destroytest.tcl (.../destroytest.tcl) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -210,6 +210,7 @@ C method foo {} { puts stderr "==== $::case [current]" namespace delete ::test + puts stderr "AAAA [current] exists [::nsf::isobject [current]]" :set x 1 # Index: tests/method-modifiers.tcl =================================================================== diff -u -r18d4d9c1a99310c3fb9b2f2bed03e9d59fb30d30 -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- tests/method-modifiers.tcl (.../method-modifiers.tcl) (revision 18d4d9c1a99310c3fb9b2f2bed03e9d59fb30d30) +++ tests/method-modifiers.tcl (.../method-modifiers.tcl) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -234,25 +234,36 @@ # Test case attribute-method { - + + ::nsf::__db_show_stack + +puts stderr ======0 Class create C { +puts stderr ======A + nsf::__db_run_assertions +puts stderr ======A-done set x [:attribute a] +puts stderr ======B + nsf::__db_run_assertions + ? [list set _ $x] "::nsf::classes::C::a" # attribute with default :attribute {b b1} :public attribute {c c1} :protected attribute {d d1} -#puts stderr ====== set X [:class-object attribute A] + puts stderr ====== + nsf::__db_run_assertions +puts stderr ====== ? [list set _ $X] "::C::A" #exit # class-object attribute with default :class-object attribute {B B2} :public class-object attribute {C C2} :protected class-object attribute {D D2} } - + C create c1 -a 1 ? {c1 a} 1 ? {c1 b} b1 Index: tests/parameters.tcl =================================================================== diff -u -r7a6e32605412db15c6b9a1d61ce0a9dfd92bfbf6 -rf69e0909fcb180e1cbcdd316f0a20de1b254af3d --- tests/parameters.tcl (.../parameters.tcl) (revision 7a6e32605412db15c6b9a1d61ce0a9dfd92bfbf6) +++ tests/parameters.tcl (.../parameters.tcl) (revision f69e0909fcb180e1cbcdd316f0a20de1b254af3d) @@ -590,7 +590,7 @@ D public method foo {a:mytype} { - puts stderr a=$a + return a=$a } d1 foo 1