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

Extend test case to show that this works with files sourcing other files.


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

https://reviews.llvm.org/D89334

Files:
  lldb/include/lldb/Interpreter/CommandInterpreter.h
  lldb/include/lldb/Interpreter/ScriptInterpreter.h
  lldb/source/Commands/CommandObjectCommands.cpp
  lldb/source/Interpreter/CommandInterpreter.cpp
  lldb/source/Interpreter/ScriptInterpreter.cpp
  lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
  lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
  lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.in
  lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.py
  lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.in
  lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.py
  lldb/test/Shell/ScriptInterpreter/Python/relative_import.test

Index: lldb/test/Shell/ScriptInterpreter/Python/relative_import.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/relative_import.test
@@ -0,0 +1,11 @@
+# REQUIRES: python
+
+# RUN: rm -rf %t && mkdir -p %t/foo/bar
+# RUN: cp %S/Inputs/zip.py %t/foo
+# RUN: cp %S/Inputs/zip.in %t/foo
+# RUN: cp %S/Inputs/hello.py %t/foo/bar
+# RUN: cp %S/Inputs/hello.in %t/foo/bar
+# RUN: echo 'command source %t/foo/bar/hello.in' >> %t/foo/zip.in
+# RUN: %lldb --script-language python -o 'command source %t/foo/zip.in' -o 'zip' -o 'hello' 2>&1 | FileCheck %s
+# CHECK: 95126
+# CHECK: Hello, World!
Index: lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.py
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.py
@@ -0,0 +1,7 @@
+import lldb
+
+def zip(debugger, command, result, internal_dict):
+    print("95126")
+
+def __lldb_init_module(debugger, internal_dict):
+    debugger.HandleCommand('command script add -f zip.zip zip')
Index: lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.in
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/Inputs/zip.in
@@ -0,0 +1 @@
+command script import zip
Index: lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.py
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.py
@@ -0,0 +1,7 @@
+import lldb
+
+def hello(debugger, command, result, internal_dict):
+    print("Hello, World!")
+
+def __lldb_init_module(debugger, internal_dict):
+    debugger.HandleCommand('command script add -f hello.hello hello')
Index: lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.in
===================================================================
--- /dev/null
+++ lldb/test/Shell/ScriptInterpreter/Python/Inputs/hello.in
@@ -0,0 +1 @@
+command script import hello
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -231,10 +231,10 @@
   bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
                               std::string &output, Status &error) override;
 
