summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp')
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp94
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;