mirror of
				https://github.com/VCMP-SqMod/SqMod.git
				synced 2025-10-30 22:07:18 +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:
		| @@ -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; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -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) | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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. | ||||||
|     */ |     */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user