Index: generic/nsfStack.c =================================================================== diff -u -rb489939c82f4fd30a0c6dc404f272d29085e087e -r86caad4d5db5f26fcf0d5b2fe009eefef554282c --- generic/nsfStack.c (.../nsfStack.c) (revision b489939c82f4fd30a0c6dc404f272d29085e087e) +++ generic/nsfStack.c (.../nsfStack.c) (revision 86caad4d5db5f26fcf0d5b2fe009eefef554282c) @@ -77,12 +77,20 @@ NSF_INLINE static NsfCallStackContent* CallStackGetTopFrame0(const Tcl_Interp *interp) nonnull(1) pure; -static NsfCallStackContent* NsfCallStackFindLastInvocation( +/* static NsfCallStackContent* NsfCallStackFindLastInvocation( const Tcl_Interp *interp, int offset, Tcl_CallFrame **framePtrPtr + ) nonnull(1);*/ + +static NsfCallStackContent* NsfCallStackFindCallingContext( + const Tcl_Interp *interp, + int offset, + Tcl_CallFrame **callingProcFramePtrPtr, + Tcl_CallFrame **callingFramePtrPtr ) nonnull(1); + static NsfCallStackContent* NsfCallStackFindActiveFrame( const Tcl_Interp *interp, int offset, @@ -613,8 +621,92 @@ /* *---------------------------------------------------------------------- + * NsfCallStackFindCallingContext -- * NsfCallStackFindLastInvocation -- * + * Find the calling context (frame) with a specified offset. Find the + * frame corresponding to the calling proc or (scripted or non-leaf) + * method. + * + * Results: + * Call stack content (for NSF methods) or NULL. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static NsfCallStackContent * +NsfCallStackFindCallingContext(const Tcl_Interp *interp, + int offset, + Tcl_CallFrame **callingProcFramePtrPtr, + Tcl_CallFrame **callingFramePtrPtr) { + register Tcl_CallFrame *varFramePtr = (Tcl_CallFrame *)Tcl_Interp_varFramePtr(interp); + int lvl = Tcl_CallFrame_level(varFramePtr); + + nonnull_assert(interp != NULL); + + // NsfShowStack((Tcl_Interp *)interp); + + for (; likely(varFramePtr != NULL); varFramePtr = Tcl_CallFrame_callerVarPtr(varFramePtr)) { + + if (((unsigned int)Tcl_CallFrame_isProcCallFrame(varFramePtr) & + (FRAME_IS_NSF_METHOD|FRAME_IS_NSF_CMETHOD)) != 0u) { + NsfCallStackContent *cscPtr = (NsfCallStackContent *)Tcl_CallFrame_clientData(varFramePtr); + + /* + * An NSF method frame. + */ + if ((cscPtr->flags & (NSF_CSC_CALL_IS_NEXT|NSF_CSC_CALL_IS_ENSEMBLE)) + || (cscPtr->frameType & NSF_CSC_TYPE_INACTIVE)) { + continue; + } + + if (offset != 0) { + offset--; + } else if (Tcl_CallFrame_level(varFramePtr) < lvl) { + if (callingProcFramePtrPtr != NULL) { + *callingProcFramePtrPtr = varFramePtr; + } + return cscPtr; + } + } else if (Tcl_CallFrame_isProcCallFrame(varFramePtr)) { + + /* + * A Tcl proc frame. + */ + if (offset != 0) { + offset--; + } else if (Tcl_CallFrame_level(varFramePtr) < lvl) { + if (callingProcFramePtrPtr != NULL) { + *callingProcFramePtrPtr = varFramePtr; + } + return NULL; + } + } else { + /* some other frame */ + if (offset != 0) { + offset--; + } else if (callingFramePtrPtr != NULL && + *callingFramePtrPtr == NULL && + Tcl_CallFrame_level(varFramePtr) < lvl) { + /* fprintf(stderr, "firstFramePtr %p lvl %d\n", + varFramePtr, Tcl_CallFrame_level(varFramePtr));*/ + *callingFramePtrPtr = varFramePtr; + } + } + } + + if (callingProcFramePtrPtr != NULL) { + *callingProcFramePtrPtr = NULL; + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * NsfCallStackFindLastInvocation -- + * * Find last invocation of a (scripted or non-leaf) method with a * specified offset. * @@ -626,13 +718,18 @@ * *---------------------------------------------------------------------- */ -static NsfCallStackContent * + +#if 0 + static NsfCallStackContent * NsfCallStackFindLastInvocation(const Tcl_Interp *interp, int offset, Tcl_CallFrame **framePtrPtr) { register Tcl_CallFrame *varFramePtr = (Tcl_CallFrame *)Tcl_Interp_varFramePtr(interp); int lvl = Tcl_CallFrame_level(varFramePtr); + Tcl_CallFrame *firstFramePtr = NULL; nonnull_assert(interp != NULL); + NsfShowStack((Tcl_Interp *)interp); + for (; likely(varFramePtr != NULL); varFramePtr = Tcl_CallFrame_callerVarPtr(varFramePtr)) { if (((unsigned int)Tcl_CallFrame_isProcCallFrame(varFramePtr) & (FRAME_IS_NSF_METHOD|FRAME_IS_NSF_CMETHOD)) != 0u) { @@ -667,6 +764,17 @@ } return NULL; } + } else { + /* some other frame */ + fprintf(stderr, "RUN\n"); + if (offset != 0) { + offset--; + } else if (firstFramePtr == NULL && + Tcl_CallFrame_level(varFramePtr) < lvl) { + fprintf(stderr, "firstFramePtr %p lvl %d\n", + varFramePtr, Tcl_CallFrame_level(varFramePtr)); + firstFramePtr = varFramePtr; + } } } @@ -675,6 +783,7 @@ } return NULL; } +#endif /* *----------------------------------------------------------------------