#ifndef HX_DEBUG_H #define HX_DEBUG_H #include // 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 struct StackVariableWrapper { typedef T wrapper; }; template<> struct StackVariableWrapper { #ifdef HXCPP_M64 typedef cpp::Int64 wrapper; #else typedef int wrapper; #endif }; template struct StackVariableWrapper { typedef cpp::Pointer wrapper; }; class StackVariable { public: const char *mHaxeName; bool mIsArg; StackVariable *mNext; template StackVariable(StackVariable *&inHead, bool inIsArg, const char *inHaxeName, T *inCppVar) : mHaxeName(inHaxeName), mIsArg(inIsArg), mHead(inHead), mCppVar((void *) inCppVar) { mGetOrSetFunction = GetOrSetFunction; 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 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 static Dynamic GetOrSetFunction(bool get, void *ptr, Dynamic *dynamic) { typedef typename StackVariableWrapper::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 StackThis(StackVariable *&inHead, T *inThis) : StackVariable(inHead, inThis) { mGetOrSetFunction = GetFunction; } template StackThis(StackVariable *&inHead, hx::ObjectPtr &inThis) : StackVariable(inHead, &inThis.mPtr) { mGetOrSetFunction = GetObjectPtr; } template static Dynamic GetObjectPtr(bool get, void *ptr, Dynamic *val) { if (get) { return *(hx::Object **) ptr; } else { return null(); } } template static Dynamic GetFunction(bool get, void *ptr, Dynamic *val) { if (get) { return (T *) ptr; } else { return null(); } } }; class StackCatchable { public: StackCatchable *mNext; template StackCatchable(StackFrame &frame, T * /* dummy required by template*/) : mFrame(frame) { mNext = frame.catchables; frame.catchables = this; mTestFunction = TestFunction; } ~StackCatchable() { mFrame.catchables = mNext; } bool Catches(Dynamic e) const { return mTestFunction(e); } private: template static bool TestFunction(Dynamic e) { return e.IsClass(); } 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 __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 __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 __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 __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