1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 00:37:15 +01:00

Initial implementation of the internal debugging system.

This commit is contained in:
Sandu Liviu Catalin 2015-11-10 14:42:52 +02:00
parent dfc5701799
commit 3da18ee02b
6 changed files with 658 additions and 1 deletions

View File

@ -158,6 +158,8 @@
<Unit filename="../source/Config.hpp" />
<Unit filename="../source/Core.cpp" />
<Unit filename="../source/Core.hpp" />
<Unit filename="../source/Debug.cpp" />
<Unit filename="../source/Debug.hpp" />
<Unit filename="../source/Entity.cpp" />
<Unit filename="../source/Entity.hpp" />
<Unit filename="../source/Entity/Blip.cpp" />

View File

@ -1,6 +1,7 @@
#include "Base/Shared.hpp"
#include "Register.hpp"
#include "Logger.hpp"
#include "Debug.hpp"
#include "Core.hpp"
// ------------------------------------------------------------------------------------------------
@ -254,6 +255,83 @@ void LogFtl(const char * fmt, ...)
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void DbgWrn(const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
_Dbg->Wrn(NULL, NULL, fmt, args);
va_end(args);
}
void DbgErr(const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
_Dbg->Wrn(NULL, NULL, fmt, args);
va_end(args);
}
void DbgFtl(const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
_Dbg->Wrn(NULL, NULL, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void DbgWrn(const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
_Dbg->Wrn(NULL, func, fmt, args);
va_end(args);
}
void DbgErr(const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
_Dbg->Wrn(NULL, func, fmt, args);
va_end(args);
}
void DbgFtl(const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
_Dbg->Wrn(NULL, func, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void DbgWrn(const char * type, const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
_Dbg->Wrn(type, func, fmt, args);
va_end(args);
}
void DbgErr(const char * type, const char * func, const char * fmt, ...)
{
_Dbg->SetInf(type, func);
va_list args;
va_start(args, fmt);
_Dbg->Wrn(type, func, fmt, args);
va_end(args);
}
void DbgFtl(const char * type, const char * func, const char * fmt, ...)
{
_Dbg->SetInf(type, func);
va_list args;
va_start(args, fmt);
_Dbg->Wrn(type, func, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
const SQChar * ToStringF(const char * fmt, ...)
{

View File

@ -84,7 +84,7 @@ template<> inline Float64 Clamp(const Float64 val, const Float64 min, const Floa
}
/* ------------------------------------------------------------------------------------------------
* Simple functions to quickly forward logging messages without including the logging system
* Simple functions to quickly forward logging messages without including the logging system.
*/
void LogDbg(const char * fmt, ...);
void LogMsg(const char * fmt, ...);
@ -94,6 +94,21 @@ void LogWrn(const char * fmt, ...);
void LogErr(const char * fmt, ...);
void LogFtl(const char * fmt, ...);
/* ------------------------------------------------------------------------------------------------
* Simple functions to quickly forward debugging messages without including the debugging system.
*/
void DbgWrn(const char * fmt, ...);
void DbgErr(const char * fmt, ...);
void DbgFtl(const char * fmt, ...);
void DbgWrn(const char * func, const char * fmt, ...);
void DbgErr(const char * func, const char * fmt, ...);
void DbgFtl(const char * func, const char * fmt, ...);
void DbgWrn(const char * type, const char * func, const char * fmt, ...);
void DbgErr(const char * type, const char * func, const char * fmt, ...);
void DbgFtl(const char * type, const char * func, const char * fmt, ...);
/* ------------------------------------------------------------------------------------------------
* ...
*/

View File

@ -1,4 +1,5 @@
#include "Core.hpp"
#include "Debug.hpp"
#include "Logger.hpp"
#include "Entity.hpp"
#include "Register.hpp"
@ -391,6 +392,7 @@ bool Core::CreateVM()
DefaultVM::Set(m_VM);
ErrorHandling::Enable(true);
m_Scripts.clear();
_Dbg->SetVM(m_VM);
}
LogDbg("Registering the standard libraries");
@ -439,6 +441,8 @@ void Core::DestroyVM()
m_VM = nullptr;
// Close the Virtual Machine
sq_close(sq_vm);
// Remove it from the debugger as well
_Dbg->SetVM(NULL);
}
}

335
source/Debug.cpp Normal file
View File

@ -0,0 +1,335 @@
#include "Debug.hpp"
#include "Logger.hpp"
#include "Register.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdarg>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
const Debug::Pointer _Dbg = Debug::Inst();
// ------------------------------------------------------------------------------------------------
Debug::Debug()
: m_VM(NULL)
, m_Opts(PRINT_ALL | TRACE_ALL)
, m_Type()
, m_Func()
, m_RootName(_SC("root"))
, m_UnknownType(_SC("unknown"))
, m_UnknownFunc(_SC("unknown"))
{
}
// ------------------------------------------------------------------------------------------------
Debug::~Debug()
{
}
// ------------------------------------------------------------------------------------------------
void Debug::_Finalizer(Debug * ptr)
{
delete ptr; /* Assuming 'delete' checks for NULL */
}
// ------------------------------------------------------------------------------------------------
Debug::Pointer Debug::Inst()
{
if (!_Dbg)
{
return Pointer(new Debug(), &Debug::_Finalizer);
}
return Pointer(nullptr, &Debug::_Finalizer);
}
// ------------------------------------------------------------------------------------------------
HSQUIRRELVM Debug::GetVM()
{
return m_VM;
}
// ------------------------------------------------------------------------------------------------
void Debug::SetVM(HSQUIRRELVM vm)
{
m_VM = vm;
}
// ------------------------------------------------------------------------------------------------
void Debug::PrintTrace(SQInt32 lvl, SQInt32 end)
{
SQMOD_UNUSED_VAR(lvl);
SQMOD_UNUSED_VAR(end);
}
// ------------------------------------------------------------------------------------------------
void Debug::PrintCallstack(SQInt32 lvl, SQInt32 end)
{
SQMOD_UNUSED_VAR(lvl);
SQMOD_UNUSED_VAR(end);
}
// ------------------------------------------------------------------------------------------------
void Debug::SetInf(const char * type, const char * func)
{
if (type != NULL)
{
m_Type.assign(type);
}
else
{
m_Type.assign(m_UnknownType);
}
if (func != NULL)
{
m_Func.assign(func);
}
else
{
m_Func.assign(m_UnknownFunc);
}
}
// ------------------------------------------------------------------------------------------------
void Debug::Wrn(const char * type, const char * func, const char * fmt, va_list args)
{
// Store the information about the source
SetInf(type, func);
// Are warning messages enabled?
if (!(m_Opts & WRN_PRINT))
{
return;
}
// Send the message
_Log->Send(Logger::LEVEL_WRN, false, fmt, args);
// Is trace enabled for warning messages?
if (!(m_Opts & WRN_TRACE))
{
return;
}
// Do a traceback of the function call
InternalTrace();
}
// ------------------------------------------------------------------------------------------------
void Debug::Err(const char * type, const char * func, const char * fmt, va_list args)
{
// Store the information about the source
SetInf(type, func);
// Are warning messages enabled?
if (!(m_Opts & ERR_PRINT))
{
return;
}
// Send the message
_Log->Send(Logger::LEVEL_ERR, false, fmt, args);
// Is trace enabled for warning messages?
if (!(m_Opts & ERR_TRACE))
{
return;
}
// Do a traceback of the function call
InternalTrace();
}
// ------------------------------------------------------------------------------------------------
void Debug::Ftl(const char * type, const char * func, const char * fmt, va_list args)
{
// Store the information about the source
SetInf(type, func);
// Are warning messages enabled?
if (!(m_Opts & FTL_PRINT))
{
return;
}
// Send the message
_Log->Send(Logger::LEVEL_FTL, false, fmt, args);
// Is trace enabled for warning messages?
if (!(m_Opts & FTL_TRACE))
{
return;
}
// Do a traceback of the function call
InternalTrace();
}
// ------------------------------------------------------------------------------------------------
void Debug::Wrn(const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
Wrn(NULL, NULL, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void Debug::Err(const char * fmt, ...)
{
SetInf(NULL, NULL);
va_list args;
va_start(args, fmt);
Err(NULL, NULL, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void Debug::Ftl(const char * fmt, ...)
{
SetInf(NULL, NULL);
va_list args;
va_start(args, fmt);
Ftl(NULL, NULL, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void Debug::Wrn(const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
Wrn(NULL, func, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void Debug::Err(const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
Err(NULL, func, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void Debug::Ftl(const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
Ftl(NULL, func, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void Debug::Wrn(const char * type, const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
Wrn(type, func, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void Debug::Err(const char * type, const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
Err(type, func, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void Debug::Ftl(const char * type, const char * func, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
Ftl(type, func, fmt, args);
va_end(args);
}
// ------------------------------------------------------------------------------------------------
void Debug::InternalTrace()
{
// Structure that will contain informations about the queried stack level
SQStackInfos si;
// Output the base stack information before the actual trace
if (SQ_SUCCEEDED(sq_stackinfos(m_VM, 1, &si)))
{
if (m_Func.at(0) == '@')
{
_Log->SInf(" > 1 [ %s:%d > %s::%s ]", si.source ? si.source : _SC("unknown"),
si.line, m_Type.c_str(), m_Func.c_str()+1);
}
else
{
_Log->SInf(" > 1 [ %s:%d > %s::%s(...) ]", si.source ? si.source : _SC("unknown"),
si.line, m_Type.c_str(), m_Func.c_str());
}
}
// Keep outputting traceback information for the rest of the function calls
for (SQInt32 level = 2; SQ_SUCCEEDED(sq_stackinfos(m_VM, level, &si)); ++level)
{
_Log->SInf(" > %d [ %s:%d > %s::%s(...) ]", level, si.source ? si.source : _SC("unknown"),
si.line, EnvName(level).c_str(), si.funcname ? si.funcname : _SC("unknown"));
}
}
// ------------------------------------------------------------------------------------------------
String Debug::EnvName(SQInt32 level)
{
// Obtain the top of the stack
const SQInteger top = sq_gettop(m_VM);
// Name of the retrieved local
const SQChar * name = NULL;
// Attempt to find the this environment
for (SQInt32 seq = 0; (name = sq_getlocal(m_VM, level, seq)); ++seq)
{
// Is this the `this` environment?
if (strcmp(name, "this") == 0)
{
// Found it!
break;
}
// Pop this useless local from the stack
sq_pop(m_VM, 1);
}
// Have we found anything?
if (name == NULL)
{
// Unable to find the `this` environment
return m_UnknownType;
}
// Push the root table on the stack
sq_pushroottable(m_VM);
// See if the `this` environment in the current level is the root table
if (sq_cmp(m_VM) == 0)
{
// Pop everything pushed onto the stack
sq_pop(m_VM, sq_gettop(m_VM) - top);
// Return the name specified for the root table
return m_RootName;
}
// Attempt to manually call the _typeof metamethod on the `this` environment
else if (SQ_SUCCEEDED(sq_typeof(m_VM, -2)))
{
// Treat the value returned by the the _typeof metamethod as a string
Var< String > str(m_VM, -1);
// Pop everything pushed onto the stack
sq_pop(m_VM, sq_gettop(m_VM) - top);
// If it was a valid string then return it as the name
if (!str.value.empty())
{
return str.value;
}
}
// Just pop everything pushed onto the stack
else
{
sq_pop(m_VM, sq_gettop(m_VM) - top);
}
// At this point the `this` environment is not recognized
return m_UnknownType;
}
// ================================================================================================
bool Register_Dbg(HSQUIRRELVM vm)
{
SQMOD_UNUSED_VAR(vm);
return true;
}
} // Namespace:: SqMod

223
source/Debug.hpp Normal file
View File

@ -0,0 +1,223 @@
#ifndef _DEBUG_HPP_
#define _DEBUG_HPP_
// ------------------------------------------------------------------------------------------------
#include "Common.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Class meant to help with the debugging process by offering tools for extracting information.
*/
class Debug
{
/* --------------------------------------------------------------------------------------------
* Allow only the smart pointer to delete this class instance as soon as it's not needed.
*/
friend class std::unique_ptr< Debug, void(*)(Debug *) >;
protected:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Debug();
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
Debug(const Debug & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor (disabled).
*/
Debug(Debug && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~Debug();
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
Debug & operator = (const Debug & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator (disabled).
*/
Debug & operator = (Debug && o) = delete;
/* --------------------------------------------------------------------------------------------
* Called by the smart pointer to delete the instance of this class.
*/
static void _Finalizer(Debug * ptr);
public:
// --------------------------------------------------------------------------------------------
typedef std::unique_ptr< Debug, void(*)(Debug *) > Pointer;
/* --------------------------------------------------------------------------------------------
* Creates an instance of this type if one doesn't already exist and returns it.
*/
static Pointer Inst();
/* --------------------------------------------------------------------------------------------
* ...
*/
static constexpr Uint8 WRN_PRINT = (1 << 0);
static constexpr Uint8 ERR_PRINT = (1 << 1);
static constexpr Uint8 FTL_PRINT = (1 << 2);
static constexpr Uint8 PRINT_ALL = (WRN_PRINT | ERR_PRINT | FTL_PRINT);
/* --------------------------------------------------------------------------------------------
* ...
*/
static constexpr Uint8 WRN_TRACE = (1 << 3);
static constexpr Uint8 ERR_TRACE = (1 << 4);
static constexpr Uint8 FTL_TRACE = (1 << 5);
static constexpr Uint8 TRACE_ALL = (WRN_TRACE | ERR_TRACE | FTL_TRACE);
/* --------------------------------------------------------------------------------------------
* ...
*/
HSQUIRRELVM GetVM();
/* --------------------------------------------------------------------------------------------
* ...
*/
void SetVM(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* ...
*/
void PrintTrace(SQInt32 lvl, SQInt32 end);
/* --------------------------------------------------------------------------------------------
* ...
*/
void PrintCallstack(SQInt32 lvl, SQInt32 end);
/* --------------------------------------------------------------------------------------------
* ...
*/
void SetInf(const char * type, const char * func);
/* --------------------------------------------------------------------------------------------
* Throws a warning message.
*/
void Wrn(const char * type, const char * func, const char * fmt, va_list args);
/* --------------------------------------------------------------------------------------------
* Throws a error message.
*/
void Err(const char * type, const char * func, const char * fmt, va_list args);
/* --------------------------------------------------------------------------------------------
* Throws a fatal message.
*/
void Ftl(const char * type, const char * func, const char * fmt, va_list args);
/* --------------------------------------------------------------------------------------------
* Throws a warning message.
*/
void Wrn(const char * fmt, ...);
/* --------------------------------------------------------------------------------------------
* Throws a error message.
*/
void Err(const char * fmt, ...);
/* --------------------------------------------------------------------------------------------
* Throws a fatal message.
*/
void Ftl(const char * fmt, ...);
/* --------------------------------------------------------------------------------------------
* Throws a warning message.
*/
void Wrn(const char * func, const char * fmt, ...);
/* --------------------------------------------------------------------------------------------
* Throws a error message.
*/
void Err(const char * func, const char * fmt, ...);
/* --------------------------------------------------------------------------------------------
* Throws a fatal message.
*/
void Ftl(const char * func, const char * fmt, ...);
/* --------------------------------------------------------------------------------------------
* Throws a warning message.
*/
void Wrn(const char * type, const char * func, const char * fmt, ...);
/* --------------------------------------------------------------------------------------------
* Throws a error message.
*/
void Err(const char * type, const char * func, const char * fmt, ...);
/* --------------------------------------------------------------------------------------------
* Throws a fatal message.
*/
void Ftl(const char * type, const char * func, const char * fmt, ...);
protected:
/* --------------------------------------------------------------------------------------------
* Internal function used to output a traceback of function calls when issues occur.
*/
void InternalTrace();
/* --------------------------------------------------------------------------------------------
* ...
*/
String EnvName(SQInt32 level);
private:
/* --------------------------------------------------------------------------------------------
* ...
*/
HSQUIRRELVM m_VM;
/* --------------------------------------------------------------------------------------------
* ...
*/
Uint8 m_Opts;
/* --------------------------------------------------------------------------------------------
* ...
*/
String m_Type;
/* --------------------------------------------------------------------------------------------
* ...
*/
String m_Func;
/* --------------------------------------------------------------------------------------------
* ...
*/
String m_RootName;
/* --------------------------------------------------------------------------------------------
* ...
*/
String m_UnknownType;
/* --------------------------------------------------------------------------------------------
* ...
*/
String m_UnknownFunc;
};
// ------------------------------------------------------------------------------------------------
extern const Debug::Pointer _Dbg;
} // Namespace:: SqMod
#endif // _DEBUG_HPP_