Index: generic/nsf.c =================================================================== diff -u -rbf363a408bfa522970f24b06967f2091604b6d02 -r05d94a270a6c11715c96ddbbe441160e9fd63d42 --- generic/nsf.c (.../nsf.c) (revision bf363a408bfa522970f24b06967f2091604b6d02) +++ generic/nsf.c (.../nsf.c) (revision 05d94a270a6c11715c96ddbbe441160e9fd63d42) @@ -1567,20 +1567,21 @@ for (entryPtr = *firstPtrPtr; entryPtr; prevPtr = entryPtr, entryPtr = entryPtr->nextPtr) { if ((void *)entryPtr->cl == key) { /* found entry */ - if (prevPtr) { - /* later item */ - prevPtr->nextPtr = entryPtr->nextPtr; - } else { - /* first item */ - *firstPtrPtr = entryPtr->nextPtr; - } + if (prevPtr) { + /* later item */ + prevPtr->nextPtr = entryPtr->nextPtr; + } else { + /* first item */ + *firstPtrPtr = entryPtr->nextPtr; + } break; } } } return entryPtr; } + #endif @@ -8681,11 +8682,11 @@ #if defined(NRE) if (validCscPtr) { //fprintf(stderr, "forced finalize 2 cscPtr %p\n", cscPtr); - CscListRemove(interp, cscPtr); + CscListRemove(interp, cscPtr, NULL); CscFinish(interp, cscPtr, result, "csc cleanup"); } #else - CscListRemove(interp, cscPtr); + CscListRemove(interp, cscPtr, NULL); CscFinish(interp, cscPtr, result, "csc cleanup"); #endif @@ -9093,7 +9094,7 @@ //fprintf(stderr, "forced finalize 1 cscPtr %p objc %d %p\n", cscPtr, cscPtr->objc, cscPtr->objv); result = ObjectDispatchFinalize(interp, cscPtr, result /*, "immediate" , methodName*/); - CscListRemove(interp, cscPtr); + CscListRemove(interp, cscPtr, NULL); CscFinish(interp, cscPtr, result, "non-scripted finalize"); } @@ -11959,16 +11960,17 @@ *---------------------------------------------------------------------- * NextSearchAndInvoke -- * - * The function is called with a final argument vector and searches - * for an possible shadowed method. In case is successful, it - * updates the continuation context (filter flags etc), invokes - * the found method, and performs cleanup. + * The function is called with a final argument vector and searches for a + * possibly shadowed method. If a target method is found, this dispatcher + * function updates the continuation context (filter flags etc.), invokes + * upon the target method, and performs a cleanup. * * Results: * Tcl return code * * Side effects: - * The invoked method might produce side effects + * The invoked method might produce side effects. Also, the interp's unknown + * state may be modified. * *---------------------------------------------------------------------- */ @@ -12073,16 +12075,38 @@ object, cl, methodName, frameType, 0); #endif } else if (result == TCL_OK) { + NsfCallStackContent *topCscPtr = NULL; + int isLeafNext; + /* - * We could not find a cmd, but there was no error on the call. - * When we are at the end of a filter-chain, or within a next from - * an ensemble, set the unknown flag to allow higher levels to - * handle this case. + * We could not find a cmd, yet the dispatch attempt did not result + * in an error. This means that we find ourselves in either of three + * situations at this point: + * + * 1) A next cmd (NsfNextCmd()) at the end of a filter chain: Dispatch to + * unknown as there is no implementation for the requested selector + * available. 2) A next cmd from within a leaf submethod (a "leaf next"): + * Remain silent, do not dispatch to unknown. 3) MethodDispatchCsc() + * realises the actual "ensemble next": Dispatch to unknown, the + * requested sub-selector is not resolvable to a cmd. + * + * For the cases 1) and 3), set the interp's unknown flag signalling to + * higher levels (e.g., in MethodDispatchCsc(), in NsfNextCmd()) the need + * for dispatching to unknown. */ + + topCscPtr = CallStackGetTopFrame(interp, NULL); + assert(topCscPtr); + + /* case 2 */ + isLeafNext = (cscPtr != topCscPtr) && (topCscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) && + (topCscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE) == 0; - /*fprintf(stderr, "--- no cmd, csc %p frameType %.6x callType %.6x endOfFilterChain %d NSF_CSC_CALL_IS_ENSEMBLE %d\n", - cscPtr, cscPtr->frameType, cscPtr->flags, endOfFilterChain,(cscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE)!=0);*/ - rst->unknown = endOfFilterChain || (cscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE); + /*fprintf(stderr, "--- no cmd, csc %p frameType %.6x callType %.6x endOfFilterChain %d NSF_CSC_CALL_IS_ENSEMBLE %d NSF_CSC_TYPE_ENSEMBLE % d NSF_CSC_CALL_IS_NEXT %d rst->unknown %d isLeafNext %d\n", cscPtr, cscPtr->frameType, cscPtr->flags, endOfFilterChain, (cscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE) != 0, (cscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) != 0, (cscPtr->flags & NSF_CSC_CALL_IS_NEXT) != 0, rst->unknown, isLeafNext);*/ + + rst->unknown = /* case 1 */ endOfFilterChain || + /* case 3 */ (!isLeafNext && (cscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE)); + /*fprintf(stderr, "******** setting unknown to %d\n", rst->unknown );*/ } @@ -19200,12 +19224,12 @@ * varFramePtr to the previous value. */ Nsf_PopFrameCsc(interp, framePtr2); - CscListRemove(interp, cscPtr); + CscListRemove(interp, cscPtr, NULL); CscFinish(interp, cscPtr, result, "converter object frame"); Tcl_Interp_varFramePtr(interp) = varFramePtr; - /*fprintf(stderr, "NsfOConfigureMethod_ attribute %s evaluated %s => (%d)\n", - ObjStr(paramPtr->nameObj), ObjStr(newValue), result);*/ + /* fprintf(stderr, "NsfOConfigureMethod_ attribute %s evaluated %s => (%d)\n", + ObjStr(paramPtr->nameObj), ObjStr(newValue), result);*/ if (result != TCL_OK) { Nsf_PopFrameObj(interp, framePtr);