diff options
| author | Jonas Devlieghere <jonas@devlieghere.com> | 2019-12-07 17:35:31 -0800 |
|---|---|---|
| committer | Jonas Devlieghere <jonas@devlieghere.com> | 2019-12-20 11:19:47 -0800 |
| commit | 2861324208e13846eb306f01b32448f94177cc3b (patch) | |
| tree | b47908336cb73f749fb4799dc5e877817ded4f0b /lldb/source | |
| parent | 2a42a5a2f4144cd99812ad0d230480f94a1d1c92 (diff) | |
| download | bcm5719-llvm-2861324208e13846eb306f01b32448f94177cc3b.tar.gz bcm5719-llvm-2861324208e13846eb306f01b32448f94177cc3b.zip | |
[lldb/Lua] Implement a Simple Lua Script Interpreter Prototype
This implements a very elementary Lua script interpreter. It supports
running a single command as well as running interactively. It uses
editline if available. It's still missing a bunch of stuff though. Some
things that I intentionally ingored for now are that I/O isn't properly
hooked up (so every print goes to stdout) and the non-editline support
which is not handling a bunch of corner cases. The latter is a matter of
reusing existing code in the Python interpreter.
Discussion on the mailing list:
http://lists.llvm.org/pipermail/lldb-dev/2019-December/015812.html
Differential revision: https://reviews.llvm.org/D71234
Diffstat (limited to 'lldb/source')
4 files changed, 120 insertions, 12 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Lua/CMakeLists.txt index 51161638a3d..498bd978395 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Lua/CMakeLists.txt +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/CMakeLists.txt @@ -1,7 +1,11 @@ add_lldb_library(lldbPluginScriptInterpreterLua PLUGIN + Lua.cpp ScriptInterpreterLua.cpp LINK_LIBS lldbCore lldbInterpreter - )
\ No newline at end of file + ) + +target_include_directories(lldbPluginScriptInterpreterLua PUBLIC ${LUA_INCLUDE_DIR}) +target_link_libraries(lldbPluginScriptInterpreterLua INTERFACE ${LUA_LIBRARIES}) diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp new file mode 100644 index 00000000000..a908ef08673 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp @@ -0,0 +1,27 @@ +//===-- Lua.cpp -----------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Lua.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace lldb_private; + +llvm::Error Lua::Run(llvm::StringRef buffer) { + int error = + luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer") || + lua_pcall(m_lua_state, 0, 0, 0); + if (!error) + return llvm::Error::success(); + + llvm::Error e = llvm::make_error<llvm::StringError>( + llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)), + llvm::inconvertibleErrorCode()); + // Pop error message from the stack. + lua_pop(m_lua_state, 1); + return e; +} diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h new file mode 100644 index 00000000000..50b7ade4dc4 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h @@ -0,0 +1,39 @@ +//===-- ScriptInterpreterLua.h ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Lua_h_ +#define liblldb_Lua_h_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +#include "lua.hpp" + +namespace lldb_private { + +class Lua { +public: + Lua() : m_lua_state(luaL_newstate()) { + assert(m_lua_state); + luaL_openlibs(m_lua_state); + } + + ~Lua() { + assert(m_lua_state); + luaL_openlibs(m_lua_state); + } + + llvm::Error Run(llvm::StringRef buffer); + +private: + lua_State *m_lua_state; +}; + +} // namespace lldb_private + +#endif // liblldb_Lua_h_ diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp index 78aa91a6959..b3f1689909f 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp @@ -7,35 +7,73 @@ //===----------------------------------------------------------------------===// #include "ScriptInterpreterLua.h" +#include "Lua.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StringList.h" - -#include "llvm/Support/Threading.h" - -#include <mutex> +#include "lldb/Utility/Timer.h" using namespace lldb; using namespace lldb_private; +class IOHandlerLuaInterpreter : public IOHandlerDelegate, + public IOHandlerEditline { +public: + IOHandlerLuaInterpreter(Debugger &debugger) + : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua", + ">>> ", "..> ", true, debugger.GetUseColor(), 0, + *this, nullptr), + m_lua() {} + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) override { + if (llvm::Error error = m_lua.Run(data)) { + *GetOutputStreamFileSP() << llvm::toString(std::move(error)); + } + } + +private: + Lua m_lua; +}; + ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger) : ScriptInterpreter(debugger, eScriptLanguageLua) {} ScriptInterpreterLua::~ScriptInterpreterLua() {} bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command, - CommandReturnObject *, - const ExecuteScriptOptions &) { - m_debugger.GetErrorStream().PutCString( - "error: the lua script interpreter is not yet implemented.\n"); - return false; + CommandReturnObject *result, + const ExecuteScriptOptions &options) { + Lua l; + if (llvm::Error e = l.Run(command)) { + result->AppendErrorWithFormatv( + "lua failed attempting to evaluate '{0}': {1}\n", command, + llvm::toString(std::move(e))); + return false; + } + return true; } void ScriptInterpreterLua::ExecuteInterpreterLoop() { - m_debugger.GetErrorStream().PutCString( - "error: the lua script interpreter is not yet implemented.\n"); + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); + Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); + + Debugger &debugger = m_debugger; + + // At the moment, the only time the debugger does not have an input file + // handle is when this is called directly from lua, in which case it is + // both dangerous and unnecessary (not to mention confusing) to try to embed + // a running interpreter loop inside the already running lua interpreter + // loop, so we won't do it. + + if (!debugger.GetInputFile().IsValid()) + return; + + IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger)); + debugger.PushIOHandler(io_handler_sp); } void ScriptInterpreterLua::Initialize() { |

