1 //===-- ScriptInterpreterLua.cpp --------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ScriptInterpreterLua.h" 10 #include "Lua.h" 11 #include "lldb/Core/Debugger.h" 12 #include "lldb/Core/PluginManager.h" 13 #include "lldb/Core/StreamFile.h" 14 #include "lldb/Interpreter/CommandReturnObject.h" 15 #include "lldb/Utility/Stream.h" 16 #include "lldb/Utility/StringList.h" 17 #include "lldb/Utility/Timer.h" 18 19 using namespace lldb; 20 using namespace lldb_private; 21 22 class IOHandlerLuaInterpreter : public IOHandlerDelegate, 23 public IOHandlerEditline { 24 public: 25 IOHandlerLuaInterpreter(Debugger &debugger, 26 ScriptInterpreterLua &script_interpreter) 27 : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua", 28 ">>> ", "..> ", true, debugger.GetUseColor(), 0, 29 *this, nullptr), 30 m_script_interpreter(script_interpreter) {} 31 32 void IOHandlerInputComplete(IOHandler &io_handler, 33 std::string &data) override { 34 if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) { 35 *GetOutputStreamFileSP() << llvm::toString(std::move(error)); 36 } 37 } 38 39 private: 40 ScriptInterpreterLua &m_script_interpreter; 41 }; 42 43 ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger) 44 : ScriptInterpreter(debugger, eScriptLanguageLua), 45 m_lua(std::make_unique<Lua>()) {} 46 47 ScriptInterpreterLua::~ScriptInterpreterLua() {} 48 49 bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command, 50 CommandReturnObject *result, 51 const ExecuteScriptOptions &options) { 52 if (llvm::Error e = m_lua->Run(command)) { 53 result->AppendErrorWithFormatv( 54 "lua failed attempting to evaluate '{0}': {1}\n", command, 55 llvm::toString(std::move(e))); 56 return false; 57 } 58 return true; 59 } 60 61 void ScriptInterpreterLua::ExecuteInterpreterLoop() { 62 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 63 Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); 64 65 Debugger &debugger = m_debugger; 66 67 // At the moment, the only time the debugger does not have an input file 68 // handle is when this is called directly from lua, in which case it is 69 // both dangerous and unnecessary (not to mention confusing) to try to embed 70 // a running interpreter loop inside the already running lua interpreter 71 // loop, so we won't do it. 72 73 if (!debugger.GetInputFile().IsValid()) 74 return; 75 76 IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger, *this)); 77 debugger.PushIOHandler(io_handler_sp); 78 } 79 80 void ScriptInterpreterLua::Initialize() { 81 static llvm::once_flag g_once_flag; 82 83 llvm::call_once(g_once_flag, []() { 84 PluginManager::RegisterPlugin(GetPluginNameStatic(), 85 GetPluginDescriptionStatic(), 86 lldb::eScriptLanguageLua, CreateInstance); 87 }); 88 } 89 90 void ScriptInterpreterLua::Terminate() {} 91 92 lldb::ScriptInterpreterSP 93 ScriptInterpreterLua::CreateInstance(Debugger &debugger) { 94 return std::make_shared<ScriptInterpreterLua>(debugger); 95 } 96 97 lldb_private::ConstString ScriptInterpreterLua::GetPluginNameStatic() { 98 static ConstString g_name("script-lua"); 99 return g_name; 100 } 101 102 const char *ScriptInterpreterLua::GetPluginDescriptionStatic() { 103 return "Lua script interpreter"; 104 } 105 106 lldb_private::ConstString ScriptInterpreterLua::GetPluginName() { 107 return GetPluginNameStatic(); 108 } 109 110 uint32_t ScriptInterpreterLua::GetPluginVersion() { return 1; } 111 112 Lua &ScriptInterpreterLua::GetLua() { return *m_lua; } 113