1 ///////////////////////////////////////////////////////////////////////////// 2 // Purpose: Lua and wxLua debugging code 3 // Author: J. Winwood, John Labenski 4 // Created: June 2003 5 // Copyright: (c) 2012 John Labenski, 2002 Lomtick Software. All rights reserved. 6 // Licence: wxWidgets licence 7 ///////////////////////////////////////////////////////////////////////////// 8 9 #ifndef WX_LUA_DEBUG_H 10 #define WX_LUA_DEBUG_H 11 12 #include <wx/dynarray.h> 13 #include <wx/treectrl.h> // for wxTreeItemData 14 15 #include "wxlua/debug/wxluadebugdefs.h" 16 #include "wxlua/wxlstate.h" 17 18 class WXDLLIMPEXP_WXLUADEBUG wxLuaDebugData; 19 20 // ---------------------------------------------------------------------------- 21 // wxLuaDebugItem - A class to store an item from Lua for wxLuaDebugData 22 // 23 // It is typically used to store table[key] = value pair info. However it may 24 // be used to store stack information as well. 25 // ---------------------------------------------------------------------------- 26 27 enum wxLuaDebugItem_Type 28 { 29 WXLUA_DEBUGITEM_LOCALS = 0x0100, // This wxLuaDebugItem is the parent for local variables 30 31 WXLUA_DEBUGITEM_EXPANDED = 0x0200, // for wxLuaStackDialog 32 33 WXLUA_DEBUGITEM_IS_REFED = 0x1000, // This item was created with a new 34 // wxluaR_ref() rather than using an existing one. 35 WXLUA_DEBUGITEM_KEY_REF = 0x2000, // The ref is for the key 36 WXLUA_DEBUGITEM_VALUE_REF = 0x4000, // The ref is for the value 37 }; 38 39 class WXDLLIMPEXP_WXLUADEBUG wxLuaDebugItem 40 { 41 public: 42 wxLuaDebugItem(const wxLuaDebugItem &debugDataItem); 43 wxLuaDebugItem(const wxString &itemKey, int itemKeyType, 44 const wxString &itemValue, int itemValueType, 45 const wxString &itemSource, 46 int lua_ref, int idx = 0, int flag = 0); 47 48 // The key has the typical meaning of the key in a Lua table GetKey()49 wxString GetKey() const { return m_itemKey; } GetKeyType()50 int GetKeyType() const { return m_itemKeyType; } GetKeyTypeString()51 wxString GetKeyTypeString() const { return wxluaT_typename(NULL, m_itemKeyType); } 52 53 // The value has the typical meaning of the value for the key in a Lua table GetValue()54 wxString GetValue() const { return m_itemValue; } GetValueType()55 int GetValueType() const { return m_itemValueType; } GetValueTypeString()56 wxString GetValueTypeString() const { return wxluaT_typename(NULL, m_itemValueType); } 57 58 // The lua_Debug.source value when enumerating the stack or a stack item GetSource()59 wxString GetSource() const { return m_itemSource; } 60 GetRef()61 int GetRef() const { return m_lua_ref; } // wxluaR_ref() reference GetIndex()62 int GetIndex() const { return m_index; } // stack index or table level index GetFlag()63 int GetFlag() const { return m_flag; } // see wxLuaDebugItem_Type GetFlagBit(int mask)64 bool GetFlagBit(int mask) const { return WXLUA_HASBIT(m_flag, mask); } 65 66 // If GetFlagBit(WXLUA_DEBUGITEM_KEY_REFED) try to convert GetKey() to a number 67 // else if GetFlagBit(WXLUA_DEBUGITEM_VALUE_REFED) try to convert GetValue() to a number 68 // Asserts if neither or both of the bits are set. 69 bool GetRefPtr(wxUIntPtr& ptr) const; 70 SetFlag(int flag)71 void SetFlag(int flag) { m_flag = flag; } SetFlagBit(int bit,bool set)72 void SetFlagBit(int bit, bool set) { m_flag = WXLUA_SETBIT(m_flag, bit, set); } SetRef(int lua_ref)73 void SetRef(int lua_ref) { m_lua_ref = lua_ref; } // only if you've wxluaR_unref()ed it 74 75 // Get a human readable string for debugging ToString()76 wxString ToString() const 77 { 78 return wxString::Format(wxT("Key: '%s' KeyType: %d '%s' Value: '%s' ValueType: %d '%s' Ref: %d Idx: %d Flag: %x HasSrc: %d"), 79 m_itemKey.c_str(), m_itemKeyType, GetKeyTypeString().c_str(), 80 m_itemValue.c_str(), m_itemValueType, GetValueTypeString().c_str(), 81 m_lua_ref, m_index, m_flag, (int)!m_itemSource.IsEmpty()); 82 } 83 84 // implementation 85 86 wxString m_itemKey; 87 int m_itemKeyType; 88 wxString m_itemValue; 89 int m_itemValueType; 90 wxString m_itemSource; 91 int m_lua_ref; 92 int m_index; 93 int m_flag; 94 }; 95 96 #if defined(WXMAKINGDLL_WXLUADEBUG) || defined(WXUSINGDLL) 97 WX_DEFINE_SORTED_USER_EXPORTED_ARRAY(wxLuaDebugItem *, wxLuaDebugItemArray, WXDLLIMPEXP_WXLUADEBUG); 98 #else 99 WX_DEFINE_SORTED_ARRAY(wxLuaDebugItem *, wxLuaDebugItemArray); 100 #endif 101 102 // ---------------------------------------------------------------------------- 103 // wxLuaDebugData - a wxObject ref counted container for a wxLuaDebugItemArray 104 // The destructor deletes the array items. 105 // ---------------------------------------------------------------------------- 106 107 // an invalid wxLuaDebugData for comparison (like wxNullBitmap) 108 extern WXDLLIMPEXP_DATA_WXLUADEBUG(wxLuaDebugData) wxNullLuaDebugData; 109 110 class WXDLLIMPEXP_WXLUADEBUG wxLuaDebugData : public wxObject 111 { 112 public: 113 wxLuaDebugData(bool create); wxLuaDebugData(const wxLuaDebugData & debugData)114 wxLuaDebugData(const wxLuaDebugData &debugData) { Ref(debugData); } 115 ~wxLuaDebugData()116 virtual ~wxLuaDebugData() {} // make gcc happy even though it's not used 117 118 // Has this been created with its ref data? Ok()119 bool Ok() const { return (m_refData != NULL); } 120 121 // Get the data array, please use safe array access functions if possible 122 wxLuaDebugItemArray* GetArray(); 123 const wxLuaDebugItemArray* GetArray() const; 124 125 // wxArray functions mapped to the internal array w/ error checking 126 // The wxLuaDebugItem items added must be created with 'new' and 127 // will be deleted when this class is destroyed. 128 size_t GetCount() const; 129 wxLuaDebugItem* Item(size_t index) const; 130 void Add(wxLuaDebugItem* item); 131 132 //------------------------------------------------------------------------- 133 134 // fill this with the stack entries for the wxLuaState 135 // returns the number of stack entries added 136 int EnumerateStack(lua_State* L); 137 // fill this with the locals from a particular stack frame, if an item on the stack is a 138 // table then add a reference to it in the references array 139 int EnumerateStackEntry(lua_State* L, int stack_frame, wxArrayInt& references); 140 // Fill this with the name and value of items in a table at the given reference 141 // in the wxlua_lreg_debug_refs_key in the LUA_REGISTRYINDEX. 142 // nRef may also be LUA_GLOBALSINDEX and LUA_REGISTRYINDEX. 143 // If the table has a sub table then add a reference to it to the references array. 144 int EnumerateTable(lua_State* L, int nRef, int nEntry, wxArrayInt& references); 145 146 //------------------------------------------------------------------------- 147 // These functions are static to allow them to be used in other places to 148 // give a consistent feel to the display of Lua values. 149 150 // Get information about the item at the 'stack_idx'. Returns the lua_type(L, stack_idx), 151 // fills 'wxl_type' with the WXLUA_TXXX type and 'value' with a human readable value. 152 static int GetTypeValue(lua_State *L, int stack_idx, int* wxl_type, wxString& value); 153 // Get a wxString description about the table at the stack_idx in the Lua stack 154 static wxString GetTableInfo(lua_State *L, int stack_idx); 155 // Get a wxString description about user data at the stack_idx in the Lua stack 156 // if full then try to look up the name of the user data from the bindings 157 static wxString GetUserDataInfo(lua_State *L, int stack_idx, bool full_userdata); 158 159 //------------------------------------------------------------------------- 160 161 // Make a full copy of the array and return it. 162 wxLuaDebugData Copy() const; 163 164 // Ref this table if it hasn't been refed already, returns ref # or LUA_NOREF if not refed 165 int RefTable(lua_State* L, int stack_idx, int* flag_type, int extra_flag, wxArrayInt& references); 166 167 // Sorting function for the wxLuaDebugItemArray, sorts by name 168 static int SortFunction(wxLuaDebugItem *elem1, wxLuaDebugItem *elem2 ); 169 170 // operators 171 bool operator == (const wxLuaDebugData& debugData) const 172 { return m_refData == debugData.m_refData; } 173 bool operator != (const wxLuaDebugData& debugData) const 174 { return m_refData != debugData.m_refData; } 175 176 wxLuaDebugData& operator = (const wxLuaDebugData& debugData) 177 { 178 if ( (*this) != debugData ) 179 Ref(debugData); 180 return *this; 181 } 182 }; 183 184 // ---------------------------------------------------------------------------- 185 // wxLuaCheckStack - Dump the contents of the lua_State for debugging 186 // ---------------------------------------------------------------------------- 187 188 class WXDLLIMPEXP_WXLUADEBUG wxLuaCheckStack 189 { 190 public: 191 // Create a instance, remembers lua_gettop(), 'msg' can be used to add 192 // information about where or why this was created. 193 // If 'print_to_console' then all functions below that return a string will also 194 // print to the console as well. 195 wxLuaCheckStack(lua_State* L, const wxString &msg = wxEmptyString, bool print_to_console = true); 196 // Prints out the starting top and ending top if 'print_to_console' in constructor 197 ~wxLuaCheckStack(); 198 199 // Returns a string comparing the starting and current lua_gettop() with additional msg 200 wxString TestStack(const wxString &msg = wxEmptyString); 201 202 // Returns a string of the current items on the stack with their types. 203 wxString DumpStack(const wxString& msg = wxEmptyString); 204 205 // Returns a string of all of the global variables and subtables with additional msg. 206 wxString DumpGlobals(const wxString& msg = wxEmptyString); 207 // Dump the table and its subtables from the globals index with additional msg. 208 // The name may be of the form "table1.subtable2.subtable3..." 209 wxString DumpTable(const wxString& tableName, const wxString& msg = wxEmptyString); 210 // Dump the table and its subtables at the stack_idx with additional msg. 211 wxString DumpTable(int stack_idx, const wxString& msg = wxEmptyString); 212 213 // Dump the contents of the table at the stack_idx to a string. 'tablename' and 'msg' are 214 // for informational messages, 'tableArray' is used to avoid recursion and should be empty 215 // for the initial call, and 'indent' is used to track indentation level for each subtable. 216 wxString DumpTable(int stack_idx, const wxString& tablename, const wxString& msg, wxSortedArrayString& tableArray, int indent); 217 218 // Print a message to the console if 'print_to_console' in constructor. 219 void OutputMsg(const wxString& msg) const; 220 221 // implementation 222 223 lua_State* m_luaState; 224 wxString m_msg; 225 int m_top; 226 bool m_print_to_console; 227 }; 228 229 #endif // WX_LUA_DEBUG_H 230