Skip to content

Commit a84c61a

Browse files
committed
Verbose lua call stack (Thanks @Giperion)
Other lua debugging corrections
1 parent dbcdd34 commit a84c61a

File tree

3 files changed

+129
-45
lines changed

3 files changed

+129
-45
lines changed

src/xrScriptEngine/ScriptEngineScript.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,8 @@ void LuaLog(pcstr caMessage)
2626

2727
void ErrorLog(pcstr caMessage)
2828
{
29-
if (!GEnv.ScriptEngine->m_stack_is_ready)
30-
Msg("LUA Error: %s", caMessage); // Xottab_DUTY: temporary workaround to get lua error output
31-
3229
GEnv.ScriptEngine->error_log("%s", caMessage);
33-
#ifdef DEBUG
3430
GEnv.ScriptEngine->print_stack();
35-
#endif
3631
#if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO)
3732
if (GEnv.ScriptEngine->debugger())
3833
GEnv.ScriptEngine->debugger()->Write(caMessage);

src/xrScriptEngine/script_engine.cpp

Lines changed: 125 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ void CScriptEngine::reinit()
120120
m_virtual_machine = luaL_newstate();
121121
if (!m_virtual_machine)
122122
{
123-
Msg("! ERROR : Cannot initialize script virtual machine!");
123+
Log("! ERROR : Cannot initialize script virtual machine!");
124124
return;
125125
}
126126
RegisterState(m_virtual_machine, this);
@@ -134,9 +134,8 @@ void CScriptEngine::reinit()
134134

135135
int CScriptEngine::vscript_log(LuaMessageType luaMessageType, LPCSTR caFormat, va_list marker)
136136
{
137-
#ifdef DEBUG
138-
if (!g_LuaDebug.test(1) && luaMessageType != LuaMessageType::Error)
139-
return 0;
137+
//if (!g_LuaDebug.test(1) && luaMessageType != LuaMessageType::Error)
138+
// return 0;
140139
LPCSTR S = "", SS = "";
141140
LPSTR S1;
142141
string4096 S2;
@@ -186,17 +185,19 @@ int CScriptEngine::vscript_log(LuaMessageType luaMessageType, LPCSTR caFormat, v
186185
xr_strcat(S2, "\r\n");
187186
m_output.w(S2, xr_strlen(S2));
188187
return l_iResult;
189-
#else
190-
return 0;
191-
#endif
192188
}
193189

194-
void CScriptEngine::print_stack()
190+
void CScriptEngine::print_stack(lua_State* L)
195191
{
196-
if (!m_stack_is_ready)
192+
if (!m_stack_is_ready || logReenterability)
197193
return;
194+
195+
logReenterability = true;
198196
m_stack_is_ready = false;
199-
lua_State* L = lua();
197+
198+
if (L == nullptr)
199+
L = lua();
200+
200201
lua_Debug l_tDebugInfo;
201202
for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); i++)
202203
{
@@ -213,23 +214,114 @@ void CScriptEngine::print_stack()
213214
script_log(LuaMessageType::Error, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src,
214215
l_tDebugInfo.currentline, l_tDebugInfo.name);
215216
}
217+
// Giperion: verbose log
218+
Msg("\tLocals: ");
219+
pcstr name = nullptr;
220+
int VarID = 1;
221+
while ((name = lua_getlocal(L, &l_tDebugInfo, VarID++)) != nullptr)
222+
{
223+
LogVariable(L, name, 1, true);
224+
225+
lua_pop(L, 1); /* remove variable value */
226+
}
227+
Msg("\tEnd");
228+
// -Giperion
229+
}
230+
231+
m_stack_is_ready = true;
232+
logReenterability = false;
233+
}
234+
235+
void CScriptEngine::LogTable(lua_State* luaState, pcstr S, int level)
236+
{
237+
if (!lua_istable(luaState, -1))
238+
return;
239+
240+
lua_pushnil(luaState); /* first key */
241+
while (lua_next(luaState, -2) != 0)
242+
{
243+
char sname[256];
244+
char sFullName[256];
245+
xr_sprintf(sname, "%s", lua_tostring(luaState, -2));
246+
xr_sprintf(sFullName, "%s.%s", S, sname);
247+
LogVariable(luaState, sFullName, level + 1, false);
248+
249+
lua_pop(luaState, 1); /* removes `value'; keeps `key' for next iteration */
216250
}
217251
}
218252

