00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "wx/wxprec.h"
00011
00012 #ifdef __BORLANDC__
00013 #pragma hdrstop
00014 #endif
00015
00016 #ifndef WX_PRECOMP
00017 #include "wx/wx.h"
00018 #endif
00019
00020 #include "wxluadebug/include/wxldebug.h"
00021 #include "wxlua/include/wxlcallb.h"
00022
00023 wxLuaDebugData wxNullLuaDebugData(false);
00024
00025
00026
00027
00028 wxLuaDebugItem::wxLuaDebugItem(const wxString &itemKey, int itemKeyType,
00029 const wxString &itemValue, int itemValueType,
00030 const wxString &itemSource,
00031 int lua_ref, int idx, int flag)
00032 :m_itemKey(itemKey), m_itemKeyType(itemKeyType),
00033 m_itemValue(itemValue), m_itemValueType(itemValueType),
00034 m_itemSource(itemSource),
00035 m_lua_ref(lua_ref), m_index(idx), m_flag(flag)
00036 {
00037 }
00038
00039 wxLuaDebugItem::wxLuaDebugItem(const wxLuaDebugItem &dataItem)
00040 :m_itemKey(dataItem.m_itemKey), m_itemKeyType(dataItem.m_itemKeyType),
00041 m_itemValue(dataItem.m_itemValue), m_itemValueType(dataItem.m_itemValueType),
00042 m_itemSource(dataItem.m_itemSource),
00043 m_lua_ref(dataItem.m_lua_ref), m_index(dataItem.m_index),
00044 m_flag(dataItem.m_flag)
00045 {
00046 }
00047
00048 bool wxLuaDebugItem::GetRefPtr(long& ptr) const
00049 {
00050 bool key_ref = GetFlagBit(WXLUA_DEBUGITEM_KEY_REF);
00051 bool val_ref = GetFlagBit(WXLUA_DEBUGITEM_VALUE_REF);
00052
00053
00054 wxCHECK_MSG((key_ref || val_ref), false, wxT("wxLuaDebugItem has neither key or value reference"));
00055 wxCHECK_MSG(!(key_ref && val_ref), false, wxT("wxLuaDebugItem has both key and value reference"));
00056
00057 return wxString(key_ref ? m_itemKey: m_itemValue).BeforeFirst(wxT(' ')).ToLong(&ptr, 16);
00058 }
00059
00060
00061
00062
00063
00064 class wxLuaDebugDataRefData : public wxObjectRefData
00065 {
00066 public:
00067 wxLuaDebugDataRefData() : m_dataArray(wxLuaDebugData::SortFunction) {}
00068
00069 virtual ~wxLuaDebugDataRefData()
00070 {
00071 size_t idx, count = m_dataArray.GetCount();
00072 for (idx = 0; idx < count; ++idx)
00073 {
00074 const wxLuaDebugItem *pData = m_dataArray.Item(idx);
00075 delete pData;
00076 }
00077 }
00078
00079 wxLuaDebugItemArray m_dataArray;
00080 };
00081
00082 #define M_DEBUGREFDATA ((wxLuaDebugDataRefData*)m_refData)
00083
00084 wxLuaDebugData::wxLuaDebugData(bool create) : wxObject()
00085 {
00086 if (create)
00087 m_refData = new wxLuaDebugDataRefData;
00088 }
00089
00090 wxLuaDebugItemArray* wxLuaDebugData::GetArray()
00091 {
00092 wxCHECK_MSG(M_DEBUGREFDATA != NULL, NULL, wxT("Invalid ref data"));
00093 return &(M_DEBUGREFDATA->m_dataArray);
00094 }
00095 const wxLuaDebugItemArray* wxLuaDebugData::GetArray() const
00096 {
00097 wxCHECK_MSG(M_DEBUGREFDATA != NULL, NULL, wxT("Invalid ref data"));
00098 return &(M_DEBUGREFDATA->m_dataArray);
00099 }
00100
00101 size_t wxLuaDebugData::GetCount() const
00102 {
00103 wxCHECK_MSG(M_DEBUGREFDATA != NULL, 0, wxT("Invalid ref data"));
00104 return M_DEBUGREFDATA->m_dataArray.GetCount();
00105 }
00106 wxLuaDebugItem* wxLuaDebugData::Item(size_t index) const
00107 {
00108 wxCHECK_MSG(M_DEBUGREFDATA != NULL, NULL, wxT("Invalid ref data"));
00109 return M_DEBUGREFDATA->m_dataArray.Item(index);
00110 }
00111 void wxLuaDebugData::Add(wxLuaDebugItem* item)
00112 {
00113 wxCHECK_RET(M_DEBUGREFDATA != NULL, wxT("Invalid ref data"));
00114 wxCHECK_RET(item != NULL, wxT("Invalid wxLuaDebugItem"));
00115 M_DEBUGREFDATA->m_dataArray.Add(item);
00116 }
00117
00118 wxLuaDebugData wxLuaDebugData::Copy() const
00119 {
00120 wxCHECK_MSG(M_DEBUGREFDATA != NULL, wxNullLuaDebugData, wxT("Invalid ref data"));
00121
00122 wxLuaDebugData copyData(true);
00123
00124 size_t idx, count = GetCount();
00125 for (idx = 0; idx < count; ++idx)
00126 {
00127 const wxLuaDebugItem *pOldData = M_DEBUGREFDATA->m_dataArray.Item(idx);
00128 if (pOldData != NULL)
00129 copyData.Add(new wxLuaDebugItem(*pOldData));
00130 }
00131
00132 return copyData;
00133 }
00134
00135 int wxLuaDebugData::SortFunction(wxLuaDebugItem *elem1, wxLuaDebugItem *elem2 )
00136 {
00137 int ret = 0;
00138
00139 long l1 = 0, l2 = 0;
00140
00141 if ((elem1->m_itemKeyType == WXLUA_TNUMBER) &&
00142 (elem2->m_itemKeyType == WXLUA_TNUMBER) &&
00143 elem1->m_itemKey.BeforeFirst(wxT(' ')).ToLong(&l1) &&
00144 elem2->m_itemKey.BeforeFirst(wxT(' ')).ToLong(&l2))
00145 ret = l1 - l2;
00146 else
00147 ret = elem1->m_itemKey.Cmp(elem2->m_itemKey);
00148
00149 if (ret == 0)
00150 {
00151 ret = elem1->m_itemKeyType - elem2->m_itemKeyType;
00152
00153 if (ret == 0)
00154 {
00155 ret = elem1->m_itemValueType - elem2->m_itemValueType;
00156
00157 if (ret == 0)
00158 {
00159 ret = elem1->m_itemValue.Cmp(elem2->m_itemValue);
00160
00161 if (ret == 0)
00162 ret = int(elem2->GetFlagBit(WXLUA_DEBUGITEM_KEY_REF)) -
00163 int(elem1->GetFlagBit(WXLUA_DEBUGITEM_KEY_REF));
00164 }
00165 }
00166 }
00167
00168 return ret;
00169 }
00170
00171 int wxLuaDebugData::EnumerateStack(const wxLuaState& wxlState_)
00172 {
00173 wxCHECK_MSG(wxlState_.Ok(), 0, wxT("Invalid wxLuaState"));
00174 wxCHECK_MSG(M_DEBUGREFDATA != NULL, 0, wxT("Invalid ref data"));
00175
00176 wxLuaState wxlState(wxlState_);
00177 lua_State* L = wxlState.GetLuaState();
00178 lua_Debug luaDebug = INIT_LUA_DEBUG;
00179 int stack_frame = 0;
00180 int count = 0;
00181
00182 while (lua_getstack(L, stack_frame, &luaDebug) != 0)
00183 {
00184 if (lua_getinfo(L, "Sln", &luaDebug))
00185 {
00186
00187
00188
00189 int currentLine = luaDebug.currentline;
00190 if ((count == 0) || (currentLine != -1))
00191 {
00192 wxString name;
00193 wxString source(lua2wx(luaDebug.source));
00194
00195 if (currentLine == -1)
00196 currentLine = 0;
00197
00198 if (luaDebug.name != NULL)
00199 name = wxString::Format(_("function %s line %d"), lua2wx(luaDebug.name).c_str(), currentLine);
00200 else
00201 name = wxString::Format(_("line %d"), currentLine);
00202
00203 Add(new wxLuaDebugItem(name, WXLUA_TNONE, wxT(""), WXLUA_TNONE, source, LUA_NOREF, stack_frame, WXLUA_DEBUGITEM_LOCALS));
00204 ++count;
00205 }
00206 }
00207
00208 ++stack_frame;
00209 }
00210
00211 return count;
00212 }
00213
00214 int wxLuaDebugData::EnumerateStackEntry(const wxLuaState& wxlState_, int stack_frame, wxArrayInt& references)
00215 {
00216 wxCHECK_MSG(wxlState_.Ok(), 0, wxT("Invalid wxLuaState"));
00217 wxCHECK_MSG(M_DEBUGREFDATA != NULL, 0, wxT("Invalid ref data"));
00218
00219 wxLuaState wxlState(wxlState_);
00220 lua_State* L = wxlState.GetLuaState();
00221 lua_Debug luaDebug = INIT_LUA_DEBUG;
00222 int count = 0;
00223
00224 if (lua_getstack(L, stack_frame, &luaDebug) != 0)
00225 {
00226 int stack_idx = 1;
00227 wxString name(lua2wx(lua_getlocal(L, &luaDebug, stack_idx)));
00228 while (!name.IsEmpty())
00229 {
00230
00231
00232 int wxl_valuetype = WXLUA_TNONE;
00233 wxString value;
00234 wxString source(lua2wx(luaDebug.source));
00235
00236 GetTypeValue(wxlState, -1, &wxl_valuetype, value);
00237
00238
00239
00240
00241
00242
00243
00244
00245 int flag_type = 0;
00246 int nRef = LUA_NOREF;
00247
00248 lua_pop(L, 1);
00249
00250 Add(new wxLuaDebugItem(name, WXLUA_TNONE, value, wxl_valuetype, source, nRef, 0, flag_type));
00251 ++count;
00252
00253 name = lua2wx(lua_getlocal(L, &luaDebug, ++stack_idx));
00254 }
00255 }
00256
00257 return count;
00258 }
00259
00260 wxString wxLuaBindClassString(wxLuaBindClass* wxlClass)
00261 {
00262 wxCHECK_MSG(wxlClass, wxEmptyString, wxT("Invalid wxLuaBindClass"));
00263 wxString baseClasses;
00264 if (wxlClass->baseclassNames)
00265 {
00266 for (size_t i = 0; wxlClass->baseclassNames[i]; ++i)
00267 baseClasses += lua2wx(wxlClass->baseclassNames[i]) + wxT(",");
00268 }
00269
00270 return wxString::Format(wxT(" (%s, wxluatype=%d, classinfo=%s, baseclass=%s, methods=%d, enums=%d)"),
00271 lua2wx(wxlClass->name).c_str(), *wxlClass->wxluatype,
00272 wxString(wxlClass->classInfo ? wxlClass->classInfo->GetClassName() : wxEmptyString).c_str(),
00273 baseClasses.c_str(),
00274 wxlClass->wxluamethods_n, wxlClass->enums_n);
00275 }
00276
00277 int wxLuaDebugData::EnumerateTable(const wxLuaState& wxlState_, int tableRef, int nIndex, wxArrayInt& references)
00278 {
00279 wxCHECK_MSG(wxlState_.Ok(), 0, wxT("Invalid wxLuaState"));
00280 wxCHECK_MSG(M_DEBUGREFDATA != NULL, 0, wxT("Invalid ref data"));
00281
00282 wxLuaState wxlState(wxlState_);
00283 lua_State* L = wxlState.GetLuaState();
00284 int count = 0;
00285
00286 int wxl_keytype = WXLUA_TNONE;
00287 int wxl_valuetype = WXLUA_TNONE;
00288 wxString value;
00289 wxString name;
00290
00291 if ((tableRef == -1) || (tableRef == LUA_GLOBALSINDEX))
00292 {
00293 lua_pushvalue(L, LUA_GLOBALSINDEX);
00294 GetTypeValue(wxlState, -1, &wxl_valuetype, value);
00295
00296 int flag_type = 0;
00297 int val_ref = RefTable(L, -1, &flag_type, WXLUA_DEBUGITEM_VALUE_REF, references);
00298 lua_pop(L, 1);
00299
00300 Add(new wxLuaDebugItem(wxT("Globals"), WXLUA_TNONE, value, WXLUA_TTABLE, wxT(""), val_ref, 0, flag_type));
00301 }
00302 else if (tableRef == LUA_REGISTRYINDEX)
00303 {
00304 lua_pushvalue(L, LUA_REGISTRYINDEX);
00305 GetTypeValue(wxlState, -1, &wxl_valuetype, value);
00306
00307 int flag_type = 0;
00308 int val_ref = RefTable(L, -1, &flag_type, WXLUA_DEBUGITEM_VALUE_REF, references);
00309 lua_pop(L, 1);
00310
00311 Add(new wxLuaDebugItem(wxT("Registry"), WXLUA_TNONE, value, WXLUA_TTABLE, wxT(""), val_ref, 0, flag_type));
00312 }
00313 else
00314 {
00315
00316 if (wxluaR_getref(L, tableRef, &wxlua_lreg_debug_refs_key))
00317 {
00318 if (lua_isnil(L, -1))
00319 {
00320
00321 lua_pop(L, 1);
00322 wxFAIL_MSG(wxT("Invalid wxLua debug reference"));
00323 return count;
00324 }
00325
00326
00327 void *lightuserdata_reg_key = NULL;
00328 lua_pushlightuserdata(L, &wxlua_lreg_regtable_key);
00329 lua_rawget(L, LUA_REGISTRYINDEX);
00330 lua_pushvalue(L, -2);
00331 lua_rawget(L, -2);
00332 lightuserdata_reg_key = lua_touserdata(L, -1);
00333 lua_pop(L, 2);
00334
00335
00336 if (lua_getmetatable(L, -1))
00337 {
00338
00339 GetTypeValue(wxlState, -1, &wxl_valuetype, value);
00340
00341 int flag_type = 0;
00342 int val_ref = RefTable(L, -1, &flag_type, WXLUA_DEBUGITEM_VALUE_REF, references);
00343
00344
00345 Add(new wxLuaDebugItem(wxT(" __metatable"), WXLUA_TTABLE, value, wxl_valuetype, wxT(""), val_ref, nIndex, flag_type));
00346 ++count;
00347
00348 lua_pop(L, 1);
00349 }
00350
00351
00352 if (lua_istable(L, -1))
00353 {
00354 lua_pushnil(L);
00355 while (lua_next(L, -2) != 0)
00356 {
00357
00358
00359
00360 int lua_key_type = GetTypeValue(wxlState, -2, &wxl_keytype, name);
00361
00362 int lua_value_type = GetTypeValue(wxlState, -1, &wxl_valuetype, value);
00363
00364
00365 if (lightuserdata_reg_key != NULL)
00366 {
00367 if (lightuserdata_reg_key == &wxlua_lreg_types_key)
00368 {
00369 value += wxT(" (") + wxluaT_typename(L, (int)lua_tonumber(L, -2)) + wxT(")");
00370 }
00371 else if (lightuserdata_reg_key == &wxlua_lreg_classes_key)
00372 {
00373 wxLuaBindClass* wxlClass = (wxLuaBindClass*)lua_touserdata(L, -1);
00374 value += wxLuaBindClassString(wxlClass);
00375 }
00376 else if (lightuserdata_reg_key == &wxlua_lreg_wxluabindings_key)
00377 {
00378 wxLuaBinding* binding = (wxLuaBinding*)lua_touserdata(L, -2);
00379 name = wxT("wxLuaBinding(")+name+wxT(") -> ")+binding->GetBindingName();
00380 value += wxT(" = ") + binding->GetLuaNamespace();
00381 }
00382 else if (lightuserdata_reg_key == &wxlua_lreg_evtcallbacks_key)
00383 {
00384 wxLuaEventCallback* wxlCallback = (wxLuaEventCallback*)lua_touserdata(L, -2);
00385 wxCHECK_MSG(wxlCallback, count, wxT("Invalid wxLuaEventCallback"));
00386
00387 wxString s(wxlCallback->GetInfo());
00388 name = s.BeforeFirst(wxT('|'));
00389 value = s.AfterFirst(wxT('|'));
00390 }
00391 else if (lightuserdata_reg_key == &wxlua_lreg_windestroycallbacks_key)
00392 {
00393
00394 wxLuaWinDestroyCallback* wxlDestroyCallBack = (wxLuaWinDestroyCallback*)lua_touserdata(L, -1);
00395 wxCHECK_MSG(wxlDestroyCallBack, count, wxT("Invalid wxLuaWinDestroyCallback"));
00396
00397 wxString s(wxlDestroyCallBack->GetInfo());
00398 name = s.BeforeFirst(wxT('|'));
00399 value = s.AfterFirst(wxT('|'));
00400 }
00401 else if (lightuserdata_reg_key == &wxlua_lreg_topwindows_key)
00402 {
00403 wxWindow* win = (wxWindow*)lua_touserdata(L, -2);
00404 name += wxT(" ") + wxString(win->GetClassInfo()->GetClassName());
00405 }
00406 else if (lightuserdata_reg_key == &wxlua_lreg_gcobjects_key)
00407 {
00408 wxObject* obj = (wxObject*)lua_touserdata(L, -1);
00409 name = wxString(obj->GetClassInfo()->GetClassName()) + wxT("(") + name + wxT(")");
00410 }
00411 }
00412
00413
00414 if (lua_key_type == LUA_TLIGHTUSERDATA)
00415 {
00416 void* key = lua_touserdata(L, -2);
00417
00418 if (key == &wxlua_metatable_type_key)
00419 {
00420 value += wxT(" (") + wxluaT_typename(L, (int)lua_tonumber(L, -1)) + wxT(")");
00421 }
00422 else if (key == &wxlua_metatable_wxluabindclass_key)
00423 {
00424 wxLuaBindClass* wxlClass = (wxLuaBindClass*)lua_touserdata(L, -1);
00425 value += wxLuaBindClassString(wxlClass);
00426 }
00427 else if (key == &wxlua_lreg_debug_refs_key)
00428 {
00429 value += wxT(" Note: You cannot traverse refed tables");
00430 }
00431 }
00432
00433
00434
00435
00436 int key_flag_type = 0;
00437 int key_ref = LUA_NOREF;
00438
00439
00440 if ((lua_key_type == LUA_TTABLE) && (lightuserdata_reg_key != &wxlua_lreg_debug_refs_key))
00441 key_ref = RefTable(L, -2, &key_flag_type, WXLUA_DEBUGITEM_KEY_REF, references);
00442 else if (lua_key_type == LUA_TUSERDATA)
00443 {
00444 if (lua_getmetatable(L, -2))
00445 {
00446 key_ref = RefTable(L, -2, &key_flag_type, WXLUA_DEBUGITEM_KEY_REF, references);
00447 lua_pop(L, 1);
00448 }
00449 }
00450
00451
00452 if (key_flag_type != 0)
00453 {
00454 Add(new wxLuaDebugItem(name, wxl_keytype, value, wxl_valuetype, wxT(""), key_ref, nIndex, key_flag_type));
00455 ++count;
00456 }
00457
00458
00459
00460
00461 int val_flag_type = 0;
00462 int val_ref = LUA_NOREF;
00463
00464
00465 if ((lua_value_type == LUA_TTABLE) && (lightuserdata_reg_key != &wxlua_lreg_debug_refs_key))
00466 val_ref = RefTable(L, -1, &val_flag_type, WXLUA_DEBUGITEM_VALUE_REF, references);
00467 else if (lua_value_type == LUA_TUSERDATA)
00468 {
00469 if (lua_getmetatable(L, -1))
00470 {
00471 val_ref = RefTable(L, -1, &val_flag_type, WXLUA_DEBUGITEM_VALUE_REF, references);
00472 lua_pop(L, 1);
00473 }
00474 }
00475
00476 if ((key_flag_type == 0) || ((key_flag_type != 0) && (val_flag_type != 0)))
00477 {
00478 Add(new wxLuaDebugItem(name, wxl_keytype, value, wxl_valuetype, wxT(""), val_ref, nIndex, val_flag_type));
00479 ++count;
00480 }
00481
00482 lua_pop(L, 1);
00483 }
00484 }
00485
00486 lua_pop(L, 1);
00487 }
00488 }
00489
00490 return count;
00491 }
00492
00493 int wxLuaDebugData::RefTable(lua_State* L, int stack_idx, int* flag_type, int extra_flag, wxArrayInt& references)
00494 {
00495 wxCHECK_MSG(L, LUA_NOREF, wxT("Invalid lua_State"));
00496
00497 int lua_ref = LUA_NOREF;
00498
00499 {
00500
00501
00502 if (lua_ref == LUA_NOREF)
00503 {
00504 if (flag_type) *flag_type |= (WXLUA_DEBUGITEM_IS_REFED | extra_flag);
00505 lua_ref = wxluaR_ref(L, stack_idx, &wxlua_lreg_debug_refs_key);
00506 references.Add(lua_ref);
00507 }
00508 }
00509
00510 return lua_ref;
00511 }
00512
00513 int wxLuaDebugData::GetTypeValue(const wxLuaState& wxlState, int stack_idx, int* wxl_type_, wxString& value)
00514 {
00515 wxCHECK_MSG(wxlState.Ok(), 0, wxT("Invalid wxLuaState"));
00516
00517 lua_State* L = wxlState.GetLuaState();
00518 int l_type = lua_type(L, stack_idx);
00519 int wxl_type = wxlua_luatowxluatype(l_type);
00520
00521 if (wxl_type_) *wxl_type_ = wxl_type;
00522
00523 switch (l_type)
00524 {
00525 case LUA_TNONE:
00526 {
00527 value = wxEmptyString;
00528 break;
00529 }
00530 case LUA_TNIL:
00531 {
00532 value = wxT("nil");
00533 break;
00534 }
00535 case LUA_TBOOLEAN:
00536 {
00537 value = (lua_toboolean(L, stack_idx) != 0) ? wxT("true") : wxT("false");
00538 break;
00539 }
00540 case LUA_TLIGHTUSERDATA:
00541 {
00542 value = GetUserDataInfo(wxlState, stack_idx, false);
00543 break;
00544 }
00545 case LUA_TNUMBER:
00546 {
00547 double num = lua_tonumber(L, stack_idx);
00548
00549 if ((long)num == num)
00550 value = wxString::Format(wxT("%ld (0x%lx)"), (long)num, (unsigned long)num);
00551 else
00552 value = wxString::Format(wxT("%g"), num);
00553
00554 break;
00555 }
00556 case LUA_TSTRING:
00557 {
00558 value = lua2wx(lua_tostring(L, stack_idx));
00559 break;
00560 }
00561 case LUA_TTABLE:
00562 {
00563 value = GetTableInfo(wxlState, stack_idx);
00564 break;
00565 }
00566 case LUA_TFUNCTION:
00567 {
00568 value.Printf(wxT("%p"), lua_topointer(L, stack_idx));
00569
00570 if (lua_iscfunction(L, stack_idx))
00571 wxl_type = WXLUA_TCFUNCTION;
00572
00573 break;
00574 }
00575 case LUA_TUSERDATA:
00576 {
00577 value = GetUserDataInfo(wxlState, stack_idx, true);
00578 break;
00579 }
00580 case LUA_TTHREAD:
00581 {
00582 value.Printf(wxT("%p"), lua_topointer(L, stack_idx));
00583 break;
00584 }
00585 default :
00586 {
00587 value = wxEmptyString;
00588 break;
00589 }
00590 }
00591
00592 return l_type;
00593 }
00594
00595 wxString wxLuaDebugData::GetTableInfo(const wxLuaState& wxlState, int stack_idx)
00596 {
00597 wxCHECK_MSG(wxlState.Ok(), wxEmptyString, wxT("Invalid wxLuaState"));
00598 lua_State* L = wxlState.GetLuaState();
00599
00600 int wxl_type = wxluaT_type(L, stack_idx);
00601 int nItems = luaL_getn(L, stack_idx);
00602 const void *pItem = lua_topointer(L, stack_idx);
00603
00604 wxString s(wxString::Format(wxT("%p"), pItem));
00605
00606 if (nItems > 0)
00607 s += wxString::Format(wxT(" (approx %d items)"), nItems);
00608
00609 if (wxlua_iswxuserdatatype(wxl_type))
00610 s += wxString::Format(wxT(" (wxltype %d)"), wxl_type);
00611
00612 return s;
00613 }
00614
00615 wxString wxLuaDebugData::GetUserDataInfo(const wxLuaState& wxlState, int stack_idx, bool full_userdata)
00616 {
00617 wxCHECK_MSG(wxlState.Ok(), wxEmptyString, wxT("Invalid wxLuaState"));
00618 lua_State* L = wxlState.GetLuaState();
00619
00620 void* udata = lua_touserdata(L, stack_idx);
00621
00622 wxString s(wxString::Format(wxT("%p"), udata));
00623
00624 if (!full_userdata)
00625 {
00626
00627 if ((udata == &wxlua_lreg_types_key) ||
00628 (udata == &wxlua_lreg_refs_key) ||
00629 (udata == &wxlua_lreg_debug_refs_key) ||
00630 (udata == &wxlua_lreg_classes_key) ||
00631 (udata == &wxlua_lreg_derivedmethods_key) ||
00632 (udata == &wxlua_lreg_wxluastate_key) ||
00633 (udata == &wxlua_lreg_wxluabindings_key) ||
00634 (udata == &wxlua_lreg_weakobjects_key) ||
00635 (udata == &wxlua_lreg_gcobjects_key) ||
00636 (udata == &wxlua_lreg_evtcallbacks_key) ||
00637 (udata == &wxlua_lreg_windestroycallbacks_key) ||
00638 (udata == &wxlua_lreg_callbaseclassfunc_key) ||
00639 (udata == &wxlua_lreg_wxeventtype_key) ||
00640 (udata == &wxlua_lreg_wxluastatedata_key) ||
00641 (udata == &wxlua_lreg_regtable_key) ||
00642
00643 (udata == &wxlua_metatable_type_key) ||
00644 (udata == &wxlua_lreg_topwindows_key) ||
00645 (udata == &wxlua_metatable_wxluabindclass_key))
00646 {
00647 const char* ss = *(const char**)udata;
00648 s += wxT(" (") + lua2wx(ss) + wxT(")");
00649 }
00650 }
00651 else
00652 {
00653 int wxl_type = wxluaT_type(L, stack_idx);
00654
00655 if (wxlua_iswxuserdatatype(wxl_type))
00656 {
00657 s += wxString::Format(wxT(" (wxltype %d)"), wxl_type);
00658
00659 wxString wxltypeName(wxluaT_typename(L, wxl_type));
00660 if (!wxltypeName.IsEmpty())
00661 s += wxString::Format(wxT(" '%s'"), wxltypeName.c_str());
00662 }
00663 }
00664
00665 return s;
00666 }
00667
00668
00669
00670
00671
00672 wxLuaCheckStack::wxLuaCheckStack(lua_State *L, const wxString &msg, bool print_to_console)
00673 {
00674 m_luaState = L;
00675 m_msg = msg;
00676 m_top = lua_gettop(m_luaState);
00677 m_print_to_console = print_to_console;
00678 }
00679
00680 wxLuaCheckStack::~wxLuaCheckStack()
00681 {
00682 if (m_print_to_console)
00683 TestStack(wxT("~wxLuaCheckStack"));
00684 }
00685
00686 wxString wxLuaCheckStack::TestStack(const wxString &msg)
00687 {
00688 wxString s;
00689 s.Printf(wxT("wxLuaCheckStack::TestStack(L=%p) '%s':'%s': starting top %d ending top %d\n"),
00690 m_luaState, m_msg.c_str(), msg.c_str(), m_top, lua_gettop(m_luaState));
00691
00692 if (m_top != lua_gettop(m_luaState)) s += wxT(" **********");
00693
00694 OutputMsg(s);
00695
00696 return s;
00697 }
00698
00699 wxString wxLuaCheckStack::DumpStack(const wxString& msg)
00700 {
00701 wxCHECK_MSG(m_luaState, wxEmptyString, wxT("Invalid lua_State"));
00702
00703 lua_State* L = m_luaState;
00704 int i, count = lua_gettop(L);
00705 wxString str;
00706 wxString retStr;
00707
00708 str.Printf(wxT("wxLuaCheckStack::DumpStack(L=%p), '%s':'%s', items %d, starting top %d\n"), L, m_msg.c_str(), msg.c_str(), count, m_top);
00709 retStr += str;
00710 OutputMsg(str);
00711
00712 wxLuaState wxlState(L);
00713
00714 for (i = 1; i <= count; i++)
00715 {
00716 int wxl_type = 0;
00717 wxString value;
00718 int l_type = wxLuaDebugData::GetTypeValue(wxlState, i, &wxl_type, value);
00719
00720 str.Printf(wxT(" idx %d: l_type = %d, wxl_type = %d : '%s'='%s'\n"),
00721 i, l_type, wxl_type, wxluaT_typename(L, wxl_type).c_str(), value.c_str());
00722 retStr += str;
00723 OutputMsg(str);
00724 }
00725
00726 return retStr;
00727 }
00728
00729 wxString wxLuaCheckStack::DumpGlobals(const wxString& msg)
00730 {
00731 wxCHECK_MSG(m_luaState, wxEmptyString, wxT("Invalid lua_State"));
00732
00733 wxSortedArrayString tableArray;
00734
00735 return DumpTable(LUA_GLOBALSINDEX, wxT("Globals"), msg, tableArray, 0);
00736 }
00737
00738 wxString wxLuaCheckStack::DumpTable(const wxString &tablename, const wxString& msg)
00739 {
00740 wxCHECK_MSG(m_luaState, wxEmptyString, wxT("Invalid lua_State"));
00741
00742 lua_State* L = m_luaState;
00743 wxSortedArrayString tableArray;
00744 wxString s;
00745
00746
00747 wxString tname(tablename);
00748 lua_pushvalue(L, LUA_GLOBALSINDEX);
00749
00750 do {
00751 lua_pushstring(L, wx2lua(tname.BeforeFirst(wxT('.'))));
00752 lua_rawget(L, -2);
00753
00754 if (lua_isnil(L, -1) || !lua_istable(L, -1))
00755 {
00756 lua_pop(L, 2);
00757
00758 s.Printf(wxT("wxLuaCheckStack::DumpTable(L=%p) Table: '%s' cannot be found!\n"), L, tablename.c_str());
00759 OutputMsg(s);
00760 return s;
00761 }
00762
00763 lua_remove(L, -2);
00764 tname = tname.AfterFirst(wxT('.'));
00765 } while (tname.Len() > 0);
00766
00767 s = DumpTable(lua_gettop(L), tablename, msg, tableArray, 0);
00768 lua_pop(L, 1);
00769
00770 return s;
00771 }
00772
00773 wxString wxLuaCheckStack::DumpTable(int stack_idx, const wxString& msg)
00774 {
00775 wxCHECK_MSG(m_luaState, wxEmptyString, wxT("Invalid lua_State"));
00776
00777 wxSortedArrayString tableArray;
00778
00779 return DumpTable(stack_idx, wxString::Format(wxT("StackIdx=%d"), stack_idx), msg, tableArray, 0);
00780 }
00781
00782 wxString wxLuaCheckStack::DumpTable(int stack_idx, const wxString& tablename, const wxString& msg, wxSortedArrayString& tableArray, int indent)
00783 {
00784 wxCHECK_MSG(m_luaState, wxEmptyString, wxT("Invalid lua_State"));
00785
00786 lua_State* L = m_luaState;
00787 wxLuaState wxlState(L);
00788 wxString indentStr;
00789 wxString s;
00790
00791
00792 if (!lua_istable(L, stack_idx))
00793 {
00794 s.Printf(wxT("wxLuaCheckStack::DumpTable(L=%p) stack idx %d is not a table.\n"), L, stack_idx);
00795 OutputMsg(s);
00796 return s;
00797 }
00798
00799 if (indent == 0)
00800 {
00801
00802 s.Printf(wxT("wxLuaCheckStack::DumpTable(L=%p) Table: '%s'\n"), L, tablename.c_str());
00803 OutputMsg(s);
00804 }
00805 else if (indent > 10)
00806 {
00807
00808 s.Printf(wxT("wxLuaCheckStack::DumpTable(L=%p) Table depth > 10! Truncating: '%s'\n"), L, tablename.c_str());
00809 OutputMsg(s);
00810 return s;
00811 }
00812 else
00813 {
00814 indentStr = wxString(wxT(' '), indent*2) + wxT(">");
00815 }
00816
00817 wxString title = wxString::Format(wxT("%sTable Level %d : name '%s'\n"), indentStr.c_str(), indent, tablename.c_str());
00818 s += title;
00819 OutputMsg(title);
00820
00821 lua_pushvalue(L, stack_idx);
00822
00823 lua_pushnil(L);
00824 while (lua_next(L, -2) != 0)
00825 {
00826 int keyType = 0, valueType = 0;
00827 wxString key, value;
00828
00829 wxLuaDebugData::GetTypeValue(wxlState, -2, &keyType, key);
00830 wxLuaDebugData::GetTypeValue(wxlState, -1, &valueType, value);
00831
00832 wxString info = wxString::Format(wxT("%s%-32s\t%-16s\t%-20s\t%-16s\n"),
00833 indentStr.c_str(), key.c_str(), wxluaT_typename(L, keyType).c_str(), value.c_str(), wxluaT_typename(L, valueType).c_str());
00834 s += info;
00835 OutputMsg(info);
00836
00837 if (tableArray.Index(value) == wxNOT_FOUND)
00838 {
00839 if (valueType == WXLUA_TTABLE)
00840 {
00841 tableArray.Add(value);
00842 s += DumpTable(lua_gettop(L), tablename + wxT(".") + key, msg, tableArray, indent+1);
00843 }
00844 else
00845 {
00846 tableArray.Add(value);
00847 }
00848 }
00849
00850 lua_pop(L, 1);
00851 }
00852
00853 lua_pop(L, 1);
00854
00855 return s;
00856 }
00857
00858 void wxLuaCheckStack::OutputMsg(const wxString& msg) const
00859 {
00860 if (m_print_to_console)
00861 {
00862 #if defined(__WXMSW__)
00863
00864 wxPrintf(wxT("%s"), msg.c_str()); fflush(stdout);
00865 #else //if defined(__WXGTK__) || defined(__WXMAC__)
00866 wxPrintf(wxT("%s"), msg.c_str());
00867 #endif
00868 }
00869 }