366 lines
10 KiB
C
Raw Normal View History

2025-01-22 16:18:30 +01:00
#ifndef HX_DEBUG_H
#define HX_DEBUG_H
#include <hxcpp.h>
// Some functions used by AdvancedDebug.cpp
// Returns the thread number of the calling thread
HXCPP_EXTERN_CLASS_ATTRIBUTES
int __hxcpp_GetCurrentThreadNumber();
namespace hx
{
#ifdef HXCPP_DEBUGGER
template<typename T> struct StackVariableWrapper
{
typedef T wrapper;
};
template<> struct StackVariableWrapper<size_t>
{
#ifdef HXCPP_M64
typedef cpp::Int64 wrapper;
#else
typedef int wrapper;
#endif
};
template<typename T> struct StackVariableWrapper<T *>
{
typedef cpp::Pointer<T> wrapper;
};
class StackVariable
{
public:
const char *mHaxeName;
bool mIsArg;
StackVariable *mNext;
template<typename T>
StackVariable(StackVariable *&inHead, bool inIsArg,
const char *inHaxeName, T *inCppVar)
: mHaxeName(inHaxeName), mIsArg(inIsArg), mHead(inHead),
mCppVar((void *) inCppVar)
{
mGetOrSetFunction = GetOrSetFunction<T>;
mNext = mHead;
mHead = this;
}
StackVariable(StackVariable *&inHead, bool inIsArg,
const char *inHaxeName, hx::Object **inCppVar)
: mHaxeName(inHaxeName), mIsArg(inIsArg), mHead(inHead),
mCppVar((void *) inCppVar)
{
mGetOrSetFunction = GetOrSetFunctionHxObject;
mNext = mHead;
mHead = this;
}
// For StackThis
template<typename T>
StackVariable(StackVariable *&inHead, T *inCppVar)
: mHaxeName("this"), mIsArg(true), mHead(inHead),
mCppVar((void *) inCppVar)
{
mNext = mHead;
mHead = this;
}
~StackVariable()
{
// Stack variables are always deleted in the reverse order that they
// are created, so a simple pop_front is sufficient; no need to hunt
// for and remove the variable, it's always in the front ...
mHead = mNext;
}
operator Dynamic()
{
return mGetOrSetFunction(true, mCppVar, 0);
}
StackVariable &operator =(Dynamic &other)
{
(void) mGetOrSetFunction(false, mCppVar, &other);
return *this;
}
protected:
typedef Dynamic (*GetOrSetFunctionType)(bool, void *, Dynamic *);
GetOrSetFunctionType mGetOrSetFunction;
private:
template<typename T>
static Dynamic GetOrSetFunction(bool get, void *ptr, Dynamic *dynamic)
{
typedef typename StackVariableWrapper<T>::wrapper Wrap;
if (get) {
return Wrap(* (T *) ptr);
}
else {
* (T *) ptr = Wrap(*dynamic);
return null();
}
}
static Dynamic GetOrSetFunctionHxObject(bool get, void *ptr, Dynamic *dynamic)
{
if (get) {
return * (hx::Object **) ptr;
}
else {
* (hx::Object **)ptr = dynamic->mPtr;
return null();
}
}
StackVariable *&mHead;
void *mCppVar;
};
class StackThis : public StackVariable
{
public:
template<typename T>
StackThis(StackVariable *&inHead, T *inThis)
: StackVariable(inHead, inThis)
{
mGetOrSetFunction = GetFunction<T>;
}
template<typename T>
StackThis(StackVariable *&inHead, hx::ObjectPtr<T> &inThis)
: StackVariable(inHead, &inThis.mPtr)
{
mGetOrSetFunction = GetObjectPtr<T>;
}
template<typename T>
static Dynamic GetObjectPtr(bool get, void *ptr, Dynamic *val)
{
if (get) {
return *(hx::Object **) ptr;
}
else {
return null();
}
}
template<typename T>
static Dynamic GetFunction(bool get, void *ptr, Dynamic *val)
{
if (get) {
return (T *) ptr;
}
else {
return null();
}
}
};
class StackCatchable
{
public:
StackCatchable *mNext;
template<typename T>
StackCatchable(StackFrame &frame, T * /* dummy required by template*/)
: mFrame(frame)
{
mNext = frame.catchables;
frame.catchables = this;
mTestFunction = TestFunction<T>;
}
~StackCatchable()
{
mFrame.catchables = mNext;
}
bool Catches(Dynamic e) const
{
return mTestFunction(e);
}
private:
template<typename T>
static bool TestFunction(Dynamic e)
{
return e.IsClass<T>();
}
StackFrame &mFrame;
bool (*mTestFunction)(Dynamic e);
};
#endif // HXCPP_DEBUGGER
} // end namespace hx
void __hxcpp_dbg_getScriptableFiles( Array< ::String> ioPaths );
void __hxcpp_dbg_getScriptableFilesFullPath( Array< ::String> ioPaths );
void __hxcpp_dbg_getScriptableClasses( Array< ::String> ioClasses );
#ifdef HXCPP_DEBUGGER
namespace hx
{
// These must match the values present in cpp.vm.Debugger
enum ThreadEvent
{
THREAD_CREATED = 1,
THREAD_TERMINATED = 2,
THREAD_STARTED = 3,
THREAD_STOPPED = 4
};
enum StepType
{
STEP_NONE = 0, // Not present or needed in cpp.vm.Debugger
STEP_INTO = 1,
STEP_OVER = 2,
STEP_OUT = 3
};
} // end namespace hx
// The following functions are called directly, and only, by the haxe standard
// library's cpp.vm.Debugger.hx class
void __hxcpp_dbg_setEventNotificationHandler(Dynamic handler);
void __hxcpp_dbg_enableCurrentThreadDebugging(bool enable);
int __hxcpp_dbg_getCurrentThreadNumber();
Array< ::String> __hxcpp_dbg_getFiles();
Array< ::String> __hxcpp_dbg_getFilesFullPath();
Array< ::String> __hxcpp_dbg_getClasses();
Array<Dynamic> __hxcpp_dbg_getThreadInfos();
Dynamic __hxcpp_dbg_getThreadInfo(int threadNumber, bool unsafe);
int __hxcpp_dbg_addFileLineBreakpoint(String fileName, int lineNumber);
int __hxcpp_dbg_addClassFunctionBreakpoint(String className,
String functionName);
void __hxcpp_dbg_deleteAllBreakpoints();
void __hxcpp_dbg_deleteBreakpoint(int number);
void __hxcpp_dbg_breakNow(bool wait);
void __hxcpp_dbg_continueThreads(int threadNumber, int count);
void __hxcpp_dbg_stepThread(int threadNumber, int stepType, int stepCount);
Array<Dynamic> __hxcpp_dbg_getStackVariables(int threadNumber,
int stackFrameNumber,
bool unsafe,
Dynamic markThreadNotStopped);
Dynamic __hxcpp_dbg_getStackVariableValue(int threadNumber,
int stackFrameNumber,
String name,
bool unsafe,
Dynamic markNonexistent,
Dynamic markThreadNotStopped);
Dynamic __hxcpp_dbg_setStackVariableValue(int threadNumber,
int stackFrameNumber,
String name, Dynamic value,
bool unsafe,
Dynamic markNonexistent,
Dynamic markThreadNotStopped);
void __hxcpp_dbg_setNewParameterFunction(Dynamic function);
void __hxcpp_dbg_setNewStackFrameFunction(Dynamic function);
void __hxcpp_dbg_setNewThreadInfoFunction(Dynamic function);
void __hxcpp_dbg_setAddParameterToStackFrameFunction(Dynamic function);
void __hxcpp_dbg_setAddStackFrameToThreadInfoFunction(Dynamic function);
bool __hxcpp_dbg_fix_critical_error(String inErr);
// The following functions are called by Thread.cpp to notify of thread
// created and terminated
void __hxcpp_dbg_threadCreatedOrTerminated(int threadNumber, bool created);
// The following is called by the stack macros, but only if
// HXCPP_DEBUGGER is set
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic __hxcpp_dbg_checkedThrow(Dynamic toThrow);
HXCPP_EXTERN_CLASS_ATTRIBUTES
Dynamic __hxcpp_dbg_checkedRethrow(Dynamic toThrow);
#else // !HXCPP_DEBUGGER
// If no debugger, provide empty implementations of the debugging functions
inline void __hxcpp_dbg_setEventNotificationHandler(Dynamic)
{ hx::Throw("Debugging is not enabled for this program; try\n"
"rebuilding it with the -D HXCPP_DEBUGGER option"); }
inline void __hxcpp_dbg_enableCurrentThreadDebugging(bool) { }
inline int __hxcpp_dbg_getCurrentThreadNumber() { return -1; }
inline Array< ::String> __hxcpp_dbg_getFiles()
{ return Array_obj< String>::__new(); }
inline Array< ::String> __hxcpp_dbg_getFilesFullPath()
{ return Array_obj< String>::__new(); }
inline Array< ::String> __hxcpp_dbg_getClasses()
{ return Array_obj< String>::__new(); }
inline Array<Dynamic> __hxcpp_dbg_getThreadInfos()
{ return Array_obj< ::Dynamic>::__new(); }
inline Dynamic __hxcpp_dbg_getThreadInfo(int, bool) { return null(); }
inline int __hxcpp_dbg_addFileLineBreakpoint(String, int) { return -1; }
inline int __hxcpp_dbg_addClassFunctionBreakpoint(String, String)
{ return -1; }
inline void __hxcpp_dbg_deleteAllBreakpoints() { }
inline void __hxcpp_dbg_deleteBreakpoint(int) { }
inline void __hxcpp_dbg_breakNow(bool) { }
inline void __hxcpp_dbg_continueThreads(int, int) { }
inline void __hxcpp_dbg_stepThread(int, int, int) { }
inline Array<Dynamic> __hxcpp_dbg_getStackVariables(int, int, bool, Dynamic)
{ return Array_obj< String>::__new(); }
inline Dynamic __hxcpp_dbg_getStackVariableValue(int, int, String, bool,
Dynamic, Dynamic)
{ return null(); }
inline Dynamic __hxcpp_dbg_setStackVariableValue(int, int, String, Dynamic,
bool, Dynamic, Dynamic)
{ return null(); }
inline void __hxcpp_dbg_setNewParameterFunction(Dynamic) { }
inline void __hxcpp_dbg_setNewStackFrameFunction(Dynamic) { }
inline void __hxcpp_dbg_setNewThreadInfoFunction(Dynamic) { }
inline void __hxcpp_dbg_setAddParameterToStackFrameFunction(Dynamic) { }
inline void __hxcpp_dbg_setAddStackFrameToThreadInfoFunction(Dynamic) { }
// The following functions are called by Thread.cpp to notify of thread
// created and terminated
inline void __hxcpp_dbg_threadCreatedOrTerminated(int, bool) { }
inline Dynamic __hxcpp_dbg_checkedThrow(Dynamic toThrow) { return hx::Throw(toThrow); }
inline Dynamic __hxcpp_dbg_checkedRethrow(Dynamic toThrow) { return hx::Rethrow(toThrow); }
#endif // HXCPP_DEBUGGER
#endif // HX_DEBUG_H