253+
void CScriptEngine::LogVariable(lua_State* luaState, pcstr name, int level, bool bOpenTable)
254+
{
255+
const int ntype = lua_type(luaState, -1);
256+
const pcstr type = lua_typename(luaState, ntype);
257+
258+
char tabBuffer[32] = {0};
259+
memset(tabBuffer, '\t', level);
260+
261+
char value[128];
262+
263+
switch (ntype)
264+
{
265+
case LUA_TNUMBER:
266+
xr_sprintf(value, "%f", lua_tonumber(luaState, -1));
267+
break;
268+
269+
case LUA_TBOOLEAN:
270+
xr_sprintf(value, "%s", lua_toboolean(luaState, -1) ? "true" : "false");
271+
break;
272+
273+
case LUA_TSTRING:
274+
xr_sprintf(value, "%.127s", lua_tostring(luaState, -1));
275+
break;
276+
277+
case LUA_TTABLE:
278+
{
279+
if (bOpenTable)
280+
{
281+
Msg("%s Table: %s", tabBuffer, name);
282+
LogTable(luaState, name, level + 1);
283+
return;
284+
}
285+
xr_sprintf(value, "[...]");
286+
}
287+
break;
288+
289+
case LUA_TUSERDATA:
290+
{
291+
/*luabind::detail::object_rep* obj = static_cast<luabind::detail::object_rep*>(lua_touserdata(luaState, -1));
292+
luabind::detail::lua_reference& r = obj->get_lua_table(); // XXX: No such method
293+
if (r.is_valid())
294+
{
295+
r.get(luaState);
296+
Msg("%s Userdata: %s", tabBuffer, name);
297+
LogTable(luaState, name, level + 1);
298+
lua_pop(luaState, 1); //Remove userobject
299+
return;
300+
}*/
301+
Msg("%s TODO: Fix userdata retrieval", tabBuffer);
302+
xr_strcpy(value, "[not available]");
303+
}
304+
break;
305+
306+
default:
307+
xr_strcpy(value, "[not available]");
308+
break;
309+
}
310+
311+
312+
Msg("%s %s %s : %s", tabBuffer, type, name, value);
313+
}
314+
219315
int CScriptEngine::script_log(LuaMessageType message, LPCSTR caFormat, ...)
220316
{
221317
va_list marker;
222318
va_start(marker, caFormat);
223319
int result = vscript_log(message, caFormat, marker);
224320
va_end(marker);
225-
#ifdef DEBUG
226-
if (message == LuaMessageType::Error && !logReenterability)
227-
{
228-
logReenterability = true;
321+
322+
if (message == LuaMessageType::Error)
229323
print_stack();
230-
logReenterability = false;
231-
}
232-
#endif
324+
233325
return result;
234326
}
235327

