Index: generic/xotclAccessInt.h =================================================================== diff -u -r2880a345930ceabfec83d491f26b8254099c8991 -rd1369a8b2d5b02d622a18cfccc2f9dd99959d05d --- generic/xotclAccessInt.h (.../xotclAccessInt.h) (revision 2880a345930ceabfec83d491f26b8254099c8991) +++ generic/xotclAccessInt.h (.../xotclAccessInt.h) (revision d1369a8b2d5b02d622a18cfccc2f9dd99959d05d) @@ -1,6 +1,7 @@ #define Tcl_Interp_numLevels(interp) ((Interp *)interp)->numLevels #define Tcl_Interp_framePtr(interp) ((Tcl_CallFrame *)((Interp *)interp)->framePtr) #define Tcl_Interp_varFramePtr(interp) (((Interp *)interp)->varFramePtr) +#define Tcl_Interp_cmdFramePtr(interp) (((Interp *)interp)->cmdFramePtr) #define Tcl_Interp_globalNsPtr(interp) ((Tcl_Namespace *)((Interp *)interp)->globalNsPtr) #define Tcl_Interp_flags(interp) ((Interp *)interp)->flags #if DISPATCH_TRACE Index: generic/xotclInt.h =================================================================== diff -u -r091d3c94b06fd94c8e2bf39f806c43483909e2af -rd1369a8b2d5b02d622a18cfccc2f9dd99959d05d --- generic/xotclInt.h (.../xotclInt.h) (revision 091d3c94b06fd94c8e2bf39f806c43483909e2af) +++ generic/xotclInt.h (.../xotclInt.h) (revision d1369a8b2d5b02d622a18cfccc2f9dd99959d05d) @@ -525,7 +525,7 @@ XOTE_METHOD, XOTE_OBJECT, XOTE_SETTER, XOTE_GUARD_OPTION, XOTE___UNKNOWN__, /* Patly redefined Tcl commands; leave them together at the end */ - XOTE_EXPR, XOTE_FORMAT, XOTE_INFO, XOTE_INTERP, XOTE_IS, XOTE_RENAME, XOTE_SUBST + XOTE_EXPR, XOTE_FORMAT, XOTE_INFO, XOTE_INFO_FRAME, XOTE_INTERP, XOTE_IS, XOTE_RENAME, XOTE_SUBST } XOTclGlobalNames; #if !defined(XOTCL_C) extern char *XOTclGlobalStrings[]; @@ -548,7 +548,7 @@ "method", "object", "setter", "-guard", "__unknown__", /* tcl commands */ - "expr", "format", "info", "interp", "::tcl::string::is", "rename", "subst", + "expr", "format", "info", "::tcl::info::frame", "interp", "::tcl::string::is", "rename", "subst", }; #endif Index: generic/xotclShadow.c =================================================================== diff -u -r5a0750dc422574bc5ae91d9b58c64b8f5713d405 -rd1369a8b2d5b02d622a18cfccc2f9dd99959d05d --- generic/xotclShadow.c (.../xotclShadow.c) (revision 5a0750dc422574bc5ae91d9b58c64b8f5713d405) +++ generic/xotclShadow.c (.../xotclShadow.c) (revision d1369a8b2d5b02d622a18cfccc2f9dd99959d05d) @@ -107,6 +107,49 @@ return XOTclCallCommand(interp, XOTE_RENAME, objc, objv); } +static int +XOTcl_InfoFrameObjCmd(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { + int result; + CONST char* resultString; + + result = XOTclCallCommand(interp, XOTE_INFO_FRAME, objc, objv); + + if (result == TCL_OK && objc == 2) { + int level, topLevel, frameFlags; + CmdFrame *framePtr = Tcl_Interp_cmdFramePtr(interp); + CallFrame *varFramePtr = Tcl_Interp_varFramePtr(interp); + Tcl_Obj *resultObj = Tcl_GetObjResult(interp); + + /* level must be ok, otherwise we weould not have a TCL_OK */ + Tcl_GetIntFromObj(interp, objv[1], &level); + + /* todo: coroutine level messing is missing */ + topLevel = framePtr == NULL ? 0 : framePtr->level; + + if (level > 0) { + level -= topLevel; + } + /*fprintf(stderr, "topLevel %d level %d\n",topLevel, level);*/ + while (++level <= 0) { + framePtr = framePtr->nextPtr; + varFramePtr = varFramePtr->callerPtr; + } + frameFlags = Tcl_CallFrame_isProcCallFrame(varFramePtr); + /*fprintf(stderr, " ... frame %p varFramePtr %p frameFlags %.6x\n", framePtr, varFramePtr, frameFlags); + tcl85showStack(interp);*/ + if (frameFlags & (FRAME_IS_XOTCL_METHOD|FRAME_IS_XOTCL_CMETHOD)) { + XOTclCallStackContent *cscPtr = + ((XOTclCallStackContent *)Tcl_CallFrame_clientData(varFramePtr)); + Tcl_ListObjAppendElement(interp, resultObj, Tcl_NewStringObj("object",6)); + Tcl_ListObjAppendElement(interp, resultObj, cscPtr->self->cmdName); + Tcl_ListObjAppendElement(interp, resultObj, Tcl_NewStringObj("class",5)); + Tcl_ListObjAppendElement(interp, resultObj, cscPtr->cl ? cscPtr->cl->object.cmdName : XOTclGlobalObjects[XOTE_EMPTY]); + } + } + + return result; +} + /* * Obtain the names of the tcl commands * not available through the stub interface and overload some global commands @@ -126,20 +169,22 @@ /* no commands are overloaded, these are only used for calling e.g. Tcl_ExprObjCmd(), Tcl_IncrObjCmd() and Tcl_SubstObjCmd(), which are not available in though the stub table */ - rc |= XOTclReplaceCommand(interp, XOTE_EXPR, 0, initialized); - rc |= XOTclReplaceCommand(interp, XOTE_SUBST, 0, initialized); + rc |= XOTclReplaceCommand(interp, XOTE_EXPR, NULL, initialized); + rc |= XOTclReplaceCommand(interp, XOTE_SUBST, NULL, initialized); #endif - rc |= XOTclReplaceCommand(interp, XOTE_FORMAT, 0, initialized); - rc |= XOTclReplaceCommand(interp, XOTE_INTERP, 0, initialized); - rc |= XOTclReplaceCommand(interp, XOTE_IS, 0, initialized); + rc |= XOTclReplaceCommand(interp, XOTE_FORMAT, NULL, initialized); + rc |= XOTclReplaceCommand(interp, XOTE_INTERP, NULL, initialized); + rc |= XOTclReplaceCommand(interp, XOTE_IS, NULL, initialized); /* for the following commands, we have to add our own semantics */ - rc |= XOTclReplaceCommand(interp, XOTE_RENAME, XOTcl_RenameObjCmd, initialized); + rc |= XOTclReplaceCommand(interp, XOTE_INFO_FRAME, XOTcl_InfoFrameObjCmd, initialized); + rc |= XOTclReplaceCommand(interp, XOTE_RENAME, XOTcl_RenameObjCmd, initialized); } else if (load == SHADOW_REFETCH) { XOTclReplaceCommandCheck(interp, XOTE_RENAME, XOTcl_RenameObjCmd); } else { XOTclReplaceCommandCleanup(interp, XOTE_RENAME); + XOTclReplaceCommandCleanup(interp, XOTE_INFO_FRAME); FREE(XOTclShadowTclCommandInfo*, RUNTIME_STATE(interp)->tclCommands); RUNTIME_STATE(interp)->tclCommands = NULL; }