128613242SJonas Devlieghere //===-- Lua.cpp -----------------------------------------------------------===// 228613242SJonas Devlieghere // 328613242SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 428613242SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information. 528613242SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 628613242SJonas Devlieghere // 728613242SJonas Devlieghere //===----------------------------------------------------------------------===// 828613242SJonas Devlieghere 928613242SJonas Devlieghere #include "Lua.h" 10572b9f46SJonas Devlieghere #include "lldb/Host/FileSystem.h" 11572b9f46SJonas Devlieghere #include "lldb/Utility/FileSpec.h" 1228613242SJonas Devlieghere #include "llvm/Support/FormatVariadic.h" 1328613242SJonas Devlieghere 1428613242SJonas Devlieghere using namespace lldb_private; 1545c971f7SJonas Devlieghere using namespace lldb; 1628613242SJonas Devlieghere 17*ca175710SPedro Tammela static int lldb_print(lua_State *L) { 18*ca175710SPedro Tammela int n = lua_gettop(L); 19*ca175710SPedro Tammela lua_getglobal(L, "io"); 20*ca175710SPedro Tammela lua_getfield(L, -1, "stdout"); 21*ca175710SPedro Tammela lua_getfield(L, -1, "write"); 22*ca175710SPedro Tammela for (int i = 1; i <= n; i++) { 23*ca175710SPedro Tammela lua_pushvalue(L, -1); // write() 24*ca175710SPedro Tammela lua_pushvalue(L, -3); // io.stdout 25*ca175710SPedro Tammela luaL_tolstring(L, i, nullptr); 26*ca175710SPedro Tammela lua_pushstring(L, i != n ? "\t" : "\n"); 27*ca175710SPedro Tammela lua_call(L, 3, 0); 28*ca175710SPedro Tammela } 29*ca175710SPedro Tammela return 0; 30*ca175710SPedro Tammela } 31*ca175710SPedro Tammela 32*ca175710SPedro Tammela Lua::Lua() : m_lua_state(luaL_newstate()) { 33*ca175710SPedro Tammela assert(m_lua_state); 34*ca175710SPedro Tammela luaL_openlibs(m_lua_state); 35*ca175710SPedro Tammela luaopen_lldb(m_lua_state); 36*ca175710SPedro Tammela lua_pushcfunction(m_lua_state, lldb_print); 37*ca175710SPedro Tammela lua_setglobal(m_lua_state, "print"); 38*ca175710SPedro Tammela } 39*ca175710SPedro Tammela 40*ca175710SPedro Tammela Lua::~Lua() { 41*ca175710SPedro Tammela assert(m_lua_state); 42*ca175710SPedro Tammela lua_close(m_lua_state); 43*ca175710SPedro Tammela } 44*ca175710SPedro Tammela 4528613242SJonas Devlieghere llvm::Error Lua::Run(llvm::StringRef buffer) { 4628613242SJonas Devlieghere int error = 4728613242SJonas Devlieghere luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer") || 4828613242SJonas Devlieghere lua_pcall(m_lua_state, 0, 0, 0); 494b9fa3b7SPedro Tammela if (error == LUA_OK) 5028613242SJonas Devlieghere return llvm::Error::success(); 5128613242SJonas Devlieghere 5228613242SJonas Devlieghere llvm::Error e = llvm::make_error<llvm::StringError>( 5328613242SJonas Devlieghere llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)), 5428613242SJonas Devlieghere llvm::inconvertibleErrorCode()); 5528613242SJonas Devlieghere // Pop error message from the stack. 5628613242SJonas Devlieghere lua_pop(m_lua_state, 1); 5728613242SJonas Devlieghere return e; 5828613242SJonas Devlieghere } 59572b9f46SJonas Devlieghere 60572b9f46SJonas Devlieghere llvm::Error Lua::LoadModule(llvm::StringRef filename) { 61572b9f46SJonas Devlieghere FileSpec file(filename); 62572b9f46SJonas Devlieghere if (!FileSystem::Instance().Exists(file)) { 63572b9f46SJonas Devlieghere return llvm::make_error<llvm::StringError>("invalid path", 64572b9f46SJonas Devlieghere llvm::inconvertibleErrorCode()); 65572b9f46SJonas Devlieghere } 66572b9f46SJonas Devlieghere 67572b9f46SJonas Devlieghere ConstString module_extension = file.GetFileNameExtension(); 68572b9f46SJonas Devlieghere if (module_extension != ".lua") { 69572b9f46SJonas Devlieghere return llvm::make_error<llvm::StringError>("invalid extension", 70572b9f46SJonas Devlieghere llvm::inconvertibleErrorCode()); 71572b9f46SJonas Devlieghere } 72572b9f46SJonas Devlieghere 73572b9f46SJonas Devlieghere int error = luaL_loadfile(m_lua_state, filename.data()) || 74572b9f46SJonas Devlieghere lua_pcall(m_lua_state, 0, 1, 0); 754b9fa3b7SPedro Tammela if (error != LUA_OK) { 76572b9f46SJonas Devlieghere llvm::Error e = llvm::make_error<llvm::StringError>( 77572b9f46SJonas Devlieghere llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)), 78572b9f46SJonas Devlieghere llvm::inconvertibleErrorCode()); 79572b9f46SJonas Devlieghere // Pop error message from the stack. 80572b9f46SJonas Devlieghere lua_pop(m_lua_state, 1); 81572b9f46SJonas Devlieghere return e; 82572b9f46SJonas Devlieghere } 83572b9f46SJonas Devlieghere 84572b9f46SJonas Devlieghere ConstString module_name = file.GetFileNameStrippingExtension(); 85572b9f46SJonas Devlieghere lua_setglobal(m_lua_state, module_name.GetCString()); 86572b9f46SJonas Devlieghere return llvm::Error::success(); 87572b9f46SJonas Devlieghere } 88fa1b4a96SJonas Devlieghere 89fa1b4a96SJonas Devlieghere llvm::Error Lua::ChangeIO(FILE *out, FILE *err) { 90fa1b4a96SJonas Devlieghere assert(out != nullptr); 91fa1b4a96SJonas Devlieghere assert(err != nullptr); 92fa1b4a96SJonas Devlieghere 93fa1b4a96SJonas Devlieghere lua_getglobal(m_lua_state, "io"); 94fa1b4a96SJonas Devlieghere 95fa1b4a96SJonas Devlieghere lua_getfield(m_lua_state, -1, "stdout"); 96fa1b4a96SJonas Devlieghere if (luaL_Stream *s = static_cast<luaL_Stream *>( 97fa1b4a96SJonas Devlieghere luaL_testudata(m_lua_state, -1, LUA_FILEHANDLE))) { 98fa1b4a96SJonas Devlieghere s->f = out; 99fa1b4a96SJonas Devlieghere lua_pop(m_lua_state, 1); 100fa1b4a96SJonas Devlieghere } else { 101fa1b4a96SJonas Devlieghere lua_pop(m_lua_state, 2); 102fa1b4a96SJonas Devlieghere return llvm::make_error<llvm::StringError>("could not get stdout", 103fa1b4a96SJonas Devlieghere llvm::inconvertibleErrorCode()); 104fa1b4a96SJonas Devlieghere } 105fa1b4a96SJonas Devlieghere 106be494adbSJonas Devlieghere lua_getfield(m_lua_state, -1, "stderr"); 107fa1b4a96SJonas Devlieghere if (luaL_Stream *s = static_cast<luaL_Stream *>( 108fa1b4a96SJonas Devlieghere luaL_testudata(m_lua_state, -1, LUA_FILEHANDLE))) { 109fa1b4a96SJonas Devlieghere s->f = out; 110fa1b4a96SJonas Devlieghere lua_pop(m_lua_state, 1); 111fa1b4a96SJonas Devlieghere } else { 112fa1b4a96SJonas Devlieghere lua_pop(m_lua_state, 2); 113fa1b4a96SJonas Devlieghere return llvm::make_error<llvm::StringError>("could not get stderr", 114fa1b4a96SJonas Devlieghere llvm::inconvertibleErrorCode()); 115fa1b4a96SJonas Devlieghere } 116fa1b4a96SJonas Devlieghere 117fa1b4a96SJonas Devlieghere lua_pop(m_lua_state, 1); 118fa1b4a96SJonas Devlieghere return llvm::Error::success(); 119fa1b4a96SJonas Devlieghere } 120