@@ -290,9 +382,7 @@ lua_State* L, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, LPCSTR caNameS
290382
l_iErrorCode = luaL_loadbuffer(L, caBuffer, tSize, caScriptName);
291383
if (l_iErrorCode)
292384
{
293-
#ifdef DEBUG
294385
print_output(L, caScriptName, l_iErrorCode);
295-
#endif
296386
on_error(L);
297387
return false;
298388
}
@@ -345,9 +435,7 @@ bool CScriptEngine::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName)
345435
#endif
346436
if (l_iErrorCode)
347437
{
348-
#ifdef DEBUG
349438
print_output(lua(), caScriptName, l_iErrorCode);
350-
#endif
351439
on_error(lua());
352440
lua_settop(lua(), start);
353441
return false;
@@ -478,20 +566,18 @@ luabind::object CScriptEngine::name_space(LPCSTR namespace_name)
478566

479567
struct raii_guard : private Noncopyable
480568
{
481-
CScriptEngine* scriptEngine;
569+
CScriptEngine* m_script_engine;
482570
int m_error_code;
483571
const char*& m_error_description;
484572

485573
raii_guard(CScriptEngine* scriptEngine, int error_code, const char*& error_description)
486-
: m_error_code(error_code), m_error_description(error_description)
487-
{
488-
this->scriptEngine = scriptEngine;
489-
}
574+
: m_script_engine(scriptEngine), m_error_code(error_code), m_error_description(error_description)
575+
{}
490576

491577
~raii_guard()
492578
{
493579
#ifdef DEBUG
494-
bool lua_studio_connected = !!scriptEngine->debugger();
580+
const bool lua_studio_connected = !!m_script_engine->debugger();
495581
if (!lua_studio_connected)
496582
#endif
497583
{
@@ -519,8 +605,9 @@ bool CScriptEngine::print_output(lua_State* L, LPCSTR caScriptFileName, int erro
519605
VERIFY(scriptEngine);
520606
if (errorCode)
521607
print_error(L, errorCode);
522-
LPCSTR S = "see call_stack for details!";
523-
raii_guard guard(scriptEngine, errorCode, S);
608+
scriptEngine->print_stack(L);
609+
pcstr S = "see call_stack for details!";
610+
raii_guard guard(scriptEngine, errorCode, caErrorText ? caErrorText : S);
524611
if (!lua_isstring(L, -1))
525612
return false;
526613
S = lua_tostring(L, -1);
@@ -690,9 +777,7 @@ CScriptEngine::CScriptEngine(bool is_editor)
690777
luabind::allocator = &luabind_allocator;
691778
luabind::allocator_context = nullptr;
692779
m_current_thread = nullptr;
693-
#ifdef DEBUG
694780
m_stack_is_ready = false;
695-
#endif
696781
m_virtual_machine = nullptr;
697782
m_stack_level = 0;
698783
m_reload_modules = false;
@@ -740,16 +825,17 @@ void CScriptEngine::unload()
740825

741826
int CScriptEngine::lua_panic(lua_State* L)
742827
{
743-
print_output(L, "PANIC", LUA_ERRRUN);
828+
print_output(L, "", LUA_ERRRUN, "PANIC");
744829
return 0;
745830
}
746831

747832
void CScriptEngine::lua_error(lua_State* L)
748833
{
749-
print_output(L, "", LUA_ERRRUN);
834+
pcstr err = lua_tostring(L, -1);
835+
print_output(L, "", LUA_ERRRUN, err);
750836
on_error(L);
751837
#if !XRAY_EXCEPTIONS
752-
xrDebug::Fatal(DEBUG_INFO, "LUA error: %s", lua_tostring(L, -1));
838+
xrDebug::Fatal(DEBUG_INFO, "LUA error: %s", err);
753839
#else
754840
throw lua_tostring(L, -1);
755841
#endif
@@ -779,8 +865,9 @@ int CScriptEngine::lua_pcall_failed(lua_State* L)
779865
#if !XRAY_EXCEPTIONS
780866
void CScriptEngine::lua_cast_failed(lua_State* L, const luabind::type_id& info)
781867
{
782-
print_output(L, "", LUA_ERRRUN);
783-
xrDebug::Fatal(DEBUG_INFO, "LUA error: cannot cast lua value to %s", info.name());
868+
string128 buf;
869+
xr_sprintf(buf, "LUA error: cannot cast lua value to %s", info.name());
870+
print_output(L, "", LUA_ERRRUN,buf);
784871
}
785872
#endif
786873

@@ -901,7 +988,7 @@ void CScriptEngine::init(ExporterFunc exporterFunc, bool loadGlobalNamespace)
901988
luajit::open_lib(lua(), LUA_STRLIBNAME, luaopen_string);
902989
luajit::open_lib(lua(), LUA_BITLIBNAME, luaopen_bit);
903990
luajit::open_lib(lua(), LUA_FFILIBNAME, luaopen_ffi);
904-
#ifdef DEBUG
991+
#if 1//def DEBUG
905992
luajit::open_lib(lua(), LUA_DBLIBNAME, luaopen_debug);
906993
#endif
907994
// XXX nitrocaster: with vanilla scripts, '-nojit' option requires script profiler to be disabled. The reason
@@ -928,9 +1015,8 @@ void CScriptEngine::init(ExporterFunc exporterFunc, bool loadGlobalNamespace)
9281015
}
9291016
#endif
9301017
setup_auto_load();
931-
#ifdef DEBUG
9321018
m_stack_is_ready = true;
933-
#endif
1019+
9341020
#if defined(DEBUG) && !defined(USE_LUA_STUDIO)
9351021
#if defined(USE_DEBUGGER)
9361022
if (!debugger() || !debugger()->Active())

src/xrScriptEngine/script_engine.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ class XRSCRIPTENGINE_API CScriptEngine
146146
static void on_error(lua_State* state);
147147

148148
void flush_log();
149-
void print_stack();
149+
void print_stack(lua_State* L = nullptr);
150+
151+
void LogTable(lua_State* l, pcstr S, int level);
152+
void LogVariable(lua_State* l, pcstr name, int level, bool bOpenTable);
150153

151154
using ExporterFunc = XRay::ScriptExporter::Node::ExporterFunc;
152155
CScriptEngine(bool is_editor = false);

0 commit comments

Comments
 (0)