366 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			366 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #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
 |