-  bool
-  LoadScriptingModule(const char *filename, bool init_session,
-                      lldb_private::Status &error,
-                      StructuredData::ObjectSP *module_sp = nullptr) override;
+  bool LoadScriptingModule(const char *filename, bool init_session,
+                           lldb_private::Status &error,
+                           StructuredData::ObjectSP *module_sp = nullptr,
+                           FileSpec extra_search_dir = {}) override;
 
   bool IsReservedWord(const char *word) override;
 
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -2733,7 +2733,7 @@
 
 bool ScriptInterpreterPythonImpl::LoadScriptingModule(
     const char *pathname, bool init_session, lldb_private::Status &error,
-    StructuredData::ObjectSP *module_sp) {
+    StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) {
   if (!pathname || !pathname[0]) {
     error.SetErrorString("invalid pathname");
     return false;
@@ -2760,24 +2760,12 @@
     fs::file_status st;
     std::error_code ec = status(target_file.GetPath(), st);
 
-    if (ec || st.type() == fs::file_type::status_error ||
-        st.type() == fs::file_type::type_unknown ||
-        st.type() == fs::file_type::file_not_found) {
-      // if not a valid file of any sort, check if it might be a filename still
-      // dot can't be used but / and \ can, and if either is found, reject
-      if (strchr(pathname, '\\') || strchr(pathname, '/')) {
-        error.SetErrorString("invalid pathname");
-        return false;
-      }
-      basename = pathname; // not a filename, probably a package of some sort,
-                           // let it go through
-    } else if (is_directory(st) || is_regular_file(st)) {
-      if (target_file.GetDirectory().IsEmpty()) {
-        error.SetErrorString("invalid directory name");
-        return false;
+    auto ExtendSysPath = [this](std::string directory) -> llvm::Error {
+      if (directory.empty()) {
+        return llvm::make_error<llvm::StringError>(
+            "invalid directory name", llvm::inconvertibleErrorCode());
       }
 
-      std::string directory = target_file.GetDirectory().GetCString();
       replace_all(directory, "\\", "\\\\");
       replace_all(directory, "'", "\\'");
 
@@ -2793,7 +2781,35 @@
                                    .SetSetLLDBGlobals(false))
               .Success();
       if (!syspath_retval) {
-        error.SetErrorString("Python sys.path handling failed");
+        return llvm::make_error<llvm::StringError>(
+            "Python sys.path handling failed", llvm::inconvertibleErrorCode());
+      }
+
+      return llvm::Error::success();
+    };
+
+    if (extra_search_dir) {
+      if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) {
+        error = std::move(e);
+        return false;
+      }
+    }
+
+    if (ec || st.type() == fs::file_type::status_error ||
+        st.type() == fs::file_type::type_unknown ||
+        st.type() == fs::file_type::file_not_found) {
+      // if not a valid file of any sort, check if it might be a filename still
+      // dot can't be used but / and \ can, and if either is found, reject
+      if (strchr(pathname, '\\') || strchr(pathname, '/')) {
+        error.SetErrorString("invalid pathname");
+        return false;
+      }
+      basename = pathname; // not a filename, probably a package of some sort,
+                           // let it go through
+    } else if (is_directory(st) || is_regular_file(st)) {
+      if (llvm::Error e =
+              ExtendSysPath(target_file.GetDirectory().GetCString())) {
+        error = std::move(e);
         return false;
       }
 
@@ -3229,11 +3245,16 @@
 
   LLDBSwigPyInit();
 
-  // Update the path python uses to search for modules to include the current
-  // directory.
-
+  // We need to call this before AddToSysPath as it uses the sys module.
   PyRun_SimpleString("import sys");
+
+  // Update the path python uses to search for modules to include the current
+  // directory and the home directory.
   AddToSysPath(AddLocation::End, ".");
+  FileSpec home_dir_spec;
+  llvm::SmallString<128> home_dir;
+  if (FileSystem::Instance().GetHomeDirectory(home_dir))
+    AddToSysPath(AddLocation::End, std::string(home_dir));
 
   // Don't denormalize paths when calling file_spec.GetPath().  On platforms
   // that use a backslash as the path separator, this will result in executing
Index: lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
+++ lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
@@ -25,10 +25,10 @@
 
   void ExecuteInterpreterLoop() override;
 
-  bool
-  LoadScriptingModule(const char *filename, bool init_session,
-                      lldb_private::Status &error,
-                      StructuredData::ObjectSP *module_sp = nullptr) override;
+  bool LoadScriptingModule(const char *filename, bool init_session,
+                           lldb_private::Status &error,
+                           StructuredData::ObjectSP *module_sp = nullptr,
+                           FileSpec extra_search_dir = {}) 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
@@ -124,7 +124,7 @@
 
 bool ScriptInterpreterLua::LoadScriptingModule(
     const char *filename, bool init_session, lldb_private::Status &error,
-    StructuredData::ObjectSP *module_sp) {
+    StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) {
 
   FileSystem::Instance().Collect(filename);
   if (llvm::Error e = m_lua->LoadModule(filename)) {
Index: lldb/source/Interpreter/ScriptInterpreter.cpp
===================================================================
--- lldb/source/Interpreter/ScriptInterpreter.cpp
+++ lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -47,9 +47,11 @@
       "This script interpreter does not support watchpoint callbacks.");
 }
 
-bool ScriptInterpreter::LoadScriptingModule(
-    const char *filename, bool init_session, lldb_private::Status &error,
-    StructuredData::ObjectSP *module_sp) {
+bool ScriptInterpreter::LoadScriptingModule(const char *filename,
+                                            bool init_session,
+                                            lldb_private::Status &error,
+                                            StructuredData::ObjectSP *module_sp,
+                                            FileSpec extra_search_dir) {
   error.SetErrorString(
       "This script interpreter does not support importing modules.");
   return false;
Index: lldb/source/Interpreter/CommandInterpreter.cpp
===================================================================
--- lldb/source/Interpreter/CommandInterpreter.cpp
+++ lldb/source/Interpreter/CommandInterpreter.cpp
@@ -2554,11 +2554,15 @@
     debugger.SetAsyncExecution(false);
 
   m_command_source_depth++;
+  m_command_source_dirs.push_back(cmd_file.CopyByRemovingLastPathComponent());
 
   debugger.RunIOHandlerSync(io_handler_sp);
   if (!m_command_source_flags.empty())
     m_command_source_flags.pop_back();
+
+  m_command_source_dirs.pop_back();
   m_command_source_depth--;
+
   result.SetStatus(eReturnStatusSuccessFinishNoResult);
   debugger.SetAsyncExecution(old_async_execution);
 }
@@ -2964,6 +2968,12 @@
   return true;
 }
 
+FileSpec CommandInterpreter::GetCurrentSourceDir() {
+  if (m_command_source_dirs.empty())
+    return {};
+  return m_command_source_dirs.back();
+}
+
 void CommandInterpreter::GetLLDBCommandsFromIOHandler(
     const char *prompt, IOHandlerDelegate &delegate, void *baton) {
   Debugger &debugger = GetDebugger();
Index: lldb/source/Commands/CommandObjectCommands.cpp
===================================================================
--- lldb/source/Commands/CommandObjectCommands.cpp
+++ lldb/source/Commands/CommandObjectCommands.cpp
@@ -1294,6 +1294,9 @@
       return false;
     }
 
+    FileSpec source_dir =
+        GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
+
     for (auto &entry : command.entries()) {
       Status error;
 
@@ -1308,7 +1311,7 @@
       // more)
       m_exe_ctx.Clear();
       if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
-              entry.c_str(), init_session, error)) {
+              entry.c_str(), init_session, error, nullptr, source_dir)) {
         result.SetStatus(eReturnStatusSuccessFinishNoResult);
       } else {
         result.AppendErrorWithFormat("module importing failed: %s",
Index: lldb/include/lldb/Interpreter/ScriptInterpreter.h
===================================================================
--- lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -507,7 +507,8 @@
   virtual bool
   LoadScriptingModule(const char *filename, bool init_session,
                       lldb_private::Status &error,
-                      StructuredData::ObjectSP *module_sp = nullptr);
+                      StructuredData::ObjectSP *module_sp = nullptr,
+                      FileSpec extra_search_dir = {});
 
   virtual bool IsReservedWord(const char *word) { return false; }
 
Index: lldb/include/lldb/Interpreter/CommandInterpreter.h
===================================================================
--- lldb/include/lldb/Interpreter/CommandInterpreter.h
+++ lldb/include/lldb/Interpreter/CommandInterpreter.h
@@ -551,6 +551,8 @@
   bool SaveTranscript(CommandReturnObject &result,
                       llvm::Optional<std::string> output_file = llvm::None);
 
+  FileSpec GetCurrentSourceDir();
+
 protected:
   friend class Debugger;
 
@@ -637,7 +639,13 @@
   ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated
                                                        // children and whether
                                                        // the user has been told
+
+  // FIXME: Stop using this to control adding to the history and then replace
+  // this with m_command_source_dirs.size().
   uint32_t m_command_source_depth;
+  /// A stack of directory paths. When not empty, the last one is the directory
+  /// of the file that's currently sourced.
+  std::vector<FileSpec> m_command_source_dirs;
   std::vector<uint32_t> m_command_source_flags;
   CommandInterpreterRunResult m_result;
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to