Index: generic/nsf.c =================================================================== diff -u -r86caad4d5db5f26fcf0d5b2fe009eefef554282c -rb97fe27792607e6e3d6b89d3e012760e641a90df --- generic/nsf.c (.../nsf.c) (revision 86caad4d5db5f26fcf0d5b2fe009eefef554282c) +++ generic/nsf.c (.../nsf.c) (revision b97fe27792607e6e3d6b89d3e012760e641a90df) @@ -32336,24 +32336,27 @@ } */ static int -NsfOUplevelMethod(Tcl_Interp *interp, NsfObject *UNUSED(object), int objc, Tcl_Obj *const objv[]) { - int i, result; - Tcl_CallFrame *framePtr, *savedVarFramePtr; +NsfOUplevelMethod(Tcl_Interp *interp, NsfObject *object, int objc, Tcl_Obj *const objv[]) { + int result; + CallFrame *requestedFramePtr; + Tcl_CallFrame *framePtr = NULL, *savedVarFramePtr; nonnull_assert(interp != NULL); nonnull_assert(objv != NULL); - /* - * Find the level to use for executing the command. - */ - if (objc > 2) { - CallFrame *cf; - const char *frameInfo = ObjStr(objv[1]); + if (objc < 2) { + wrongArgs: + return NsfPrintError(interp, + "wrong # args: should be \"%s %s ?level? command ?arg ...?\"", + ObjectName(object), + NsfMethodName(objv[0])); + } - result = TclGetFrame(interp, frameInfo, &cf); - if (unlikely(result == -1)) { - return TCL_ERROR; + result = TclObjGetFrame(interp, objv[1], &requestedFramePtr); + if (unlikely(result == -1)) { + return TCL_ERROR; } +<<<<<<< HEAD framePtr = (Tcl_CallFrame *)cf; i = result+1; } else { @@ -32363,25 +32366,31 @@ objc -= i; objv += i; +======= + objc -= result + 1; + if (objc == 0) { + goto wrongArgs; + } + objv += result + 1; +>>>>>>> * nsf.c, methods.test (NsfOUplevelMethod): Fix argument handling - if (framePtr == NULL) { - Tcl_CallFrame *callingFramePtr = NULL; - NsfCallStackFindCallingContext(interp, 1, &framePtr, &callingFramePtr); - // fprintf(stderr, "UPLEVEL framePtr %p\n", framePtr); - // NsfCallStackFindLastInvocation(interp, 1, &framePtr); - if (framePtr == NULL) { - framePtr = callingFramePtr; + if (result == 0) { + /* 0 is returned from TclObjGetFrame when no (or, an invalid) level specifier was provided */ + Tcl_CallFrame *callingFramePtr = NULL; + NsfCallStackFindCallingContext(interp, 1, &framePtr, &callingFramePtr); if (framePtr == NULL) { - framePtr = (Tcl_CallFrame *)Tcl_Interp_varFramePtr(interp)->callerVarPtr; - if (framePtr == NULL) { - framePtr = (Tcl_CallFrame *)Tcl_Interp_varFramePtr(interp); - } + /* no proc frame was found, default to parent frame */ + framePtr = callingFramePtr; } + } else { + /* use the requested frame corresponding to the (valid) level specifier */ + framePtr = (Tcl_CallFrame *)requestedFramePtr; } - } - savedVarFramePtr = (Tcl_CallFrame *)Tcl_Interp_varFramePtr(interp); - Tcl_Interp_varFramePtr(interp) = (CallFrame *)framePtr; + assert(framePtr != NULL); + + savedVarFramePtr = (Tcl_CallFrame *)Tcl_Interp_varFramePtr(interp); + Tcl_Interp_varFramePtr(interp) = (CallFrame *)framePtr; /* * Execute the residual arguments as a command.