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 : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua", 27 ">>> ", "..> ", true, debugger.GetUseColor(), 0, 28 *this, nullptr), 29 m_lua() {} 30 31 void IOHandlerInputComplete(IOHandler &io_handler, 32 std::string &data) override { 33 if (llvm::Error error = m_lua.Run(data)) { 34 *GetOutputStreamFileSP() << llvm::toString(std::move(error)); 35 } 36 } 37 38 private: 39 Lua m_lua; 40 }; 41 42 ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger) 43 : ScriptInterpreter(debugger, eScriptLanguageLua) {} 44 45 ScriptInterpreterLua::~ScriptInterpreterLua() {} 46 47 bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command, 48 CommandReturnObject *result, 49 const ExecuteScriptOptions &options) { 50 Lua l; 51 if (llvm::Error e = l.Run(command)) { 52 result->AppendErrorWithFormatv( 53 "lua failed attempting to evaluate '{0}': {1}\n", command, 54 llvm::toString(std::move(e))); 55 return false; 56 } 57 return true; 58 } 59 60 void ScriptInterpreterLua::ExecuteInterpreterLoop() { 61 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 62 Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); 63 64 Debugger &debugger = m_debugger; 65 66 // At the moment, the only time the debugger does not have an input file 67 // handle is when this is called directly from lua, in which case it is 68 // both dangerous and unnecessary (not to mention confusing) to try to embed 69 // a running interpreter loop inside the already running lua interpreter 70 // loop, so we won't do it. 71 72 if (!debugger.GetInputFile().IsValid()) 73 return; 74 75 IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger)); 76 debugger.PushIOHandler(io_handler_sp); 77 } 78 79 void ScriptInterpreterLua::Initialize() { 80 static llvm::once_flag g_once_flag; 81 82 llvm::call_once(g_once_flag, []() { 83 PluginManager::RegisterPlugin(GetPluginNameStatic(), 84 GetPluginDescriptionStatic(), 85 lldb::eScriptLanguageLua, CreateInstance); 86 }); 87 } 88 89 void ScriptInterpreterLua::Terminate() {} 90 91 lldb::ScriptInterpreterSP 92 ScriptInterpreterLua::CreateInstance(Debugger &debugger) { 93 return std::make_shared<ScriptInterpreterLua>(debugger); 94 } 95 96 lldb_private::ConstString ScriptInterpreterLua::GetPluginNameStatic() { 97 static ConstString g_name("script-lua"); 98 return g_name; 99 } 100 101 const char *ScriptInterpreterLua::GetPluginDescriptionStatic() { 102 return "Lua script interpreter"; 103 } 104 105 lldb_private::ConstString ScriptInterpreterLua::GetPluginName() { 106 return GetPluginNameStatic(); 107 } 108 109 uint32_t ScriptInterpreterLua::GetPluginVersion() { return 1; } 110