1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-02-22 12:47:13 +01:00

Improve the debug information provided by the logger. Include value, size, type and other useful information where possible.

This commit is contained in:
Sandu Liviu Catalin 2019-05-17 22:54:08 +03:00
parent 7ad3790f8c
commit d52507e824
3 changed files with 115 additions and 23 deletions

View File

@ -1661,7 +1661,7 @@ struct StackStrF
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF(HSQUIRRELVM vm, SQInteger idx) StackStrF(HSQUIRRELVM vm, SQInteger idx)
: mPtr(_SC("")) : mPtr(_SC(""))
, mLen(SQ_ERROR) , mLen(0)
, mRes(SQ_OK) , mRes(SQ_OK)
, mObj() , mObj()
, mVM(vm) , mVM(vm)
@ -1741,9 +1741,9 @@ struct StackStrF
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Release any object references. /// Release any object references and assign a new target if necessary, then return self for chaining.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Release() StackStrF & Release(HSQUIRRELVM vm = nullptr, SQInteger idx = -1)
{ {
if (!sq_isnull(mObj)) if (!sq_isnull(mObj))
{ {
@ -1752,9 +1752,10 @@ struct StackStrF
mPtr = _SC(""); mPtr = _SC("");
mLen = 0; mLen = 0;
mRes = SQ_OK; mRes = SQ_OK;
mVM = nullptr; mVM = vm;
mIdx = -1; mIdx = idx;
sq_resetobject(&mObj); sq_resetobject(&mObj);
return *this;
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -215,6 +215,7 @@ Logger::Logger()
, m_ConsoleTime(false) , m_ConsoleTime(false)
, m_LogFileTime(true) , m_LogFileTime(true)
, m_CyclicLock(false) , m_CyclicLock(false)
, m_StringTruncate(32)
, m_File(nullptr) , m_File(nullptr)
, m_Filename() , m_Filename()
, m_LogCb{} , m_LogCb{}
@ -502,6 +503,7 @@ void Logger::Debug(CCStr fmt, va_list args)
SQInteger i_, seq = 0; SQInteger i_, seq = 0;
SQFloat f_; SQFloat f_;
SQUserPointer p_; SQUserPointer p_;
StackStrF ssf_;
// Begin the local variables information // Begin the local variables information
ret = m_Buffer.WriteF(0, "Locals:\n[\n"); ret = m_Buffer.WriteF(0, "Locals:\n[\n");
// Process each stack level // Process each stack level
@ -515,60 +517,116 @@ void Logger::Debug(CCStr fmt, va_list args)
switch(sq_gettype(vm, -1)) switch(sq_gettype(vm, -1))
{ {
case OT_NULL: case OT_NULL:
ret += m_Buffer.WriteF(ret, "=> [%d] NULL [%s] : ...\n", level, name); ret += m_Buffer.WriteF(ret, "=> [%d] NULL [%s]\n", level, name);
break; break;
case OT_INTEGER: case OT_INTEGER:
sq_getinteger(vm, -1, &i_); sq_getinteger(vm, -1, &i_);
ret += m_Buffer.WriteF(ret, "=> [%d] INTEGER [%s] : %d\n", level, name, i_); ret += m_Buffer.WriteF(ret, "=> [%d] INTEGER [%s] with value: " _PRINT_INT_FMT "\n", level, name, i_);
break; break;
case OT_FLOAT: case OT_FLOAT:
sq_getfloat(vm, -1, &f_); sq_getfloat(vm, -1, &f_);
ret += m_Buffer.WriteF(ret, "=> [%d] FLOAT [%s] : %f\n", level, name, f_); ret += m_Buffer.WriteF(ret, "=> [%d] FLOAT [%s] with value: %f\n", level, name, f_);
break; break;
case OT_USERPOINTER: case OT_USERPOINTER:
sq_getuserpointer(vm, -1, &p_); sq_getuserpointer(vm, -1, &p_);
ret += m_Buffer.WriteF(ret, "=> [%d] USERPOINTER [%s] : %p\n", level, name, p_); ret += m_Buffer.WriteF(ret, "=> [%d] USERPOINTER [%s] pointing at: %p\n", level, name, p_);
break; break;
case OT_STRING: case OT_STRING:
sq_getstring(vm, -1, &s_); sq_getstringandsize(vm, -1, &s_, &i_);
ret += m_Buffer.WriteF(ret, "=> [%d] STRING [%s] : %s\n", level, name, s_); if (i_ > 0) {
ret += m_Buffer.WriteF(ret, "=> [%d] STRING [%s] of " _PRINT_INT_FMT " characters: %.*s\n", level, name, i_, m_StringTruncate, s_);
} else {
ret += m_Buffer.WriteF(ret, "=> [%d] STRING [%s] empty\n", level, name);
}
break; break;
case OT_TABLE: case OT_TABLE:
ret += m_Buffer.WriteF(ret, "=> [%d] TABLE [%s] : ...\n", level, name); i_ = sq_getsize(vm, -1);
ret += m_Buffer.WriteF(ret, "=> [%d] TABLE [%s] with " _PRINT_INT_FMT " elements\n", level, name, i_);
break; break;
case OT_ARRAY: case OT_ARRAY:
ret += m_Buffer.WriteF(ret, "=> [%d] ARRAY [%s] : ...\n", level, name); i_ = sq_getsize(vm, -1);
ret += m_Buffer.WriteF(ret, "=> [%d] ARRAY [%s] with " _PRINT_INT_FMT " elements\n", level, name, i_);
break; break;
case OT_CLOSURE: case OT_CLOSURE:
ret += m_Buffer.WriteF(ret, "=> [%d] CLOSURE [%s] : ...\n", level, name); s_ = _SC("@anonymous");
if (SQ_SUCCEEDED(sq_getclosurename(vm, -1))) {
if (sq_gettype(vm, -1) != OT_NULL && SQ_SUCCEEDED(ssf_.Release(vm).Proc())) {
s_ = ssf_.mPtr;
}
sq_poptop(vm);
}
ret += m_Buffer.WriteF(ret, "=> [%d] CLOSURE [%s] with name: %s\n", level, name, s_);
break; break;
case OT_NATIVECLOSURE: case OT_NATIVECLOSURE:
ret += m_Buffer.WriteF(ret, "=> [%d] NATIVECLOSURE [%s] : ...\n", level, name); s_ = _SC("@unknown");
if (SQ_SUCCEEDED(sq_getclosurename(vm, -1))) {
if (sq_gettype(vm, -1) != OT_NULL && SQ_SUCCEEDED(ssf_.Release(vm).Proc())) {
s_ = ssf_.mPtr;
}
sq_poptop(vm);
}
ret += m_Buffer.WriteF(ret, "=> [%d] NATIVECLOSURE [%s] with name: %s\n", level, name, s_);
break; break;
case OT_GENERATOR: case OT_GENERATOR:
ret += m_Buffer.WriteF(ret, "=> [%d] GENERATOR [%s] : ...\n", level, name); ret += m_Buffer.WriteF(ret, "=> [%d] GENERATOR [%s]\n", level, name);
break; break;
case OT_USERDATA: case OT_USERDATA:
ret += m_Buffer.WriteF(ret, "=> [%d] USERDATA [%s] : ...\n", level, name); ret += m_Buffer.WriteF(ret, "=> [%d] USERDATA [%s]\n", level, name);
break; break;
case OT_THREAD: case OT_THREAD:
ret += m_Buffer.WriteF(ret, "=> [%d] THREAD [%s] : ...\n", level, name); ret += m_Buffer.WriteF(ret, "=> [%d] THREAD [%s]\n", level, name);
break; break;
case OT_CLASS: case OT_CLASS:
ret += m_Buffer.WriteF(ret, "=> [%d] CLASS [%s] : ...\n", level, name); // Brute force our way into getting the name of this class without blowing up
s_ = _SC("@unknown");
// Create a dummy, non-constructed instance and hope `_typeof` doesn't rely on member variables
if (SQ_SUCCEEDED(sq_createinstance(vm, -1))) {
// Attempt a `_typeof` on that instance
if (SQ_SUCCEEDED(sq_typeof(vm, -1))) {
if (SQ_SUCCEEDED(ssf_.Release(vm).Proc())) {
s_ = ssf_.mPtr;
}
// Pop the name object
sq_poptop(vm);
}
// Pop the dummy instance
sq_poptop(vm);
}
ret += m_Buffer.WriteF(ret, "=> [%d] CLASS [%s] of type: %s\n", level, name, s_);
break; break;
case OT_INSTANCE: case OT_INSTANCE:
ret += m_Buffer.WriteF(ret, "=> [%d] INSTANCE [%s] : ...\n", level, name); s_ = _SC("@unknown");
if (SQ_SUCCEEDED(sq_typeof(vm, -1))) {
if (SQ_SUCCEEDED(ssf_.Release(vm).Proc())) {
s_ = ssf_.mPtr;
}
sq_poptop(vm);
}
ret += m_Buffer.WriteF(ret, "=> [%d] INSTANCE [%s] of type: %s\n", level, name, s_);
break; break;
case OT_WEAKREF: case OT_WEAKREF:
ret += m_Buffer.WriteF(ret, "=> [%d] WEAKREF [%s] : ...\n", level, name); s_ = _SC("@unknown");
// Attempt to grab the value pointed by the weak reference
if (SQ_SUCCEEDED(sq_getweakrefval(vm, -1))) {
// Attempt a `_typeof` on that instance
if (SQ_SUCCEEDED(sq_typeof(vm, -1))) {
if (SQ_SUCCEEDED(ssf_.Release(vm).Proc())) {
s_ = ssf_.mPtr;
}
// Pop the name object
sq_poptop(vm);
}
// Pop the referenced value
sq_poptop(vm);
}
ret += m_Buffer.WriteF(ret, "=> [%d] WEAKREF [%s] of type: %s\n", level, name, s_);
break; break;
case OT_BOOL: case OT_BOOL:
sq_getinteger(vm, -1, &i_); sq_getinteger(vm, -1, &i_);
ret += m_Buffer.WriteF(ret, "=> [%d] BOOL [%s] : %s\n", level, name, i_ ? _SC("true") : _SC("false")); ret += m_Buffer.WriteF(ret, "=> [%d] BOOL [%s] with value: %s\n", level, name, i_ ? _SC("true") : _SC("false"));
break; break;
default: default:
ret += m_Buffer.WriteF(ret, "=> [%d] UNKNOWN [%s] : ...\n", level, name); ret += m_Buffer.WriteF(ret, "=> [%d] UNKNOWN [%s]\n", level, name);
break; break;
} }
sq_pop(vm, 1); sq_pop(vm, 1);
@ -779,6 +837,18 @@ static void SqLogSetLogFilename(CSStr filename)
Logger::Get().SetLogFilename(filename); Logger::Get().SetLogFilename(filename);
} }
// ------------------------------------------------------------------------------------------------
static SQInteger SqLogGetStringTruncate()
{
return static_cast< SQInteger >(Logger::Get().GetStringTruncate());
}
// ------------------------------------------------------------------------------------------------
static void SqLogSetStringTruncate(SQInteger nc)
{
Logger::Get().SetStringTruncate(ConvTo< Uint32 >::From(nc));
}
// ================================================================================================ // ================================================================================================
void Register_Log(HSQUIRRELVM vm) void Register_Log(HSQUIRRELVM vm)
{ {
@ -823,6 +893,8 @@ void Register_Log(HSQUIRRELVM vm)
.Func(_SC("ToggleLogFileLevel"), &SqLogToggleLogFileLevel) .Func(_SC("ToggleLogFileLevel"), &SqLogToggleLogFileLevel)
.Func(_SC("GetLogFilename"), &SqLogGetLogFilename) .Func(_SC("GetLogFilename"), &SqLogGetLogFilename)
.Func(_SC("SetLogFilename"), &SqLogSetLogFilename) .Func(_SC("SetLogFilename"), &SqLogSetLogFilename)
.Func(_SC("GetStringTruncate"), &SqLogGetStringTruncate)
.Func(_SC("SetStringTruncate"), &SqLogSetStringTruncate)
); );
} }

View File

@ -85,6 +85,9 @@ private:
bool m_LogFileTime; // Whether log file messages should be timestamped. bool m_LogFileTime; // Whether log file messages should be timestamped.
bool m_CyclicLock; // Prevent the script callback from entering a loop. bool m_CyclicLock; // Prevent the script callback from entering a loop.
// --------------------------------------------------------------------------------------------
Uint32 m_StringTruncate; // The length at which to trincate strings in debug.
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
std::FILE* m_File; // Handle to the file where the logs should be saved. std::FILE* m_File; // Handle to the file where the logs should be saved.
std::string m_Filename; // The name of the file where the logs are saved. std::string m_Filename; // The name of the file where the logs are saved.
@ -259,6 +262,22 @@ public:
} }
} }
/* --------------------------------------------------------------------------------------------
* Retrieve the number of characters that strings will be truncated in debug output.
*/
Uint32 GetStringTruncate() const
{
return m_StringTruncate;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of characters that strings will be truncated in debug output.
*/
void SetStringTruncate(Uint32 nc)
{
m_StringTruncate = nc;
}
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* Retrieve the log file name. * Retrieve the log file name.
*/ */