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
 |