diff options
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp')
| -rw-r--r-- | lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp | 94 |
1 files changed, 86 insertions, 8 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp index 239b409ac695..1dbadb90813c 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp @@ -17,23 +17,33 @@ #include "lldb/Utility/Stream.h" #include "lldb/Utility/StringList.h" #include "lldb/Utility/Timer.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/FormatAdapters.h" #include <memory> +#include <vector> using namespace lldb; using namespace lldb_private; LLDB_PLUGIN_DEFINE(ScriptInterpreterLua) +enum ActiveIOHandler { + eIOHandlerNone, + eIOHandlerBreakpoint, + eIOHandlerWatchpoint +}; + class IOHandlerLuaInterpreter : public IOHandlerDelegate, public IOHandlerEditline { public: IOHandlerLuaInterpreter(Debugger &debugger, - ScriptInterpreterLua &script_interpreter) + ScriptInterpreterLua &script_interpreter, + ActiveIOHandler active_io_handler = eIOHandlerNone) : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua", ">>> ", "..> ", true, debugger.GetUseColor(), 0, *this, nullptr), - m_script_interpreter(script_interpreter) { + m_script_interpreter(script_interpreter), + m_active_io_handler(active_io_handler) { llvm::cantFail(m_script_interpreter.GetLua().ChangeIO( debugger.GetOutputFile().GetStream(), debugger.GetErrorFile().GetStream())); @@ -44,20 +54,79 @@ public: llvm::cantFail(m_script_interpreter.LeaveSession()); } - void IOHandlerInputComplete(IOHandler &io_handler, - std::string &data) override { - if (llvm::StringRef(data).rtrim() == "quit") { - io_handler.SetIsDone(true); + void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { + const char *instructions = nullptr; + switch (m_active_io_handler) { + case eIOHandlerNone: + case eIOHandlerWatchpoint: + break; + case eIOHandlerBreakpoint: + instructions = "Enter your Lua command(s). Type 'quit' to end.\n" + "The commands are compiled as the body of the following " + "Lua function\n" + "function (frame, bp_loc, ...) end\n"; + SetPrompt(llvm::StringRef("..> ")); + break; + } + if (instructions == nullptr) return; + if (interactive) + *io_handler.GetOutputStreamFileSP() << instructions; + } + + bool IOHandlerIsInputComplete(IOHandler &io_handler, + StringList &lines) override { + size_t last = lines.GetSize() - 1; + if (IsQuitCommand(lines.GetStringAtIndex(last))) { + if (m_active_io_handler == eIOHandlerBreakpoint) + lines.DeleteStringAtIndex(last); + return true; + } + StreamString str; + lines.Join("\n", str); + if (llvm::Error E = + m_script_interpreter.GetLua().CheckSyntax(str.GetString())) { + std::string error_str = toString(std::move(E)); + // Lua always errors out to incomplete code with '<eof>' + return error_str.find("<eof>") == std::string::npos; } + // The breakpoint handler only exits with a explicit 'quit' + return m_active_io_handler != eIOHandlerBreakpoint; + } - if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) { - *GetOutputStreamFileSP() << llvm::toString(std::move(error)); + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) override { + switch (m_active_io_handler) { + case eIOHandlerBreakpoint: { + auto *bp_options_vec = static_cast<std::vector<BreakpointOptions *> *>( + io_handler.GetUserData()); + for (auto *bp_options : *bp_options_vec) { + Status error = m_script_interpreter.SetBreakpointCommandCallback( + bp_options, data.c_str()); + if (error.Fail()) + *io_handler.GetErrorStreamFileSP() << error.AsCString() << '\n'; + } + io_handler.SetIsDone(true); + } break; + case eIOHandlerWatchpoint: + io_handler.SetIsDone(true); + break; + case eIOHandlerNone: + if (IsQuitCommand(data)) { + io_handler.SetIsDone(true); + return; + } + if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) + *io_handler.GetErrorStreamFileSP() << toString(std::move(error)); + break; } } private: ScriptInterpreterLua &m_script_interpreter; + ActiveIOHandler m_active_io_handler; + + bool IsQuitCommand(llvm::StringRef cmd) { return cmd.rtrim() == "quit"; } }; ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger) @@ -205,6 +274,15 @@ bool ScriptInterpreterLua::BreakpointCallbackFunction( return *BoolOrErr; } +void ScriptInterpreterLua::CollectDataForBreakpointCommandCallback( + std::vector<BreakpointOptions *> &bp_options_vec, + CommandReturnObject &result) { + IOHandlerSP io_handler_sp( + new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerBreakpoint)); + io_handler_sp->SetUserData(&bp_options_vec); + m_debugger.RunIOHandlerAsync(io_handler_sp); +} + Status ScriptInterpreterLua::SetBreakpointCommandCallback( BreakpointOptions *bp_options, const char *command_body_text) { Status error; |
