JDevlieghere updated this revision to Diff 236853.
JDevlieghere added a comment.

- Use `?.lua` to import modules
- Use Lua runtime to quote strings


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71825/new/

https://reviews.llvm.org/D71825

Files:
  lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
  lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
  lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
  lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
  lldb/test/Shell/ScriptInterpreter/Lua/Inputs/testmodule.lua
  lldb/test/Shell/ScriptInterpreter/Lua/command_script_import.test

Index: lldb/test/Shell/ScriptInterpreter/Lua/command_script_import.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Lua/command_script_import.test
@@ -0,0 +1,4 @@
+# REQUIRES: lua
+# RUN: %lldb --script-language lua -o 'command script import %S/Inputs/testmodule.lua' -o 'script testmodule.foo()' 2>&1 | FileCheck %s
+# RUN: %lldb --script-language lua -o 'command script import %S/Inputs/testmodule.lua' -o 'command script import %S/Inputs/testmodule.lua' -o 'script testmodule.foo()'  2>&1 | FileCheck %s
+# CHECK: Hello World!
Index: lldb/test/Shell/ScriptInterpreter/Lua/Inputs/testmodule.lua
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Lua/Inputs/testmodule.lua
@@ -0,0 +1,7 @@
+local mymodule = {}
+
+function mymodule.foo()
+  print("Hello World!")
+end
+
+return mymodule
Index: lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
+++ lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
@@ -25,6 +25,11 @@
 
   void ExecuteInterpreterLoop() override;
 
+  virtual bool
+  LoadScriptingModule(const char *filename, bool init_session,
+                      lldb_private::Status &error,
+                      StructuredData::ObjectSP *module_sp = nullptr) override;
+
   // Static Functions
   static void Initialize();
 
Index: lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
@@ -77,6 +77,18 @@
   debugger.PushIOHandler(io_handler_sp);
 }
 
+bool ScriptInterpreterLua::LoadScriptingModule(
+    const char *filename, bool init_session, lldb_private::Status &error,
+    StructuredData::ObjectSP *module_sp) {
+
+  if (llvm::Error e = m_lua->LoadModule(filename)) {
+    error.SetErrorStringWithFormatv("lua failed to import '{0}': {1}\n",
+                                    filename, llvm::toString(std::move(e)));
+    return false;
+  }
+  return true;
+}
+
 void ScriptInterpreterLua::Initialize() {
   static llvm::once_flag g_once_flag;
 
Index: lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
+++ lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
@@ -10,6 +10,7 @@
 #define liblldb_Lua_h_
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Error.h"
 
 #include "lua.hpp"
@@ -36,10 +37,13 @@
   }
 
   llvm::Error Run(llvm::StringRef buffer);
+  llvm::Error LoadModule(llvm::StringRef filename);
 
 private:
+  llvm::Expected<std::string> FormatQuoted(llvm::StringRef str);
   std::mutex m_mutex;
   lua_State *m_lua_state;
+  llvm::StringSet<> m_loaded_modules;
 };
 
 } // namespace lldb_private
Index: lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
@@ -7,10 +7,32 @@
 //===----------------------------------------------------------------------===//
 
 #include "Lua.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Utility/FileSpec.h"
 #include "llvm/Support/FormatVariadic.h"
 
 using namespace lldb_private;
 
+#define uchar(c) ((unsigned char)(c))
+
+llvm::Expected<std::string> Lua::FormatQuoted(llvm::StringRef str) {
+  lua_getglobal(m_lua_state, "string");
+  lua_getfield(m_lua_state, -1, "format");
+  lua_pushlstring(m_lua_state, "%q", 2);
+  lua_pushlstring(m_lua_state, str.data(), str.size());
+  if (lua_pcall(m_lua_state, 2, 1, 0) != 0) {
+    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 std::move(e);
+  }
+  const char *formatted_str = lua_tostring(m_lua_state, -1);
+  lua_pop(m_lua_state, 1);
+  return formatted_str;
+}
+
 llvm::Error Lua::Run(llvm::StringRef buffer) {
   std::lock_guard<std::mutex> lock(m_mutex);
   int error =
@@ -26,3 +48,54 @@
   lua_pop(m_lua_state, 1);
   return e;
 }
+
+llvm::Error Lua::LoadModule(llvm::StringRef filename) {
+  FileSpec file(filename);
+  if (!FileSystem::Instance().Exists(file)) {
+    return llvm::make_error<llvm::StringError>("invalid path",
+                                               llvm::inconvertibleErrorCode());
+  }
+
+  llvm::StringRef module_extension = file.GetFileNameExtension().GetStringRef();
+  if (module_extension != ".lua") {
+    return llvm::make_error<llvm::StringError>("invalid extension",
+                                               llvm::inconvertibleErrorCode());
+  }
+
+  llvm::StringRef module_name =
+      file.GetFileNameStrippingExtension().GetStringRef();
+  if (module_name.empty()) {
+    return llvm::make_error<llvm::StringError>("invalid module name",
+                                               llvm::inconvertibleErrorCode());
+  }
+
+  llvm::StringRef module_dir = file.GetDirectory().GetStringRef();
+  // Don't clutter the package path and only add the module path if we haven't
+  // seen it before.
+  if (!m_loaded_modules.count(module_dir)) {
+    std::string s = llvm::formatv(";{0}/?.lua", module_dir).str();
+    llvm::Expected<std::string> maybe_quoted = FormatQuoted(s);
+    if (!maybe_quoted) {
+      return maybe_quoted.takeError();
+    }
+    if (llvm::Error e = Run(
+            llvm::formatv("package.path = package.path .. {0}", *maybe_quoted)
+                .str())) {
+      return e;
+    }
+    m_loaded_modules.insert(module_dir);
+  }
+
+  if (llvm::Error e =
+          Run(llvm::formatv("package.loaded.{0} = nil", module_name).str())) {
+    return e;
+  }
+
+  llvm::Expected<std::string> maybe_quoted = FormatQuoted(module_name);
+  if (!maybe_quoted) {
+    return maybe_quoted.takeError();
+  }
+  // Import the module.
+  return Run(
+      llvm::formatv("{0} = require {1}", module_name, *maybe_quoted).str());
+}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to