1480093f4SDimitry Andric //===-- ScriptInterpreterLua.cpp --------------------------------*- C++ -*-===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric 9480093f4SDimitry Andric #include "ScriptInterpreterLua.h" 10480093f4SDimitry Andric #include "Lua.h" 11480093f4SDimitry Andric #include "lldb/Core/Debugger.h" 12480093f4SDimitry Andric #include "lldb/Core/PluginManager.h" 13480093f4SDimitry Andric #include "lldb/Core/StreamFile.h" 14480093f4SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 15480093f4SDimitry Andric #include "lldb/Utility/Stream.h" 16480093f4SDimitry Andric #include "lldb/Utility/StringList.h" 17480093f4SDimitry Andric #include "lldb/Utility/Timer.h" 18480093f4SDimitry Andric 19480093f4SDimitry Andric using namespace lldb; 20480093f4SDimitry Andric using namespace lldb_private; 21480093f4SDimitry Andric 22480093f4SDimitry Andric class IOHandlerLuaInterpreter : public IOHandlerDelegate, 23480093f4SDimitry Andric public IOHandlerEditline { 24480093f4SDimitry Andric public: 25480093f4SDimitry Andric IOHandlerLuaInterpreter(Debugger &debugger, 26480093f4SDimitry Andric ScriptInterpreterLua &script_interpreter) 27480093f4SDimitry Andric : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua", 28480093f4SDimitry Andric ">>> ", "..> ", true, debugger.GetUseColor(), 0, 29480093f4SDimitry Andric *this, nullptr), 30480093f4SDimitry Andric m_script_interpreter(script_interpreter) { 31480093f4SDimitry Andric llvm::cantFail(m_script_interpreter.EnterSession(debugger.GetID())); 32480093f4SDimitry Andric } 33480093f4SDimitry Andric 34480093f4SDimitry Andric ~IOHandlerLuaInterpreter() { 35480093f4SDimitry Andric llvm::cantFail(m_script_interpreter.LeaveSession()); 36480093f4SDimitry Andric } 37480093f4SDimitry Andric 38480093f4SDimitry Andric void IOHandlerInputComplete(IOHandler &io_handler, 39480093f4SDimitry Andric std::string &data) override { 40480093f4SDimitry Andric if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) { 41480093f4SDimitry Andric *GetOutputStreamFileSP() << llvm::toString(std::move(error)); 42480093f4SDimitry Andric } 43480093f4SDimitry Andric } 44480093f4SDimitry Andric 45480093f4SDimitry Andric private: 46480093f4SDimitry Andric ScriptInterpreterLua &m_script_interpreter; 47480093f4SDimitry Andric }; 48480093f4SDimitry Andric 49480093f4SDimitry Andric ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger) 50480093f4SDimitry Andric : ScriptInterpreter(debugger, eScriptLanguageLua), 51480093f4SDimitry Andric m_lua(std::make_unique<Lua>()) {} 52480093f4SDimitry Andric 53480093f4SDimitry Andric ScriptInterpreterLua::~ScriptInterpreterLua() {} 54480093f4SDimitry Andric 55480093f4SDimitry Andric bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command, 56480093f4SDimitry Andric CommandReturnObject *result, 57480093f4SDimitry Andric const ExecuteScriptOptions &options) { 58480093f4SDimitry Andric if (llvm::Error e = m_lua->Run(command)) { 59480093f4SDimitry Andric result->AppendErrorWithFormatv( 60480093f4SDimitry Andric "lua failed attempting to evaluate '{0}': {1}\n", command, 61480093f4SDimitry Andric llvm::toString(std::move(e))); 62480093f4SDimitry Andric return false; 63480093f4SDimitry Andric } 64480093f4SDimitry Andric return true; 65480093f4SDimitry Andric } 66480093f4SDimitry Andric 67480093f4SDimitry Andric void ScriptInterpreterLua::ExecuteInterpreterLoop() { 68480093f4SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 69480093f4SDimitry Andric Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); 70480093f4SDimitry Andric 71480093f4SDimitry Andric Debugger &debugger = m_debugger; 72480093f4SDimitry Andric 73480093f4SDimitry Andric // At the moment, the only time the debugger does not have an input file 74480093f4SDimitry Andric // handle is when this is called directly from lua, in which case it is 75480093f4SDimitry Andric // both dangerous and unnecessary (not to mention confusing) to try to embed 76480093f4SDimitry Andric // a running interpreter loop inside the already running lua interpreter 77480093f4SDimitry Andric // loop, so we won't do it. 78480093f4SDimitry Andric 79480093f4SDimitry Andric if (!debugger.GetInputFile().IsValid()) 80480093f4SDimitry Andric return; 81480093f4SDimitry Andric 82480093f4SDimitry Andric IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger, *this)); 83480093f4SDimitry Andric debugger.PushIOHandler(io_handler_sp); 84480093f4SDimitry Andric } 85480093f4SDimitry Andric 86480093f4SDimitry Andric bool ScriptInterpreterLua::LoadScriptingModule( 87480093f4SDimitry Andric const char *filename, bool init_session, lldb_private::Status &error, 88480093f4SDimitry Andric StructuredData::ObjectSP *module_sp) { 89480093f4SDimitry Andric 90480093f4SDimitry Andric if (llvm::Error e = m_lua->LoadModule(filename)) { 91480093f4SDimitry Andric error.SetErrorStringWithFormatv("lua failed to import '{0}': {1}\n", 92480093f4SDimitry Andric filename, llvm::toString(std::move(e))); 93480093f4SDimitry Andric return false; 94480093f4SDimitry Andric } 95480093f4SDimitry Andric return true; 96480093f4SDimitry Andric } 97480093f4SDimitry Andric 98480093f4SDimitry Andric void ScriptInterpreterLua::Initialize() { 99480093f4SDimitry Andric static llvm::once_flag g_once_flag; 100480093f4SDimitry Andric 101480093f4SDimitry Andric llvm::call_once(g_once_flag, []() { 102480093f4SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 103480093f4SDimitry Andric GetPluginDescriptionStatic(), 104480093f4SDimitry Andric lldb::eScriptLanguageLua, CreateInstance); 105480093f4SDimitry Andric }); 106480093f4SDimitry Andric } 107480093f4SDimitry Andric 108480093f4SDimitry Andric void ScriptInterpreterLua::Terminate() {} 109480093f4SDimitry Andric 110480093f4SDimitry Andric llvm::Error ScriptInterpreterLua::EnterSession(user_id_t debugger_id) { 111480093f4SDimitry Andric if (m_session_is_active) 112480093f4SDimitry Andric return llvm::Error::success(); 113480093f4SDimitry Andric 114480093f4SDimitry Andric const char *fmt_str = 115480093f4SDimitry Andric "lldb.debugger = lldb.SBDebugger.FindDebuggerWithID({0}); " 116480093f4SDimitry Andric "lldb.target = lldb.debugger:GetSelectedTarget(); " 117480093f4SDimitry Andric "lldb.process = lldb.target:GetProcess(); " 118480093f4SDimitry Andric "lldb.thread = lldb.process:GetSelectedThread(); " 119480093f4SDimitry Andric "lldb.frame = lldb.thread:GetSelectedFrame()"; 120480093f4SDimitry Andric return m_lua->Run(llvm::formatv(fmt_str, debugger_id).str()); 121480093f4SDimitry Andric } 122480093f4SDimitry Andric 123480093f4SDimitry Andric llvm::Error ScriptInterpreterLua::LeaveSession() { 124480093f4SDimitry Andric if (!m_session_is_active) 125480093f4SDimitry Andric return llvm::Error::success(); 126480093f4SDimitry Andric 127480093f4SDimitry Andric m_session_is_active = false; 128480093f4SDimitry Andric 129480093f4SDimitry Andric llvm::StringRef str = "lldb.debugger = nil; " 130480093f4SDimitry Andric "lldb.target = nil; " 131480093f4SDimitry Andric "lldb.process = nil; " 132480093f4SDimitry Andric "lldb.thread = nil; " 133480093f4SDimitry Andric "lldb.frame = nil"; 134480093f4SDimitry Andric return m_lua->Run(str); 135480093f4SDimitry Andric } 136480093f4SDimitry Andric 137480093f4SDimitry Andric lldb::ScriptInterpreterSP 138480093f4SDimitry Andric ScriptInterpreterLua::CreateInstance(Debugger &debugger) { 139480093f4SDimitry Andric return std::make_shared<ScriptInterpreterLua>(debugger); 140480093f4SDimitry Andric } 141480093f4SDimitry Andric 142480093f4SDimitry Andric lldb_private::ConstString ScriptInterpreterLua::GetPluginNameStatic() { 143480093f4SDimitry Andric static ConstString g_name("script-lua"); 144480093f4SDimitry Andric return g_name; 145480093f4SDimitry Andric } 146480093f4SDimitry Andric 147480093f4SDimitry Andric const char *ScriptInterpreterLua::GetPluginDescriptionStatic() { 148480093f4SDimitry Andric return "Lua script interpreter"; 149480093f4SDimitry Andric } 150480093f4SDimitry Andric 151480093f4SDimitry Andric lldb_private::ConstString ScriptInterpreterLua::GetPluginName() { 152480093f4SDimitry Andric return GetPluginNameStatic(); 153480093f4SDimitry Andric } 154480093f4SDimitry Andric 155480093f4SDimitry Andric uint32_t ScriptInterpreterLua::GetPluginVersion() { return 1; } 156480093f4SDimitry Andric 157480093f4SDimitry Andric Lua &ScriptInterpreterLua::GetLua() { return *m_lua; } 158