//===-- ScriptInterpreterPython.cpp ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb-python.h"

#include "Interfaces/ScriptInterpreterPythonInterfaces.h"
#include "PythonDataObjects.h"
#include "PythonReadline.h"
#include "SWIGPythonBridge.h"
#include "ScriptInterpreterPythonImpl.h"

#include "lldb/API/SBError.h"
#include "lldb/API/SBExecutionContext.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBValue.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ThreadedCommunication.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/Timer.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"

#if defined(_WIN32)
#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
#endif

#include <cstdio>
#include <cstdlib>
#include <memory>
#include <optional>
#include <stdlib.h>
#include <string>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::python;
using llvm::Expected;

LLDB_PLUGIN_DEFINE(ScriptInterpreterPython)

// Defined in the SWIG source file
extern "C" PyObject *PyInit__lldb(void);

#define LLDBSwigPyInit PyInit__lldb

#if defined(_WIN32)
// Don't mess with the signal handlers on Windows.
#define LLDB_USE_PYTHON_SET_INTERRUPT 0
#else
#define LLDB_USE_PYTHON_SET_INTERRUPT 1
#endif

static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) {
  ScriptInterpreter *script_interpreter =
      debugger.GetScriptInterpreter(true, lldb::eScriptLanguagePython);
  return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter);
}

namespace {

// Initializing Python is not a straightforward process.  We cannot control
// what external code may have done before getting to this point in LLDB,
// including potentially having already initialized Python, so we need to do a
// lot of work to ensure that the existing state of the system is maintained
// across our initialization.  We do this by using an RAII pattern where we
// save off initial state at the beginning, and restore it at the end
struct InitializePythonRAII {
public:
  llvm::Error DoInitialize() {
    const bool was_initialized = Py_IsInitialized();

    // The table of built-in modules can only be extended before Python is
    // initialized.
    if (!was_initialized) {
#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
      // Python's readline is incompatible with libedit being linked into lldb.
      // Provide a patched version local to the embedded interpreter.
      PyImport_AppendInittab("readline", initlldb_readline);
#endif

      // Register _lldb as a built-in module.
      PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
    }

#if LLDB_EMBED_PYTHON_HOME
    if (!was_initialized) {
      PyConfig config;
      PyConfig_InitPythonConfig(&config);

      static std::string g_python_home = []() -> std::string {
        if (llvm::sys::path::is_absolute(LLDB_PYTHON_HOME))
          return LLDB_PYTHON_HOME;

        FileSpec spec = HostInfo::GetShlibDir();
        if (!spec)
          return {};
        spec.AppendPathComponent(LLDB_PYTHON_HOME);
        return spec.GetPath();
      }();
      if (!g_python_home.empty()) {
        PyStatus status = PyConfig_SetBytesString(&config, &config.home,
                                                  g_python_home.c_str());
        if (PyStatus_Exception(status)) {
          PyConfig_Clear(&config);
          return llvm::createStringError(
              "failed to set the Python config: '%s'", status.err_msg);
        }
      }

      config.install_signal_handlers = 0;
      PyStatus status = Py_InitializeFromConfig(&config);
      PyConfig_Clear(&config);
      if (PyStatus_Exception(status))
        return llvm::createStringError("Python failed to initialize: '%s'",
                                       status.err_msg);
    }
#else
    if (!was_initialized)
      Py_InitializeEx(/*install_sigs=*/0);
    if (!Py_IsInitialized())
      return llvm::createStringError("Python failed to initialize");
#endif

    m_python_initialized = true;

    // The only case we should go further and acquire the GIL: it is unlocked.
    PyGILState_STATE gil_state = PyGILState_Ensure();
    if (gil_state != PyGILState_UNLOCKED)
      return llvm::Error::success();

    m_was_already_initialized = true;
    m_gil_state = gil_state;
    LLDB_LOG_VERBOSE(
        GetLog(LLDBLog::Script), "Ensured PyGILState. Previous state = {0}",
        m_gil_state == PyGILState_UNLOCKED ? "unlocked" : "locked");
    return llvm::Error::success();
  }

  ~InitializePythonRAII() {
    if (!m_python_initialized)
      return;

    if (m_was_already_initialized) {
      LLDB_LOG_VERBOSE(GetLog(LLDBLog::Script),
                       "Releasing PyGILState. Returning to state = {0}",
                       m_gil_state == PyGILState_UNLOCKED ? "unlocked"
                                                          : "locked");
      PyGILState_Release(m_gil_state);
    } else {
      // We initialized the threads in this function, just unlock the GIL.
      PyEval_SaveThread();
    }
  }

private:
  PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;
  bool m_was_already_initialized = false;
  bool m_python_initialized = false;
};

#if LLDB_USE_PYTHON_SET_INTERRUPT
/// Saves the current signal handler for the specified signal and restores
/// it at the end of the current scope.
struct RestoreSignalHandlerScope {
  /// The signal handler.
  struct sigaction m_prev_handler;
  int m_signal_code;
  RestoreSignalHandlerScope(int signal_code) : m_signal_code(signal_code) {
    // Initialize sigaction to their default state.
    std::memset(&m_prev_handler, 0, sizeof(m_prev_handler));
    // Don't install a new handler, just read back the old one.
    struct sigaction *new_handler = nullptr;
    int signal_err = ::sigaction(m_signal_code, new_handler, &m_prev_handler);
    lldbassert(signal_err == 0 && "sigaction failed to read handler");
  }
  ~RestoreSignalHandlerScope() {
    int signal_err = ::sigaction(m_signal_code, &m_prev_handler, nullptr);
    lldbassert(signal_err == 0 && "sigaction failed to restore old handler");
  }
};
#endif
} // namespace

void ScriptInterpreterPython::ComputePythonDirForApple(
    llvm::SmallVectorImpl<char> &path) {
  auto style = llvm::sys::path::Style::posix;

  llvm::StringRef path_ref(path.begin(), path.size());
  auto rbegin = llvm::sys::path::rbegin(path_ref, style);
  auto rend = llvm::sys::path::rend(path_ref);
  auto framework = std::find(rbegin, rend, "LLDB.framework");
  if (framework == rend) {
    ComputePythonDir(path);
    return;
  }
  path.resize(framework - rend);
  llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python");
}

void ScriptInterpreterPython::ComputePythonDir(
    llvm::SmallVectorImpl<char> &path) {
  // Build the path by backing out of the lib dir, then building with whatever
  // the real python interpreter uses.  (e.g. lib for most, lib64 on RHEL
  // x86_64, or bin on Windows).
  llvm::sys::path::remove_filename(path);
  llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR);

#if defined(_WIN32)
  // This will be injected directly through FileSpec.SetDirectory(),
  // so we need to normalize manually.
  std::replace(path.begin(), path.end(), '\\', '/');
#endif
}

FileSpec ScriptInterpreterPython::GetPythonDir() {
  static FileSpec g_spec = []() {
    FileSpec spec = HostInfo::GetShlibDir();
    if (!spec)
      return FileSpec();
    llvm::SmallString<64> path;
    spec.GetPath(path);

#if defined(__APPLE__)
    ComputePythonDirForApple(path);
#else
    ComputePythonDir(path);
#endif
    spec.SetDirectory(path);
    return spec;
  }();
  return g_spec;
}

static const char GetInterpreterInfoScript[] = R"(
import os
import sys

def main(lldb_python_dir, python_exe_relative_path):
  info = {
    "lldb-pythonpath": lldb_python_dir,
    "language": "python",
    "prefix": sys.prefix,
    "executable": os.path.join(sys.prefix, python_exe_relative_path)
  }
  return info
)";

static const char python_exe_relative_path[] = LLDB_PYTHON_EXE_RELATIVE_PATH;

StructuredData::DictionarySP ScriptInterpreterPython::GetInterpreterInfo() {
  GIL gil;
  FileSpec python_dir_spec = GetPythonDir();
  if (!python_dir_spec)
    return nullptr;
  PythonScript get_info(GetInterpreterInfoScript);
  auto info_json = unwrapIgnoringErrors(
      As<PythonDictionary>(get_info(PythonString(python_dir_spec.GetPath()),
                                    PythonString(python_exe_relative_path))));
  if (!info_json)
    return nullptr;
  return info_json.CreateStructuredDictionary();
}

llvm::Expected<std::string> ScriptInterpreterPython::ExtensionToImportPath(
    lldb::ScriptedExtension extension) {
  switch (extension) {
  case eScriptedExtensionOperatingSystem:
    return "lldb.plugins.operating_system";
  case eScriptedExtensionScriptedPlatform:
    return "lldb.plugins.scripted_platform";
  case eScriptedExtensionScriptedProcess:
    return "lldb.plugins.scripted_process";
  case eScriptedExtensionScriptedHook:
    return "lldb.plugins.scripted_hook";
  case eScriptedExtensionScriptedBreakpointResolver:
    return "lldb.plugins.scripted_breakpoint";
  case eScriptedExtensionScriptedThreadPlan:
    return "lldb.plugins.scripted_thread_plan";
  case eScriptedExtensionScriptedFrameProvider:
    return "lldb.plugins.scripted_frame_provider";
  case eScriptedExtensionScriptedThread:
  case eScriptedExtensionScriptedFrame:
    return "lldb.plugins.scripted_process";
  case eScriptedExtensionScriptedStackFrameRecognizer:
    return "lldb.plugins.scripted_stackframe_recognizer";
  case eScriptedExtensionScriptedCommand:
  case eScriptedExtensionParsedCommand:
    return "lldb.plugins.scripted_command";
  case eScriptedExtensionScriptedStringSummary:
    return "lldb.plugins.scripted_string_summary";
  case eScriptedExtensionScriptedSyntheticChildren:
    return "lldb.plugins.scripted_synthetic_children";
  case eScriptedExtensionInvalid:
    return llvm::createStringError("invalid extension name");
  }
  return llvm::createStringError("invalid extension name");
}

llvm::Expected<StructuredData::ObjectSP>
ScriptInterpreterPython::GetExtensionSchema(
    const llvm::SmallVector<llvm::StringRef> &extension_path) {
  lldb::ScriptedExtension extension =
      ScriptInterpreter::StringToExtension(extension_path.back());
  auto import_path_or_err = ExtensionToImportPath(extension);
  if (!import_path_or_err)
    return import_path_or_err.takeError();

  StreamString command_stream;
  // __import__(path, fromlist=['']) imports the submodule and returns it
  // directly (rather than the top-level package), as a single expression --
  // this keeps the whole call eval-able in one line while guaranteeing the
  // module is imported first; referencing "<import_path>.<ClassName>"
  // directly would only work if something else had already imported
  // <import_path> as a side effect.
  command_stream.Printf("lldb.embedded_interpreter.generate_extension_schema("
                        "__import__('%s', fromlist=['']).%s)",
                        import_path_or_err->c_str(),
                        ScriptInterpreter::ExtensionToString(extension).data());

  // Use eScriptReturnTypeOpaqueObject: it transfers a real owned reference
  // we can safely extract the string from. eScriptReturnTypeCharStrOrNone
  // instead hands back a pointer to a temporary Python object's buffer
  // that gets destroyed (and, for a freshly created string like this one,
  // deallocated) as soon as ExecuteOneLineWithReturn returns -- reading
  // it afterwards is a use-after-free.
  void *result_obj = nullptr;
  if (!ExecuteOneLineWithReturn(
          command_stream.GetData(),
          ScriptInterpreter::eScriptReturnTypeOpaqueObject, &result_obj,
          ExecuteScriptOptions().SetEnableIO(false)))
    return llvm::createStringError("invalid extension schema format");

  // ExecuteOneLineWithReturn releases the GIL before returning, so touching
  // the returned object (Str() below can execute arbitrary Python code) must
  // re-acquire it first. py_result is scoped so its destructor (a DECREF)
  // also runs before the GIL is released below, not after.
  std::string schema_str;
  {
    PyGILState_STATE gil_state = PyGILState_Ensure();
    {
      PythonObject py_result(PyRefType::Owned,
                             static_cast<PyObject *>(result_obj));
      if (py_result.IsAllocated() && py_result.get() != Py_None)
        schema_str = py_result.Str().GetString().str();
    }
    PyGILState_Release(gil_state);
  }

  if (schema_str.empty())
    return llvm::createStringError("empty extension schema");
  return StructuredData::ParseJSON(schema_str);
}

llvm::Error ScriptInterpreterPython::ParseExtensionSchema(
    Stream &s, llvm::StringRef output_script_prefix,
    const llvm::SmallVector<llvm::StringRef> &extension_path,
    bool generate_non_abstract_methods, std::set<std::string> &typing_imports) {
  auto schema_or_err = GetExtensionSchema(extension_path);
  if (!schema_or_err)
    return schema_or_err.takeError();

  StructuredData::ObjectSP schema = *schema_or_err;
  if (!schema)
    return llvm::createStringError("empty extension schema");
  StructuredData::Dictionary *dict = schema->GetAsDictionary();
  if (!dict)
    return llvm::createStringError("extension schema is not a JSON object");

  // Merge each class' typing imports into the caller-owned set so the
  // final `from typing import ...` line covers every class we emit.
  StructuredData::Array *schema_typing;
  if (dict->GetValueForKeyAsArray("typing_imports", schema_typing))
    schema_typing->ForEach([&](StructuredData::Object *entry) {
      if (auto *str = entry->GetAsString())
        typing_imports.insert(str->GetValue().str());
      return true;
    });

  llvm::StringRef base_class, import_path;
  if (!dict->GetValueForKeyAsString("class", base_class))
    return llvm::createStringError(
        llvm::formatv("extension schema dictionary is missing 'class' key")
            .str());
  if (!dict->GetValueForKeyAsString("module", import_path))
    return llvm::createStringError(
        llvm::formatv("extension schema dictionary is missing 'module' key")
            .str());

  // imports
  s.Printf("from %s import %s\n", import_path.data(), base_class.data());
  s.EOL();

  // class definition
  s.Printf("class %s%s(%s):\n", output_script_prefix.data(), base_class.data(),
           base_class.data());
  s.IndentMore();

  // Class docstring: list the non-callable members the base class exposes
  // so the user sees what's available without having to hop back to the
  // base class definition.
  bool has_body = false;
  StructuredData::Array *attributes;
  if (dict->GetValueForKeyAsArray("attributes", attributes) &&
      attributes->GetSize()) {
    s.Indent();
    s.PutCString("\"\"\"\n");
    s.Indent();
    s.Printf("Attributes inherited from %s:\n", base_class.data());
    for (size_t i = 0; i < attributes->GetSize(); i++) {
      auto maybe_dict = attributes->GetItemAtIndexAsDictionary(i);
      if (!maybe_dict)
        continue;
      StructuredData::Dictionary *attr_dict = *maybe_dict;
      llvm::StringRef attr_name;
      if (!attr_dict->GetValueForKeyAsString("name", attr_name))
        continue;
      llvm::StringRef attr_type;
      bool has_type = attr_dict->GetValueForKeyAsString("type", attr_type);
      s.Indent();
      s.Printf("- %s", attr_name.data());
      if (has_type)
        s.Printf(": %s", attr_type.data());
      s.EOL();
    }
    s.Indent();
    s.PutCString("\"\"\"\n\n");
    has_body = true;
  }

  // members
  StructuredData::Array *members;
  if (!dict->GetValueForKeyAsArray("members", members))
    return llvm::createStringError("missing 'members' key in extension schema");

  // If the base class doesn't mark anything `@abstractmethod`, the filter
  // "only stub abstract methods" would leave the derived class empty --
  // which isn't a useful starting point. Fall back to emitting every
  // method in that case so the user has actual code to edit.
  bool any_abstract = false;
  for (size_t i = 0; i < members->GetSize(); i++) {
    auto maybe_dict = members->GetItemAtIndexAsDictionary(i);
    if (!maybe_dict)
      continue;
    bool is_abstract = false;
    if ((*maybe_dict)->GetValueForKeyAsBoolean("is_abstract", is_abstract) &&
        is_abstract) {
      any_abstract = true;
      break;
    }
  }
  bool emit_all_methods = generate_non_abstract_methods || !any_abstract;

  for (size_t i = 0; i < members->GetSize(); i++) {
    auto maybe_dict = members->GetItemAtIndexAsDictionary(i);
    if (!maybe_dict)
      return llvm::createStringError(
          llvm::formatv(
              "member at index {0} in extension schema isn't a dictionary")
              .str());

    StructuredData::Dictionary *member_dict = *maybe_dict;
    llvm::StringRef symbol, args;
    if (!member_dict->GetValueForKeyAsString("name", symbol))
      return llvm::createStringError(
          llvm::formatv(
              "member at index {0} in extension schema is missing 'name' key")
              .str());
    if (!member_dict->GetValueForKeyAsString("signature", args))
      return llvm::createStringError(
          llvm::formatv("member at index {0} in extension schema is missing "
                        "'signature' key")
              .str());

    bool is_abstract = false;
    bool has_is_abstract =
        member_dict->GetValueForKeyAsBoolean("is_abstract", is_abstract);
    if (!emit_all_methods)
      if (!has_is_abstract || !is_abstract)
        continue;

    s.Indent();
    s.Printf("def %s%s:\n", symbol.data(), args.data());

    s.IndentMore();
    llvm::StringRef documentation;
    if (member_dict->GetValueForKeyAsString("doc", documentation)) {
      s.Indent();
      s.PutCString("\"\"\"\n");

      llvm::SmallVector<llvm::StringRef> lines;
      documentation.split(lines, "\n");

      for (llvm::StringRef line : lines) {
        s.Indent();
        s.PutCString(line);
        s.EOL();
      }

      s.Indent();
      s.PutCString("\"\"\"");
      s.EOL();
    }

    if (symbol == "__init__") {
      // The base class' constructor sets up attributes (e.g. self.target,
      // self.process) that the inherited, non-overridden methods rely on.
      // Forward the same arguments so that state is still initialized.
      // Splitting the param list on `,` requires bracket-depth awareness
      // because annotations like `Union[X, Y]` also contain commas.
      llvm::StringRef params = args.trim("()");
      std::vector<std::string> forwarded_args;
      int depth = 0;
      size_t start = 0;
      auto flush = [&](size_t end) {
        llvm::StringRef param = params.slice(start, end);
        param = param.split(':').first.split('=').first.trim();
        if (!param.empty() && param != "self")
          forwarded_args.push_back(param.str());
      };
      for (size_t i = 0; i < params.size(); ++i) {
        char c = params[i];
        if (c == '[' || c == '(' || c == '{')
          ++depth;
        else if (c == ']' || c == ')' || c == '}')
          --depth;
        else if (c == ',' && depth == 0) {
          flush(i);
          start = i + 1;
        }
      }
      flush(params.size());
      s.Indent();
      s.Printf("super().__init__(%s)\n",
               llvm::join(forwarded_args, ", ").c_str());
    }

    s.Indent();
    s.PutCString("# TODO: Implement\n");
    s.Indent();
    s.PutCString("pass\n\n");
    s.IndentLess();
    has_body = true;
  }

  // A class with no body is a Python syntax error, so emit `pass` when the
  // base class has nothing to stub out (no methods and no attributes to
  // document).
  if (!has_body) {
    s.Indent();
    s.PutCString("pass\n");
  }

  return llvm::Error::success();
}

llvm::Expected<FileSpec> ScriptInterpreterPython::GenerateExtensionTemplate(
    const std::string &name, std::vector<ExtensionTemplateRequest> &extensions,
    bool generate_non_abstract_methods, std::string output_file) {
  // `ParseExtensionSchema` accumulates every `typing` generic it sees
  // (`Optional`, `Union`, `List`, ...) into this set so we can emit a
  // targeted `from typing import ...` line only for what's actually
  // referenced. The Python schema does the detection so we don't have
  // to re-scan strings here.
  std::set<std::string> typing_imports;
  StreamString bodies;
  for (const ExtensionTemplateRequest &extension : extensions) {
    if (llvm::Error err =
            ParseExtensionSchema(bodies, name, extension.path,
                                 generate_non_abstract_methods, typing_imports))
      return std::move(err);
    bodies.PutCString("\n\n");
  }

  StreamString generated_file_stream;
  generated_file_stream.PutCString("import lldb\n");
  if (!typing_imports.empty()) {
    std::vector<std::string> sorted_imports(typing_imports.begin(),
                                            typing_imports.end());
    generated_file_stream.Format("from typing import {0}\n",
                                 llvm::join(sorted_imports, ", "));
  }
  generated_file_stream.PutCString("\n");
  generated_file_stream.PutCString(bodies.GetString());

  FileSpec save_location;
  if (output_file.empty()) {
    // Sanitize the caller-supplied class prefix so it can't escape the
    // temp directory (`../`, path separators, ...). Only keep ASCII
    // alphanumerics; everything else collapses to `_`, and an all-junk
    // name falls back to a fixed default.
    std::string sanitized;
    sanitized.reserve(name.size());
    for (char c : name)
      sanitized.push_back(llvm::isAlnum(c) ? static_cast<char>(llvm::toLower(c))
                                           : '_');
    if (sanitized.find_first_not_of('_') == std::string::npos)
      sanitized = "extension";
    const std::string file_name = "lldb_" + sanitized + "_extension.py";
    save_location = HostInfo::GetGlobalTempDir();
    FileSystem::Instance().Resolve(save_location);
    save_location.AppendPathComponent(file_name);
  } else {
    save_location = FileSpec(output_file);
    FileSystem::Instance().Resolve(save_location);
  }

  File::OpenOptions flags = File::eOpenOptionWriteOnly |
                            File::eOpenOptionCanCreate |
                            File::eOpenOptionTruncate;

  auto opened_file = FileSystem::Instance().Open(save_location, flags);

  if (!opened_file)
    return opened_file.takeError();

  FileUP file = std::move(opened_file.get());

  size_t byte_size = generated_file_stream.GetSize();

  Status error = file->Write(generated_file_stream.GetData(), byte_size);

  if (error.Fail() || byte_size != generated_file_stream.GetSize())
    return llvm::createStringError("Unable to write to destination file. Bytes "
                                   "written do not match generated file size.");
  return save_location;
}

void ScriptInterpreterPython::SharedLibraryDirectoryHelper(
    FileSpec &this_file) {
  // When we're loaded from python, this_file will point to the file inside the
  // python package directory. Replace it with the one in the lib directory.
#ifdef _WIN32
  // On windows, we need to manually back out of the python tree, and go into
  // the bin directory. This is pretty much the inverse of what ComputePythonDir
  // does.
  if (this_file.GetFileNameExtension() == ".pyd") {
    this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd
    this_file.RemoveLastPathComponent(); // native
    this_file.RemoveLastPathComponent(); // lldb
    llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR;
    for (auto it = llvm::sys::path::begin(libdir),
              end = llvm::sys::path::end(libdir);
         it != end; ++it)
      this_file.RemoveLastPathComponent();
    this_file.AppendPathComponent("bin");
    this_file.AppendPathComponent("liblldb.dll");
  }
#else
  // The python file is a symlink, so we can find the real library by resolving
  // it. We can do this unconditionally.
  FileSystem::Instance().ResolveSymbolicLink(this_file, this_file);
#endif
}

llvm::StringRef ScriptInterpreterPython::GetPluginDescriptionStatic() {
  return "Embedded Python interpreter";
}

void ScriptInterpreterPython::Initialize() {
#if LLDB_ENABLE_MTE
  // Python's allocator (pymalloc) is not aware of Memory Tagging Extension
  // (MTE) and crashes.
  // https://bugs.python.org/issue43593
  setenv("PYTHONMALLOC", "malloc", /*overwrite=*/true);
#endif

  // When the plugin is a separate shared library, the SWIG wrapper lives in
  // the plugin library, so the path helper that redirects lookups back to
  // liblldb is unnecessary.
#if !LLDB_ENABLE_DYNAMIC_SCRIPTINTERPRETERS
  HostInfo::SetSharedLibraryDirectoryHelper(
      ScriptInterpreterPython::SharedLibraryDirectoryHelper);
#endif

  // Bring the interpreter up before registering, so a Python that refuses to
  // initialize leaves no plugin claiming eScriptLanguagePython behind.
  // GetScriptInterpreterForLanguage then hands out ScriptInterpreterNone and
  // the rest of lldb keeps working without scripting.
  if (llvm::Error error = ScriptInterpreterPythonImpl::Initialize()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Script), std::move(error), "{0}");
    return;
  }

  PluginManager::RegisterPlugin(
      GetPluginNameStatic(), GetPluginDescriptionStatic(),
      lldb::eScriptLanguagePython, ScriptInterpreterPythonImpl::CreateInstance,
      ScriptInterpreterPythonImpl::GetPythonDir);
  ScriptInterpreterPythonInterfaces::Initialize();
}

void ScriptInterpreterPython::Terminate() {
  ScriptInterpreterPythonInterfaces::Terminate();
  PluginManager::UnregisterPlugin(ScriptInterpreterPythonImpl::CreateInstance);
}

ScriptInterpreterPythonImpl::Locker::Locker(
    ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry,
    uint16_t on_leave, FileSP in, FileSP out, FileSP err)
    : ScriptInterpreterLocker(),
      m_teardown_session((on_leave & TearDownSession) == TearDownSession),
      m_python_interpreter(py_interpreter) {
  DoAcquireLock();
  if ((on_entry & InitSession) == InitSession) {
    if (!DoInitSession(on_entry, in, out, err)) {
      // Don't teardown the session if we didn't init it.
      m_teardown_session = false;
    }
  }
}

bool ScriptInterpreterPythonImpl::Locker::DoAcquireLock() {
  m_GILState = PyGILState_Ensure();
  LLDB_LOG_VERBOSE(GetLog(LLDBLog::Script),
                   "Ensured PyGILState. Previous state = {0}",
                   m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");

  // we need to save the thread state when we first start the command because
  // we might decide to interrupt it while some action is taking place outside
  // of Python (e.g. printing to screen, waiting for the network, ...) in that
  // case, _PyThreadState_Current will be NULL - and we would be unable to set
  // the asynchronous exception - not a desirable situation
  m_python_interpreter->SetThreadState(PyThreadState_Get());
  m_python_interpreter->IncrementLockCount();
  return true;
}

bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags,
                                                        FileSP in, FileSP out,
                                                        FileSP err) {
  if (!m_python_interpreter)
    return false;
  return m_python_interpreter->EnterSession(on_entry_flags, in, out, err);
}

bool ScriptInterpreterPythonImpl::Locker::DoFreeLock() {
  LLDB_LOG_VERBOSE(GetLog(LLDBLog::Script),
                   "Releasing PyGILState. Returning to state = {0}",
                   m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");
  PyGILState_Release(m_GILState);
  m_python_interpreter->DecrementLockCount();
  return true;
}

bool ScriptInterpreterPythonImpl::Locker::DoTearDownSession() {
  if (!m_python_interpreter)
    return false;
  m_python_interpreter->LeaveSession();
  return true;
}

ScriptInterpreterPythonImpl::Locker::~Locker() {
  if (m_teardown_session)
    DoTearDownSession();
  DoFreeLock();
}

ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger)
    : ScriptInterpreterPython(debugger), m_saved_stdin(), m_saved_stdout(),
      m_saved_stderr(), m_main_module(),
      m_session_dict(PyInitialValue::Invalid),
      m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(),
      m_run_one_line_str_global(),
      m_dictionary_name(m_debugger.GetInstanceName()),
      m_active_io_handler(eIOHandlerNone), m_session_is_active(false),
      m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0),
      m_command_thread_state(nullptr) {

  m_dictionary_name.append("_dict");
  StreamString run_string;
  run_string.Printf("%s = dict()", m_dictionary_name.c_str());

  Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock);
  RunSimpleString(run_string.GetData());

  run_string.Clear();
  run_string.Printf("run_one_line (%s, 'import copy, keyword, os, re, sys, "
                    "uuid, lldb, importlib')",
                    m_dictionary_name.c_str());
  RunSimpleString(run_string.GetData());

  // WARNING: temporary code that loads Cocoa formatters - this should be done
  // on a per-platform basis rather than loading the whole set and letting the
  // individual formatter classes exploit APIs to check whether they can/cannot
  // do their task
  run_string.Clear();
  run_string.Printf(
      "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp')",
      m_dictionary_name.c_str());
  RunSimpleString(run_string.GetData());
  run_string.Clear();

  run_string.Printf("run_one_line (%s, 'import lldb.embedded_interpreter; from "
                    "lldb.embedded_interpreter import run_python_interpreter; "
                    "from lldb.embedded_interpreter import run_one_line')",
                    m_dictionary_name.c_str());
  RunSimpleString(run_string.GetData());
  run_string.Clear();

  // Configure pydoc (built-in module) to use the "plain" pager. The default one
  // doesn't play nice with the statusline.
  run_string.Printf("run_one_line (%s, 'import pydoc; pydoc.pager = "
                    "pydoc.plainpager')",
                    m_dictionary_name.c_str());
  RunSimpleString(run_string.GetData());
  run_string.Clear();

  run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64
                    "')",
                    m_dictionary_name.c_str(), m_debugger.GetID());
  RunSimpleString(run_string.GetData());
}

/// A Python sys.stdout/stderr file backed by a pipe whose read end is drained
/// by a reader thread that writes to the debugger's terminal under the output
/// lock (Debugger::PrintAsync). Handing Python the raw terminal descriptor
/// instead lets a script's print() race the statusline, which redraws on the
/// event thread under that lock. Its cursor save/restore then rewinds over and
/// eats the script's output.
class ScriptInterpreterPythonImpl::SessionIORedirect {
public:
  static std::unique_ptr<SessionIORedirect> Create(lldb::user_id_t debugger_id,
                                                   bool is_stdout) {
    Pipe pipe;
    if (pipe.CreateNew().Fail())
      return nullptr;

    std::unique_ptr<SessionIORedirect> redirect(
        new SessionIORedirect(debugger_id, is_stdout));

#if defined(_WIN32)
    lldb::file_t read_handle = pipe.GetReadNativeHandle();
    pipe.ReleaseReadFileDescriptor();
    std::unique_ptr<Connection> conn =
        std::make_unique<ConnectionGenericFile>(read_handle, true);
#else
    std::unique_ptr<Connection> conn =
        std::make_unique<ConnectionFileDescriptor>(
            pipe.ReleaseReadFileDescriptor(), /*owns_fd=*/true);
#endif
    if (!conn->IsConnected())
      return nullptr;

    redirect->m_communication.SetConnection(std::move(conn));
    redirect->m_communication.SetReadThreadBytesReceivedCallback(
        ReadThreadBytesReceived, redirect.get());
    if (!redirect->m_communication.StartReadThread())
      return nullptr;
    redirect->m_connected = true;

    // The write end is owned here. Python only borrows its descriptor.
    redirect->m_write_file_sp = std::make_shared<NativeFile>(
        pipe.ReleaseWriteFileDescriptor(), File::eOpenOptionWriteOnly,
        NativeFile::Owned);
    return redirect;
  }

  ~SessionIORedirect() {
    if (!m_connected)
      return;
    // Close the write end so the reader sees EOF and exits, then join it.
    if (m_write_file_sp)
      m_write_file_sp->Close();
    m_communication.JoinReadThread();
    m_communication.Disconnect();
  }

  int GetWriteDescriptor() const {
    return m_write_file_sp ? m_write_file_sp->GetDescriptor()
                           : File::kInvalidDescriptor;
  }

private:
  SessionIORedirect(lldb::user_id_t debugger_id, bool is_stdout)
      : m_debugger_id(debugger_id), m_is_stdout(is_stdout),
        m_communication("lldb.ScriptInterpreterPython.io-redirect") {}

  static void ReadThreadBytesReceived(void *baton, const void *src,
                                      size_t src_len) {
    if (!src || !src_len)
      return;
    auto *self = static_cast<SessionIORedirect *>(baton);
    if (lldb::DebuggerSP debugger_sp =
            Debugger::FindDebuggerWithID(self->m_debugger_id))
      debugger_sp->PrintAsync(static_cast<const char *>(src), src_len,
                              self->m_is_stdout);
  }

  lldb::user_id_t m_debugger_id;
  bool m_is_stdout;
  lldb::FileSP m_write_file_sp;
  ThreadedCommunication m_communication;
  bool m_connected = false;
};

ScriptInterpreterPythonImpl::~ScriptInterpreterPythonImpl() {
  // the session dictionary may hold objects with complex state which means
  // that they may need to be torn down with some level of smarts and that, in
  // turn, requires a valid thread state force Python to procure itself such a
  // thread state, nuke the session dictionary and then release it for others
  // to use and proceed with the rest of the shutdown
  auto gil_state = PyGILState_Ensure();
  m_session_dict.Reset();
  PyGILState_Release(gil_state);
}

void ScriptInterpreterPythonImpl::IOHandlerActivated(IOHandler &io_handler,
                                                     bool interactive) {
  const char *instructions = nullptr;

  switch (m_active_io_handler) {
  case eIOHandlerNone:
    break;
  case eIOHandlerBreakpoint:
    instructions = R"(Enter your Python command(s). Type 'DONE' to end.
def function (frame, bp_loc, internal_dict):
    """frame: the lldb.SBFrame for the location at which you stopped
       bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information
       internal_dict: an LLDB support object not to be used"""
)";
    break;
  case eIOHandlerWatchpoint:
    instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
    break;
  }

  if (instructions && interactive) {
    if (LockableStreamFileSP stream_sp = io_handler.GetOutputStreamFileSP()) {
      LockedStreamFile locked_stream = stream_sp->Lock();
      locked_stream.PutCString(instructions);
      locked_stream.Flush();
    }
  }
}

void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
                                                         std::string &data) {
  io_handler.SetIsDone(true);
  bool batch_mode = m_debugger.GetCommandInterpreter().GetBatchCommandMode();

  switch (m_active_io_handler) {
  case eIOHandlerNone:
    break;
  case eIOHandlerBreakpoint: {
    std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec =
        (std::vector<std::reference_wrapper<BreakpointOptions>> *)
            io_handler.GetUserData();
    for (BreakpointOptions &bp_options : *bp_options_vec) {

      auto data_up = std::make_unique<CommandDataPython>();
      if (!data_up)
        break;
      data_up->user_source.SplitIntoLines(data);

      if (GenerateBreakpointCommandCallbackData(data_up->user_source,
                                                data_up->script_source,
                                                /*has_extra_args=*/false,
                                                /*is_callback=*/false)
              .Success()) {
        auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(
            std::move(data_up));
        bp_options.SetCallback(
            ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
      } else if (!batch_mode) {
        if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
          LockedStreamFile locked_stream = error_sp->Lock();
          locked_stream.Printf("Warning: No command attached to breakpoint.\n");
        }
      }
    }
    m_active_io_handler = eIOHandlerNone;
  } break;
  case eIOHandlerWatchpoint: {
    WatchpointOptions *wp_options =
        (WatchpointOptions *)io_handler.GetUserData();
    auto data_up = std::make_unique<WatchpointOptions::CommandData>();
    data_up->user_source.SplitIntoLines(data);

    if (GenerateWatchpointCommandCallbackData(data_up->user_source,
                                              data_up->script_source,
                                              /*is_callback=*/false)) {
      auto baton_sp =
          std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
      wp_options->SetCallback(
          ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);
    } else if (!batch_mode) {
      if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
        LockedStreamFile locked_stream = error_sp->Lock();
        locked_stream.Printf("Warning: No command attached to breakpoint.\n");
      }
    }
    m_active_io_handler = eIOHandlerNone;
  } break;
  }
}

lldb::ScriptInterpreterSP
ScriptInterpreterPythonImpl::CreateInstance(Debugger &debugger) {
  return std::make_shared<ScriptInterpreterPythonImpl>(debugger);
}

void ScriptInterpreterPythonImpl::LeaveSession() {
  Log *log = GetLog(LLDBLog::Script);
  if (log)
    log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()");

  // Unset the LLDB global variables.
  RunSimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
                  "= None; lldb.thread = None; lldb.frame = None");

  // checking that we have a valid thread state - since we use our own
  // threading and locking in some (rare) cases during cleanup Python may end
  // up believing we have no thread state and PyImport_AddModule will crash if
  // that is the case - since that seems to only happen when destroying the
  // SBDebugger, we can make do without clearing up stdout and stderr
  if (PyThreadState_GetDict()) {
    PythonDictionary &sys_module_dict = GetSysModuleDictionary();
    if (sys_module_dict.IsValid()) {
      // Flush the pipe-backed wrappers while they are still sys.stdout/stderr.
      // Line buffering already flushes on each newline, but a trailing
      // unterminated line would otherwise be stranded (and later flushed into
      // a closed descriptor) once we close the pipe write end below.
      auto flush_redirect = [&](const char *py_name,
                                std::unique_ptr<SessionIORedirect> &redirect) {
        if (!redirect)
          return;
        PythonObject file =
            sys_module_dict.GetItemForKey(PythonString(py_name));
        if (!file.IsValid())
          return;
        if (llvm::Expected<PythonObject> result = file.CallMethod("flush"))
          (void)result;
        else
          llvm::consumeError(result.takeError());
      };
      flush_redirect("stdout", m_stdout_redirect);
      flush_redirect("stderr", m_stderr_redirect);

      if (m_saved_stdin.IsValid()) {
        sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
        m_saved_stdin.Reset();
      }
      if (m_saved_stdout.IsValid()) {
        sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
        m_saved_stdout.Reset();
      }
      if (m_saved_stderr.IsValid()) {
        sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
        m_saved_stderr.Reset();
      }
    }
  }

  // Tear down the pipe redirects (closes each write end and joins its reader).
  // The wrappers were flushed above, so nothing buffered is lost.
  m_stdout_redirect.reset();
  m_stderr_redirect.reset();

  m_session_is_active = false;
}

bool ScriptInterpreterPythonImpl::RedirectTerminalHandleThroughLock(
    const char *py_name, PythonObject &save_file, const char *mode,
    File &file) {
  const bool is_stdout = ::strcmp(py_name, "stdout") == 0;
  if (!is_stdout && ::strcmp(py_name, "stderr") != 0)
    return false;

  // The statusline is the only writer that races Python's terminal output.
  // When it isn't drawing there is nothing to serialize against, so keep the
  // normal wrapping and skip the reader thread and pipe.
  if (!m_debugger.StatuslineSupported())
    return false;

  // Only the debugger's own terminal races the statusline. A redirect to a
  // pipe or user file (a different descriptor) is wrapped normally.
  lldb::FileSP debugger_file =
      is_stdout ? m_debugger.GetOutputFileSP() : m_debugger.GetErrorFileSP();
  int fd = file.GetDescriptor();
  if (!debugger_file || fd == File::kInvalidDescriptor ||
      fd != debugger_file->GetDescriptor())
    return false;

  std::unique_ptr<SessionIORedirect> &redirect =
      is_stdout ? m_stdout_redirect : m_stderr_redirect;
  redirect = SessionIORedirect::Create(m_debugger.GetID(), is_stdout);
  if (!redirect)
    return false;

  // Line-buffer the wrapper so each print() reaches the reader (and the
  // terminal) promptly: the pipe descriptor is not a tty, so the default
  // buffering would hold output back until the buffer filled.
  PyObject *pipe_file = PyFile_FromFd(
      PythonFile::TranslateFdToPython(redirect->GetWriteDescriptor()), nullptr,
      mode, /*buffering=*/1,
      /*encoding=*/nullptr, /*errors=*/"ignore",
      /*newline=*/nullptr,
      /*closefd=*/0);
  if (!pipe_file) {
    // Fall back to the raw descriptor. That reopens the statusline race, so
    // leave a breadcrumb rather than failing silently.
    LLDB_LOG(GetLog(LLDBLog::Script),
             "failed to wrap sys.{0} on a synchronized pipe; falling back to "
             "the unsynchronized terminal descriptor",
             py_name);
    PyErr_Clear();
    redirect.reset();
    return false;
  }

  PythonObject new_file(PyRefType::Owned, pipe_file);
  PythonDictionary &sys_module_dict = GetSysModuleDictionary();
  save_file = sys_module_dict.GetItemForKey(PythonString(py_name));
  sys_module_dict.SetItemForKey(PythonString(py_name), new_file);
  return true;
}

bool ScriptInterpreterPythonImpl::SetStdHandle(FileSP file_sp,
                                               const char *py_name,
                                               PythonObject &save_file,
                                               const char *mode,
                                               bool serialize_terminal_output) {
  if (!file_sp || !*file_sp) {
    save_file.Reset();
    return false;
  }
  File &file = *file_sp;

  // When stdout/stderr point at the debugger's own terminal, route Python's
  // output through a pipe drained under the output lock so a script's print()
  // cannot race the statusline. Any other target keeps the normal wrapping.
  if (serialize_terminal_output &&
      RedirectTerminalHandleThroughLock(py_name, save_file, mode, file))
    return true;

  // Flush the file before giving it to python to avoid interleaved output.
  file.Flush();

  PythonDictionary &sys_module_dict = GetSysModuleDictionary();

  auto new_file = PythonFile::FromFile(file, mode);
  if (!new_file) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Script), new_file.takeError(),
                   "ScriptInterpreterPythonImpl::SetStdHandle failed to wrap "
                   "sys.{1}: {0}",
                   py_name);
    return false;
  }

  save_file = sys_module_dict.GetItemForKey(PythonString(py_name));

  sys_module_dict.SetItemForKey(PythonString(py_name), new_file.get());
  return true;
}

bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
                                               FileSP in_sp, FileSP out_sp,
                                               FileSP err_sp) {
  // If we have already entered the session, without having officially 'left'
  // it, then there is no need to 'enter' it again.
  Log *log = GetLog(LLDBLog::Script);
  if (m_session_is_active) {
    LLDB_LOGF(
        log,
        "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16
        ") session is already active, returning without doing anything",
        on_entry_flags);
    return false;
  }

  LLDB_LOGF(
      log,
      "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ")",
      on_entry_flags);

  m_session_is_active = true;

  StreamString run_string;

  if (on_entry_flags & Locker::InitGlobals) {
    run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
                      m_dictionary_name.c_str(), m_debugger.GetID());
    run_string.Printf(
        "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
        m_debugger.GetID());
    run_string.PutCString("; lldb.target = lldb.debugger.GetSelectedTarget()");
    run_string.PutCString("; lldb.process = lldb.target.GetProcess()");
    run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()");
    run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");
    run_string.PutCString("')");
  } else {
    // If we aren't initing the globals, we should still always set the
    // debugger (since that is always unique.)
    run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
                      m_dictionary_name.c_str(), m_debugger.GetID());
    run_string.Printf(
        "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
        m_debugger.GetID());
    run_string.PutCString("')");
  }

  RunSimpleString(run_string.GetData());
  run_string.Clear();

  PythonDictionary &sys_module_dict = GetSysModuleDictionary();
  if (sys_module_dict.IsValid()) {
    lldb::FileSP top_in_sp;
    lldb::LockableStreamFileSP top_out_sp, top_err_sp;
    if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp)
      m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp,
                                                 top_err_sp);

    if (on_entry_flags & Locker::NoSTDIN) {
      m_saved_stdin.Reset();
    } else {
      if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r",
                        /*serialize_terminal_output=*/false)) {
        if (top_in_sp)
          SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r",
                       /*serialize_terminal_output=*/false);
      }
    }

    // Serialize terminal output for every session except those that opt out
    // with NoOutputRedirect (see the flag for why).
    const bool serialize_terminal_output =
        !(on_entry_flags & Locker::NoOutputRedirect);

    if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w",
                      serialize_terminal_output)) {
      if (top_out_sp)
        SetStdHandle(top_out_sp->GetUnlockedFileSP(), "stdout", m_saved_stdout,
                     "w", serialize_terminal_output);
    }

    if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w",
                      serialize_terminal_output)) {
      if (top_err_sp)
        SetStdHandle(top_err_sp->GetUnlockedFileSP(), "stderr", m_saved_stderr,
                     "w", serialize_terminal_output);
    }
  }

  if (PyErr_Occurred())
    PyErr_Clear();

  return true;
}

PythonModule &ScriptInterpreterPythonImpl::GetMainModule() {
  if (!m_main_module.IsValid())
    m_main_module = unwrapIgnoringErrors(PythonModule::Import("__main__"));
  return m_main_module;
}

PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() {
  if (m_session_dict.IsValid())
    return m_session_dict;

  PythonObject &main_module = GetMainModule();
  if (!main_module.IsValid())
    return m_session_dict;

  PythonDictionary main_dict(PyRefType::Borrowed,
                             PyModule_GetDict(main_module.get()));
  if (!main_dict.IsValid())
    return m_session_dict;

  m_session_dict = unwrapIgnoringErrors(
      As<PythonDictionary>(main_dict.GetItem(m_dictionary_name)));
  return m_session_dict;
}

PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() {
  if (m_sys_module_dict.IsValid())
    return m_sys_module_dict;
  PythonModule sys_module = unwrapIgnoringErrors(PythonModule::Import("sys"));
  m_sys_module_dict = sys_module.GetDictionary();
  return m_sys_module_dict;
}

llvm::Expected<unsigned>
ScriptInterpreterPythonImpl::GetMaxPositionalArgumentsForCallable(
    const llvm::StringRef &callable_name) {
  if (callable_name.empty()) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "called with empty callable name.");
  }
  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
      m_dictionary_name);
  auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
      callable_name, dict);
  if (!pfunc.IsAllocated()) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "can't find callable: %s",
                                   callable_name.str().c_str());
  }
  llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
  if (!arg_info) {
    // `-f` may point at a builtin, unlike other GetArgInfo() callers.
    LLDB_LOG_ERROR(GetLog(LLDBLog::Script), arg_info.takeError(),
                   "GetArgInfo failed for callable {1}, falling back to "
                   "inspect.signature: {0}",
                   callable_name);
    arg_info = PythonCallable::GetArgInfoFromInspectSignature(pfunc);
  }
  if (!arg_info)
    return arg_info.takeError();
  return arg_info.get().max_positional_args;
}

static std::string GenerateUniqueName(const char *base_name_wanted,
                                      uint32_t &functions_counter,
                                      const void *name_token = nullptr) {
  StreamString sstr;

  if (!base_name_wanted)
    return std::string();

  if (!name_token)
    sstr.Printf("%s_%d", base_name_wanted, functions_counter++);
  else
    sstr.Printf("%s_%p", base_name_wanted, name_token);

  return std::string(sstr.GetString());
}

bool ScriptInterpreterPythonImpl::GetEmbeddedInterpreterModuleObjects() {
  if (m_run_one_line_function.IsValid())
    return true;

  PythonObject module(PyRefType::Borrowed,
                      PyImport_AddModule("lldb.embedded_interpreter"));
  if (!module.IsValid())
    return false;

  PythonDictionary module_dict(PyRefType::Borrowed,
                               PyModule_GetDict(module.get()));
  if (!module_dict.IsValid())
    return false;

  m_run_one_line_function =
      module_dict.GetItemForKey(PythonString("run_one_line"));
  m_run_one_line_str_global =
      module_dict.GetItemForKey(PythonString("g_run_one_line_str"));
  return m_run_one_line_function.IsValid();
}

bool ScriptInterpreterPythonImpl::ExecuteOneLine(
    llvm::StringRef command, CommandReturnObject *result,
    const ExecuteScriptOptions &options) {
  std::string command_str = command.str();

  if (!m_valid_session)
    return false;

  if (!command.empty()) {
    // We want to call run_one_line, passing in the dictionary and the command
    // string.  We cannot do this through RunSimpleString here because the
    // command string may contain escaped characters, and putting it inside
    // another string to pass to RunSimpleString messes up the escaping.  So
    // we use the following more complicated method to pass the command string
    // directly down to Python.
    llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
        io_redirect_or_error = ScriptInterpreterIORedirect::Create(
            options.GetEnableIO(), m_debugger, result);
    if (!io_redirect_or_error) {
      if (result)
        result->AppendErrorWithFormatv(
            "failed to redirect I/O: {0}\n",
            llvm::fmt_consume(io_redirect_or_error.takeError()));
      else
        llvm::consumeError(io_redirect_or_error.takeError());
      return false;
    }

    ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;

    bool success = false;
    {
      // WARNING!  It's imperative that this RAII scope be as tight as
      // possible. In particular, the scope must end *before* we try to join
      // the read thread.  The reason for this is that a pre-requisite for
      // joining the read thread is that we close the write handle (to break
      // the pipe and cause it to wake up and exit).  But acquiring the GIL as
      // below will redirect Python's stdio to use this same handle.  If we
      // close the handle while Python is still using it, bad things will
      // happen.
      Locker locker(
          this,
          Locker::AcquireLock | Locker::InitSession |
              (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
              ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),
          Locker::FreeAcquiredLock | Locker::TearDownSession,
          io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
          io_redirect.GetErrorFile());

      // Find the correct script interpreter dictionary in the main module.
      PythonDictionary &session_dict = GetSessionDictionary();
      if (session_dict.IsValid()) {
        if (GetEmbeddedInterpreterModuleObjects()) {
          if (PyCallable_Check(m_run_one_line_function.get())) {
            PythonObject pargs(
                PyRefType::Owned,
                Py_BuildValue("(Os)", session_dict.get(), command_str.c_str()));
            if (pargs.IsValid()) {
              PythonObject return_value(
                  PyRefType::Owned,
                  PyObject_CallObject(m_run_one_line_function.get(),
                                      pargs.get()));
              if (return_value.IsValid())
                success = true;
              else if (options.GetMaskoutErrors() && PyErr_Occurred()) {
                PyErr_Print();
                PyErr_Clear();
              }
            }
          }
        }
      }

      io_redirect.Flush();
    }

    if (success)
      return true;

    // The one-liner failed.  Append the error message.
    if (result) {
      result->AppendErrorWithFormat("python failed attempting to evaluate '%s'",
                                    command_str.c_str());
    }
    return false;
  }

  if (result)
    result->AppendError("empty command passed to python\n");
  return false;
}

void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() {
  LLDB_SCOPED_TIMER();

  Debugger &debugger = m_debugger;

  // At the moment, the only time the debugger does not have an input file
  // handle is when this is called directly from Python, in which case it is
  // both dangerous and unnecessary (not to mention confusing) to try to embed
  // a running interpreter loop inside the already running Python interpreter
  // loop, so we won't do it.

  if (!debugger.GetInputFile().IsValid())
    return;

  IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this));
  if (io_handler_sp) {
    debugger.RunIOHandlerAsync(io_handler_sp);
  }
}

bool ScriptInterpreterPythonImpl::Interrupt() {
#if LLDB_USE_PYTHON_SET_INTERRUPT
  // If the interpreter isn't evaluating any Python at the moment then return
  // false to signal that this function didn't handle the interrupt and the
  // next component should try handling it.
  if (!IsExecutingPython())
    return false;

  // Tell Python that it should pretend to have received a SIGINT.
  PyErr_SetInterrupt();
  // PyErr_SetInterrupt has no way to return an error so we can only pretend the
  // signal got successfully handled and return true.
  // Python 3.10 introduces PyErr_SetInterruptEx that could return an error, but
  // the error handling is limited to checking the arguments which would be
  // just our (hardcoded) input signal code SIGINT, so that's not useful at all.
  return true;
#else
  Log *log = GetLog(LLDBLog::Script);

  if (IsExecutingPython()) {
    PyThreadState *state = PyThreadState_Get();
    if (!state)
      state = GetThreadState();
    if (state) {
      long tid = PyThread_get_thread_ident();
      PyThreadState_Swap(state);
      int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
      LLDB_LOGF(log,
                "ScriptInterpreterPythonImpl::Interrupt() sending "
                "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...",
                tid, num_threads);
      return true;
    }
  }
  LLDB_LOGF(log,
            "ScriptInterpreterPythonImpl::Interrupt() python code not running, "
            "can't interrupt");
  return false;
#endif
}

bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
    llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
    void *ret_value, const ExecuteScriptOptions &options) {

  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
      io_redirect_or_error = ScriptInterpreterIORedirect::Create(
          options.GetEnableIO(), m_debugger, /*result=*/nullptr);

  if (!io_redirect_or_error) {
    llvm::consumeError(io_redirect_or_error.takeError());
    return false;
  }

  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;

  Locker locker(this,
                Locker::AcquireLock | Locker::InitSession |
                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
                    Locker::NoSTDIN,
                Locker::FreeAcquiredLock | Locker::TearDownSession,
                io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
                io_redirect.GetErrorFile());

  PythonModule &main_module = GetMainModule();
  PythonDictionary globals = main_module.GetDictionary();

  PythonDictionary locals = GetSessionDictionary();
  if (!locals.IsValid())
    locals = unwrapIgnoringErrors(
        As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));
  if (!locals.IsValid())
    locals = globals;

  Expected<PythonObject> maybe_py_return =
      runStringOneLine(in_string, globals, locals);

  if (!maybe_py_return) {
    llvm::handleAllErrors(
        maybe_py_return.takeError(),
        [&](PythonException &E) {
          E.Restore();
          if (options.GetMaskoutErrors()) {
            if (E.Matches(PyExc_SyntaxError)) {
              PyErr_Print();
            }
            PyErr_Clear();
          }
        },
        [](const llvm::ErrorInfoBase &E) {});
    return false;
  }

  PythonObject py_return = std::move(maybe_py_return.get());
  assert(py_return.IsValid());

  switch (return_type) {
  case eScriptReturnTypeCharPtr: // "char *"
  {
    const char format[3] = "s#";
    return PyArg_Parse(py_return.get(), format, (char **)ret_value);
  }
  case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
                                       // Py_None
  {
    const char format[3] = "z";
    return PyArg_Parse(py_return.get(), format, (char **)ret_value);
  }
  case eScriptReturnTypeBool: {
    const char format[2] = "b";
    return PyArg_Parse(py_return.get(), format, (bool *)ret_value);
  }
  case eScriptReturnTypeShortInt: {
    const char format[2] = "h";
    return PyArg_Parse(py_return.get(), format, (short *)ret_value);
  }
  case eScriptReturnTypeShortIntUnsigned: {
    const char format[2] = "H";
    return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
  }
  case eScriptReturnTypeInt: {
    const char format[2] = "i";
    return PyArg_Parse(py_return.get(), format, (int *)ret_value);
  }
  case eScriptReturnTypeIntUnsigned: {
    const char format[2] = "I";
    return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
  }
  case eScriptReturnTypeLongInt: {
    const char format[2] = "l";
    return PyArg_Parse(py_return.get(), format, (long *)ret_value);
  }
  case eScriptReturnTypeLongIntUnsigned: {
    const char format[2] = "k";
    return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
  }
  case eScriptReturnTypeLongLong: {
    const char format[2] = "L";
    return PyArg_Parse(py_return.get(), format, (long long *)ret_value);
  }
  case eScriptReturnTypeLongLongUnsigned: {
    const char format[2] = "K";
    return PyArg_Parse(py_return.get(), format,
                       (unsigned long long *)ret_value);
  }
  case eScriptReturnTypeFloat: {
    const char format[2] = "f";
    return PyArg_Parse(py_return.get(), format, (float *)ret_value);
  }
  case eScriptReturnTypeDouble: {
    const char format[2] = "d";
    return PyArg_Parse(py_return.get(), format, (double *)ret_value);
  }
  case eScriptReturnTypeChar: {
    const char format[2] = "c";
    return PyArg_Parse(py_return.get(), format, (char *)ret_value);
  }
  case eScriptReturnTypeOpaqueObject: {
    *((PyObject **)ret_value) = py_return.release();
    return true;
  }
  }
  llvm_unreachable("Fully covered switch!");
}

Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
    const char *in_string, const ExecuteScriptOptions &options) {

  if (in_string == nullptr)
    return Status();

  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
      io_redirect_or_error = ScriptInterpreterIORedirect::Create(
          options.GetEnableIO(), m_debugger, /*result=*/nullptr);

  if (!io_redirect_or_error)
    return Status::FromError(io_redirect_or_error.takeError());

  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;

  Locker locker(this,
                Locker::AcquireLock | Locker::InitSession |
                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
                    Locker::NoSTDIN,
                Locker::FreeAcquiredLock | Locker::TearDownSession,
                io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
                io_redirect.GetErrorFile());

  PythonModule &main_module = GetMainModule();
  PythonDictionary globals = main_module.GetDictionary();

  PythonDictionary locals = GetSessionDictionary();
  if (!locals.IsValid())
    locals = unwrapIgnoringErrors(
        As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));
  if (!locals.IsValid())
    locals = globals;

  Expected<PythonObject> return_value =
      runStringMultiLine(in_string, globals, locals);

  if (!return_value) {
    llvm::Error error =
        llvm::handleErrors(return_value.takeError(), [&](PythonException &E) {
          llvm::Error error = llvm::createStringError(
              llvm::inconvertibleErrorCode(), E.ReadBacktrace());
          if (!options.GetMaskoutErrors())
            E.Restore();
          return error;
        });
    return Status::FromError(std::move(error));
  }

  return Status();
}

void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(
    std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
    CommandReturnObject &result) {
  m_active_io_handler = eIOHandlerBreakpoint;
  m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
      "    ", *this, &bp_options_vec);
}

void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback(
    WatchpointOptions *wp_options, CommandReturnObject &result) {
  m_active_io_handler = eIOHandlerWatchpoint;
  m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
      "    ", *this, wp_options);
}

Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
    BreakpointOptions &bp_options, const char *function_name,
    StructuredData::ObjectSP extra_args_sp) {
  Status error;
  // For now just cons up a oneliner that calls the provided function.
  std::string function_signature = function_name;

  llvm::Expected<unsigned> maybe_args =
      GetMaxPositionalArgumentsForCallable(function_name);
  if (!maybe_args) {
    error = Status::FromErrorStringWithFormat(
        "could not get num args: %s",
        llvm::toString(maybe_args.takeError()).c_str());
    return error;
  }
  size_t max_args = *maybe_args;

  bool uses_extra_args = false;
  if (max_args >= 4) {
    uses_extra_args = true;
    function_signature += "(frame, bp_loc, extra_args, internal_dict)";
  } else if (max_args >= 3) {
    if (extra_args_sp) {
      error = Status::FromErrorStringWithFormat(
          "cannot pass extra_args to a three argument callback");
      return error;
    }
    uses_extra_args = false;
    function_signature += "(frame, bp_loc, internal_dict)";
  } else {
    error = Status::FromErrorStringWithFormat("expected 3 or 4 argument "
                                              "function, %s can only take %zu",
                                              function_name, max_args);
    return error;
  }

  SetBreakpointCommandCallback(bp_options, function_signature.c_str(),
                               extra_args_sp, uses_extra_args,
                               /*is_callback=*/true);
  return error;
}

Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
    BreakpointOptions &bp_options,
    std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {
  Status error;
  error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,
                                                cmd_data_up->script_source,
                                                /*has_extra_args=*/false,
                                                /*is_callback=*/false);
  if (error.Fail()) {
    return error;
  }
  auto baton_sp =
      std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up));
  bp_options.SetCallback(
      ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
  return error;
}

Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
    BreakpointOptions &bp_options, const char *command_body_text,
    bool is_callback) {
  return SetBreakpointCommandCallback(bp_options, command_body_text, {},
                                      /*uses_extra_args=*/false, is_callback);
}

// Set a Python one-liner as the callback for the breakpoint.
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
    BreakpointOptions &bp_options, const char *command_body_text,
    StructuredData::ObjectSP extra_args_sp, bool uses_extra_args,
    bool is_callback) {
  auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);
  // Split the command_body_text into lines, and pass that to
  // GenerateBreakpointCommandCallbackData.  That will wrap the body in an
  // auto-generated function, and return the function name in script_source.
  // That is what the callback will actually invoke.

  data_up->user_source.SplitIntoLines(command_body_text);
  Status error = GenerateBreakpointCommandCallbackData(
      data_up->user_source, data_up->script_source, uses_extra_args,
      is_callback);
  if (error.Success()) {
    auto baton_sp =
        std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
    bp_options.SetCallback(
        ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
    return error;
  }
  return error;
}

// Set a Python one-liner as the callback for the watchpoint.
void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback(
    WatchpointOptions *wp_options, const char *user_input, bool is_callback) {
  auto data_up = std::make_unique<WatchpointOptions::CommandData>();

  // It's necessary to set both user_source and script_source to the oneliner.
  // The former is used to generate callback description (as in watchpoint
  // command list) while the latter is used for Python to interpret during the
  // actual callback.

  data_up->user_source.AppendString(user_input);
  data_up->script_source.assign(user_input);

  if (GenerateWatchpointCommandCallbackData(
          data_up->user_source, data_up->script_source, is_callback)) {
    auto baton_sp =
        std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
    wp_options->SetCallback(
        ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);
  }
}

Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter(
    StringList &function_def) {
  // Convert StringList to one long, newline delimited, const char *.
  std::string function_def_string(function_def.CopyList());
  LLDB_LOG(GetLog(LLDBLog::Script), "Added Function:\n{0}\n",
           function_def_string.c_str());

  Status error = ExecuteMultipleLines(
      function_def_string.c_str(), ExecuteScriptOptions().SetEnableIO(false));
  return error;
}

Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature,
                                                     const StringList &input,
                                                     bool is_callback) {
  Status error;
  int num_lines = input.GetSize();
  if (num_lines == 0) {
    error = Status::FromErrorString("No input data.");
    return error;
  }

  if (!signature || *signature == 0) {
    error = Status::FromErrorString("No output function name.");
    return error;
  }

  StreamString sstr;
  StringList auto_generated_function;
  auto_generated_function.AppendString(signature);
  auto_generated_function.AppendString(
      "    global_dict = globals()"); // Grab the global dictionary
  auto_generated_function.AppendString(
      "    new_keys = internal_dict.keys()"); // Make a list of keys in the
                                              // session dict
  auto_generated_function.AppendString(
      "    old_keys = global_dict.keys()"); // Save list of keys in global dict
  auto_generated_function.AppendString(
      "    global_dict.update(internal_dict)"); // Add the session dictionary
                                                // to the global dictionary.

  if (is_callback) {
    // If the user input is a callback to a python function, make sure the input
    // is only 1 line, otherwise appending the user input would break the
    // generated wrapped function
    if (num_lines == 1) {
      sstr.Clear();
      sstr.Printf("    __return_val = %s", input.GetStringAtIndex(0));
      auto_generated_function.AppendString(sstr.GetData());
    } else {
      return Status::FromErrorString(
          "ScriptInterpreterPythonImpl::GenerateFunction(is_callback="
          "true) = ERROR: python function is multiline.");
    }
  } else {
    auto_generated_function.AppendString(
        "    __return_val = None"); // Initialize user callback return value.
    auto_generated_function.AppendString(
        "    def __user_code():"); // Create a nested function that will wrap
                                   // the user input. This is necessary to
                                   // capture the return value of the user input
                                   // and prevent early returns.
    for (int i = 0; i < num_lines; ++i) {
      sstr.Clear();
      sstr.Printf("      %s", input.GetStringAtIndex(i));
      auto_generated_function.AppendString(sstr.GetData());
    }
    auto_generated_function.AppendString(
        "    __return_val = __user_code()"); //  Call user code and capture
                                             //  return value
  }
  auto_generated_function.AppendString(
      "    for key in new_keys:"); // Iterate over all the keys from session
                                   // dict
  auto_generated_function.AppendString(
      "        if key in old_keys:"); // If key was originally in
                                      // global dict
  auto_generated_function.AppendString(
      "            internal_dict[key] = global_dict[key]"); // Update it
  auto_generated_function.AppendString(
      "        elif key in global_dict:"); // Then if it is still in the
                                           // global dict
  auto_generated_function.AppendString(
      "            del global_dict[key]"); //  remove key/value from the
                                           //  global dict
  auto_generated_function.AppendString(
      "    return __return_val"); //  Return the user callback return value.

  // Verify that the results are valid Python.
  error = ExportFunctionDefinitionToInterpreter(auto_generated_function);

  return error;
}

bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(
    StringList &user_input, std::string &output, const void *name_token) {
  static uint32_t num_created_functions = 0;
  user_input.RemoveBlankLines();
  StreamString sstr;

  // Check to see if we have any data; if not, just return.
  if (user_input.GetSize() == 0)
    return false;

  // Take what the user wrote, wrap it all up inside one big auto-generated
  // Python function, passing in the ValueObject as parameter to the function.

  std::string auto_generated_function_name(
      GenerateUniqueName("lldb_autogen_python_type_print_func",
                         num_created_functions, name_token));
  sstr.Printf("def %s (valobj, internal_dict):",
              auto_generated_function_name.c_str());

  if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)
           .Success())
    return false;

  // Store the name of the auto-generated function to be called.
  output.assign(auto_generated_function_name);
  return true;
}

bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction(
    StringList &user_input, std::string &output) {
  static uint32_t num_created_functions = 0;
  user_input.RemoveBlankLines();
  StreamString sstr;

  // Check to see if we have any data; if not, just return.
  if (user_input.GetSize() == 0)
    return false;

  std::string auto_generated_function_name(GenerateUniqueName(
      "lldb_autogen_python_cmd_alias_func", num_created_functions));

  sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):",
              auto_generated_function_name.c_str());

  if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)
           .Success())
    return false;

  // Store the name of the auto-generated function to be called.
  output.assign(auto_generated_function_name);
  return true;
}

bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(
    StringList &user_input, std::string &output, const void *name_token) {
  static uint32_t num_created_classes = 0;
  user_input.RemoveBlankLines();
  int num_lines = user_input.GetSize();
  StreamString sstr;

  // Check to see if we have any data; if not, just return.
  if (user_input.GetSize() == 0)
    return false;

  // Wrap all user input into a Python class

  std::string auto_generated_class_name(GenerateUniqueName(
      "lldb_autogen_python_type_synth_class", num_created_classes, name_token));

  StringList auto_generated_class;

  // Create the function name & definition string.

  sstr.Printf("class %s:", auto_generated_class_name.c_str());
  auto_generated_class.AppendString(sstr.GetString());

  // Wrap everything up inside the class, increasing the indentation. we don't
  // need to play any fancy indentation tricks here because there is no
  // surrounding code whose indentation we need to honor
  for (int i = 0; i < num_lines; ++i) {
    sstr.Clear();
    sstr.Printf("     %s", user_input.GetStringAtIndex(i));
    auto_generated_class.AppendString(sstr.GetString());
  }

  // Verify that the results are valid Python. (even though the method is
  // ExportFunctionDefinitionToInterpreter, a class will actually be exported)
  // (TODO: rename that method to ExportDefinitionToInterpreter)
  if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())
    return false;

  // Store the name of the auto-generated class

  output.assign(auto_generated_class_name);
  return true;
}

ScriptedProcessInterfaceUP
ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() {
  return std::make_unique<ScriptedProcessPythonInterface>(*this);
}

ScriptedHookInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedHookInterface() {
  return std::make_shared<ScriptedHookPythonInterface>(*this);
}

ScriptedBreakpointInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedBreakpointInterface() {
  return std::make_shared<ScriptedBreakpointPythonInterface>(*this);
}

ScriptedStackFrameRecognizerInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedStackFrameRecognizerInterface() {
  return std::make_shared<ScriptedStackFrameRecognizerPythonInterface>(*this);
}

ScriptedCommandInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedCommandInterface() {
  return std::make_shared<ScriptedCommandPythonInterface>(*this);
}

ScriptedStringSummaryInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedStringSummaryInterface() {
  return std::make_shared<ScriptedStringSummaryPythonInterface>(*this);
}

ScriptedSyntheticChildrenInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedSyntheticChildrenInterface() {
  return std::make_shared<ScriptedSyntheticChildrenPythonInterface>(*this);
}

ScriptedThreadInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {
  return std::make_shared<ScriptedThreadPythonInterface>(*this);
}

ScriptedFrameInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedFrameInterface() {
  return std::make_shared<ScriptedFramePythonInterface>(*this);
}

ScriptedFrameProviderInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedFrameProviderInterface() {
  return std::make_shared<ScriptedFrameProviderPythonInterface>(*this);
}

ScriptedThreadPlanInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedThreadPlanInterface() {
  return std::make_shared<ScriptedThreadPlanPythonInterface>(*this);
}

OperatingSystemInterfaceSP
ScriptInterpreterPythonImpl::CreateOperatingSystemInterface() {
  return std::make_shared<OperatingSystemPythonInterface>(*this);
}

StructuredData::ObjectSP
ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(
    ScriptObject obj) {
  void *ptr = const_cast<void *>(obj.GetPointer());
  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
  PythonObject py_obj(PyRefType::Borrowed, static_cast<PyObject *>(ptr));
  if (!py_obj.IsValid() || py_obj.IsNone())
    return {};
  return py_obj.CreateStructuredObject();
}

StructuredData::ObjectSP
ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,
                                              lldb_private::Status &error) {
  if (!FileSystem::Instance().Exists(file_spec)) {
    error = Status::FromErrorString("no such file");
    return StructuredData::ObjectSP();
  }

  StructuredData::ObjectSP module_sp;

  LoadScriptOptions load_script_options =
      LoadScriptOptions().SetInitSession(true).SetSilent(false);
  if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options,
                          error, &module_sp))
    return module_sp;

  return StructuredData::ObjectSP();
}

StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings(
    StructuredData::ObjectSP plugin_module_sp, Target *target,
    const char *setting_name, lldb_private::Status &error) {
  if (!plugin_module_sp || !target || !setting_name || !setting_name[0])
    return StructuredData::DictionarySP();
  StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();
  if (!generic)
    return StructuredData::DictionarySP();

  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  TargetSP target_sp(target->shared_from_this());

  auto setting = (PyObject *)SWIGBridge::LLDBSWIGPython_GetDynamicSetting(
      generic->GetValue(), setting_name, target_sp);

  if (!setting)
    return StructuredData::DictionarySP();

  PythonDictionary py_dict =
      unwrapIgnoringErrors(As<PythonDictionary>(Take<PythonObject>(setting)));

  if (!py_dict)
    return StructuredData::DictionarySP();

  return py_dict.CreateStructuredDictionary();
}

bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(
    const char *oneliner, std::string &output, const void *name_token) {
  StringList input;
  input.SplitIntoLines(oneliner, strlen(oneliner));
  return GenerateTypeScriptFunction(input, output, name_token);
}

bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(
    const char *oneliner, std::string &output, const void *name_token) {
  StringList input;
  input.SplitIntoLines(oneliner, strlen(oneliner));
  return GenerateTypeSynthClass(input, output, name_token);
}

Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(
    StringList &user_input, std::string &output, bool has_extra_args,
    bool is_callback) {
  static uint32_t num_created_functions = 0;
  user_input.RemoveBlankLines();
  StreamString sstr;
  Status error;
  if (user_input.GetSize() == 0) {
    error = Status::FromErrorString("No input data.");
    return error;
  }

  std::string auto_generated_function_name(GenerateUniqueName(
      "lldb_autogen_python_bp_callback_func_", num_created_functions));
  if (has_extra_args)
    sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):",
                auto_generated_function_name.c_str());
  else
    sstr.Printf("def %s (frame, bp_loc, internal_dict):",
                auto_generated_function_name.c_str());

  error = GenerateFunction(sstr.GetData(), user_input, is_callback);
  if (!error.Success())
    return error;

  // Store the name of the auto-generated function to be called.
  output.assign(auto_generated_function_name);
  return error;
}

bool ScriptInterpreterPythonImpl::GenerateWatchpointCommandCallbackData(
    StringList &user_input, std::string &output, bool is_callback) {
  static uint32_t num_created_functions = 0;
  user_input.RemoveBlankLines();
  StreamString sstr;

  if (user_input.GetSize() == 0)
    return false;

  std::string auto_generated_function_name(GenerateUniqueName(
      "lldb_autogen_python_wp_callback_func_", num_created_functions));
  sstr.Printf("def %s (frame, wp, internal_dict):",
              auto_generated_function_name.c_str());

  if (!GenerateFunction(sstr.GetData(), user_input, is_callback).Success())
    return false;

  // Store the name of the auto-generated function to be called.
  output.assign(auto_generated_function_name);
  return true;
}

bool ScriptInterpreterPythonImpl::GetScriptedSummary(
    const char *python_function_name, lldb::ValueObjectSP valobj,
    StructuredData::ObjectSP &callee_wrapper_sp,
    const TypeSummaryOptions &options, std::string &retval) {

  LLDB_SCOPED_TIMER();

  if (!valobj.get()) {
    retval.assign("<no object>");
    return false;
  }

  void *old_callee = nullptr;
  StructuredData::Generic *generic = nullptr;
  if (callee_wrapper_sp) {
    generic = callee_wrapper_sp->GetAsGeneric();
    if (generic)
      old_callee = generic->GetValue();
  }
  void *new_callee = old_callee;

  bool ret_val;
  if (python_function_name && *python_function_name) {
    {
      Locker py_lock(this, Locker::AcquireLock | Locker::InitSession |
                               Locker::NoSTDIN);
      {
        TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));

        static Timer::Category func_cat("LLDBSwigPythonCallTypeScript");
        Timer scoped_timer(func_cat, "LLDBSwigPythonCallTypeScript");
        ret_val = SWIGBridge::LLDBSwigPythonCallTypeScript(
            python_function_name, GetSessionDictionary().get(), valobj,
            &new_callee, options_sp, retval);
      }
    }
  } else {
    retval.assign("<no function name>");
    return false;
  }

  if (new_callee && old_callee != new_callee) {
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
    callee_wrapper_sp = std::make_shared<StructuredPythonObject>(
        PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(new_callee)));
  }

  return ret_val;
}

bool ScriptInterpreterPythonImpl::FormatterCallbackFunction(
    const char *python_function_name, TypeImplSP type_impl_sp) {
  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  return SWIGBridge::LLDBSwigPythonFormatterCallbackFunction(
      python_function_name, m_dictionary_name.c_str(), type_impl_sp);
}

bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction(
    void *baton, StoppointCallbackContext *context, user_id_t break_id,
    user_id_t break_loc_id) {
  CommandDataPython *bp_option_data = (CommandDataPython *)baton;
  const char *python_function_name = bp_option_data->script_source.c_str();

  if (!context)
    return true;

  ExecutionContext exe_ctx(context->exe_ctx_ref);
  Target *target = exe_ctx.GetTargetPtr();

  if (!target)
    return true;

  Debugger &debugger = target->GetDebugger();
  ScriptInterpreterPythonImpl *python_interpreter =
      GetPythonInterpreter(debugger);

  if (!python_interpreter)
    return true;

  if (python_function_name && python_function_name[0]) {
    const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
    BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);
    if (breakpoint_sp) {
      const BreakpointLocationSP bp_loc_sp(
          breakpoint_sp->FindLocationByID(break_loc_id));

      if (stop_frame_sp && bp_loc_sp) {
        bool ret_val = true;
        {
          Locker py_lock(python_interpreter, Locker::AcquireLock |
                                                 Locker::InitSession |
                                                 Locker::NoSTDIN);
          Expected<bool> maybe_ret_val =
              SWIGBridge::LLDBSwigPythonBreakpointCallbackFunction(
                  python_function_name,
                  python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
                  bp_loc_sp, bp_option_data->m_extra_args);

          if (!maybe_ret_val) {

            llvm::handleAllErrors(
                maybe_ret_val.takeError(),
                [&](PythonException &E) {
                  *debugger.GetAsyncErrorStream() << E.ReadBacktrace();
                },
                [&](const llvm::ErrorInfoBase &E) {
                  *debugger.GetAsyncErrorStream() << E.message();
                });

          } else {
            ret_val = maybe_ret_val.get();
          }
        }
        return ret_val;
      }
    }
  }
  // We currently always true so we stop in case anything goes wrong when
  // trying to call the script function
  return true;
}

bool ScriptInterpreterPythonImpl::WatchpointCallbackFunction(
    void *baton, StoppointCallbackContext *context, user_id_t watch_id) {
  WatchpointOptions::CommandData *wp_option_data =
      (WatchpointOptions::CommandData *)baton;
  const char *python_function_name = wp_option_data->script_source.c_str();

  if (!context)
    return true;

  ExecutionContext exe_ctx(context->exe_ctx_ref);
  Target *target = exe_ctx.GetTargetPtr();

  if (!target)
    return true;

  Debugger &debugger = target->GetDebugger();
  ScriptInterpreterPythonImpl *python_interpreter =
      GetPythonInterpreter(debugger);

  if (!python_interpreter)
    return true;

  if (python_function_name && python_function_name[0]) {
    const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
    WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);
    if (wp_sp) {
      if (stop_frame_sp && wp_sp) {
        bool ret_val = true;
        {
          Locker py_lock(python_interpreter, Locker::AcquireLock |
                                                 Locker::InitSession |
                                                 Locker::NoSTDIN);
          ret_val = SWIGBridge::LLDBSwigPythonWatchpointCallbackFunction(
              python_function_name,
              python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
              wp_sp);
        }
        return ret_val;
      }
    }
  }
  // We currently always true so we stop in case anything goes wrong when
  // trying to call the script function
  return true;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, Process *process, std::string &output,
    Status &error) {
  bool ret_val;
  if (!process) {
    error = Status::FromErrorString("no process");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  {
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
    ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordProcess(
        impl_function, m_dictionary_name.c_str(), process->shared_from_this(),
        output);
    if (!ret_val)
      error = Status::FromErrorString("python script evaluation failed");
  }
  return ret_val;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, Thread *thread, std::string &output,
    Status &error) {
  if (!thread) {
    error = Status::FromErrorString("no thread");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  if (std::optional<std::string> result =
          SWIGBridge::LLDBSWIGPythonRunScriptKeywordThread(
              impl_function, m_dictionary_name.c_str(),
              thread->shared_from_this())) {
    output = std::move(*result);
    return true;
  }
  error = Status::FromErrorString("python script evaluation failed");
  return false;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, Target *target, std::string &output,
    Status &error) {
  bool ret_val;
  if (!target) {
    error = Status::FromErrorString("no thread");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  {
    TargetSP target_sp(target->shared_from_this());
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
    ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordTarget(
        impl_function, m_dictionary_name.c_str(), target_sp, output);
    if (!ret_val)
      error = Status::FromErrorString("python script evaluation failed");
  }
  return ret_val;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, StackFrame *frame, std::string &output,
    Status &error) {
  if (!frame) {
    error = Status::FromErrorString("no frame");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  if (std::optional<std::string> result =
          SWIGBridge::LLDBSWIGPythonRunScriptKeywordFrame(
              impl_function, m_dictionary_name.c_str(),
              frame->shared_from_this())) {
    output = std::move(*result);
    return true;
  }
  error = Status::FromErrorString("python script evaluation failed");
  return false;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, ValueObject *value, std::string &output,
    Status &error) {
  bool ret_val;
  if (!value) {
    error = Status::FromErrorString("no value");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  {
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
    ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordValue(
        impl_function, m_dictionary_name.c_str(), value->GetSP(), output);
    if (!ret_val)
      error = Status::FromErrorString("python script evaluation failed");
  }
  return ret_val;
}

uint64_t replace_all(std::string &str, const std::string &oldStr,
                     const std::string &newStr) {
  size_t pos = 0;
  uint64_t matches = 0;
  while ((pos = str.find(oldStr, pos)) != std::string::npos) {
    matches++;
    str.replace(pos, oldStr.length(), newStr);
    pos += newStr.length();
  }
  return matches;
}

bool ScriptInterpreterPythonImpl::LoadScriptingModule(
    const char *pathname, const LoadScriptOptions &options,
    lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
    FileSpec extra_search_dir, lldb::TargetSP target_sp) {
  namespace fs = llvm::sys::fs;
  namespace path = llvm::sys::path;

  ExecuteScriptOptions exc_options = ExecuteScriptOptions()
                                         .SetEnableIO(!options.GetSilent())
                                         .SetSetLLDBGlobals(false);

  if (!pathname || !pathname[0]) {
    error = Status::FromErrorString("empty path");
    return false;
  }

  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
      io_redirect_or_error = ScriptInterpreterIORedirect::Create(
          exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr);

  if (!io_redirect_or_error) {
    error = Status::FromError(io_redirect_or_error.takeError());
    return false;
  }

  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;

  // Before executing Python code, lock the GIL.
  Locker py_lock(this,
                 Locker::AcquireLock |
                     (options.GetInitSession() ? Locker::InitSession : 0) |
                     Locker::NoSTDIN,
                 Locker::FreeAcquiredLock |
                     (options.GetInitSession() ? Locker::TearDownSession : 0),
                 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
                 io_redirect.GetErrorFile());

  auto ExtendSysPath = [&](std::string directory) -> llvm::Error {
    if (directory.empty()) {
      return llvm::createStringError("invalid directory name");
    }

    replace_all(directory, "\\", "\\\\");
    replace_all(directory, "'", "\\'");

    // Make sure that Python has "directory" in the search path.
    StreamString command_stream;
    command_stream.Printf("if not (sys.path.__contains__('%s')):\n    "
                          "sys.path.insert(1,'%s');\n\n",
                          directory.c_str(), directory.c_str());
    bool syspath_retval =
        ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();
    if (!syspath_retval)
      return llvm::createStringError("Python sys.path handling failed");

    return llvm::Error::success();
  };

  std::string module_name(pathname);
  bool possible_package = false;

  if (extra_search_dir) {
    if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) {
      error = Status::FromError(std::move(e));
      return false;
    }
  } else {
    FileSpec module_file(pathname);
    FileSystem::Instance().Resolve(module_file);

    fs::file_status st;
    std::error_code ec = status(module_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 = Status::FromErrorStringWithFormatv("invalid pathname '{0}'",
                                                   pathname);
        return false;
      }
      // Not a filename, probably a package of some sort, let it go through.
      possible_package = true;
    } else if (is_directory(st) || is_regular_file(st)) {
      if (module_file.GetDirectory().empty()) {
        error = Status::FromErrorStringWithFormatv(
            "invalid directory name '{0}'", pathname);
        return false;
      }
      if (llvm::Error e = ExtendSysPath(module_file.GetDirectory().str())) {
        error = Status::FromError(std::move(e));
        return false;
      }
      module_name = module_file.GetFilename().str();
    } else {
      error = Status::FromErrorString(
          "no known way to import this module specification");
      return false;
    }
  }

  // Strip .py or .pyc extension
  llvm::StringRef extension = llvm::sys::path::extension(module_name);
  if (!extension.empty()) {
    if (extension == ".py")
      module_name.resize(module_name.length() - 3);
    else if (extension == ".pyc")
      module_name.resize(module_name.length() - 4);
  }

  if (!possible_package && module_name.find('.') != llvm::StringRef::npos) {
    error = Status::FromErrorStringWithFormat(
        "Python does not allow dots in module names: %s", module_name.c_str());
    return false;
  }

  if (module_name.find('-') != llvm::StringRef::npos) {
    error = Status::FromErrorStringWithFormat(
        "Python discourages dashes in module names: %s", module_name.c_str());
    return false;
  }

  // Check if the module is already imported.
  StreamString command_stream;
  command_stream.Clear();
  command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str());
  bool does_contain = false;
  // This call will succeed if the module was ever imported in any Debugger in
  // the lifetime of the process in which this LLDB framework is living.
  const bool does_contain_executed = ExecuteOneLineWithReturn(
      command_stream.GetData(),
      ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain,
      exc_options);

  const bool was_imported_globally = does_contain_executed && does_contain;
  const bool was_imported_locally =
      GetSessionDictionary()
          .GetItemForKey(PythonString(module_name))
          .IsAllocated();

  // now actually do the import
  command_stream.Clear();

  if (was_imported_globally || was_imported_locally) {
    if (!was_imported_locally)
      command_stream.Printf("import %s ; importlib.reload(%s)",
                            module_name.c_str(), module_name.c_str());
    else
      command_stream.Printf("importlib.reload(%s)", module_name.c_str());
  } else
    command_stream.Printf("import %s", module_name.c_str());

  error = ExecuteMultipleLines(command_stream.GetData(), exc_options);
  if (error.Fail())
    return false;

  // if we are here, everything worked
  // call __lldb_init_module(debugger,dict)
  if (!SWIGBridge::LLDBSwigPythonCallModuleInit(
          module_name.c_str(), m_dictionary_name.c_str(),
          m_debugger.shared_from_this())) {
    error = Status::FromErrorString("calling __lldb_init_module failed");
    return false;
  }

  if (module_sp) {
    // everything went just great, now set the module object
    command_stream.Clear();
    command_stream.Printf("%s", module_name.c_str());
    void *module_pyobj = nullptr;
    if (ExecuteOneLineWithReturn(
            command_stream.GetData(),
            ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj,
            exc_options) &&
        module_pyobj)
      *module_sp = std::make_shared<StructuredPythonObject>(PythonObject(
          PyRefType::Owned, static_cast<PyObject *>(module_pyobj)));
  }

  // Finally, if we got a target passed in, then we should tell the new module
  // about this target:
  if (target_sp)
    return SWIGBridge::LLDBSwigPythonCallModuleNewTarget(
        module_name.c_str(), m_dictionary_name.c_str(), target_sp);

  return true;
}

bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) {
  if (!word || !word[0])
    return false;

  llvm::StringRef word_sr(word);

  // filter out a few characters that would just confuse us and that are
  // clearly not keyword material anyway
  if (word_sr.find('"') != llvm::StringRef::npos ||
      word_sr.find('\'') != llvm::StringRef::npos)
    return false;

  StreamString command_stream;
  command_stream.Printf("keyword.iskeyword('%s')", word);
  bool result;
  ExecuteScriptOptions options;
  options.SetEnableIO(false);
  options.SetMaskoutErrors(true);
  options.SetSetLLDBGlobals(false);
  if (ExecuteOneLineWithReturn(command_stream.GetData(),
                               ScriptInterpreter::eScriptReturnTypeBool,
                               &result, options))
    return result;
  return false;
}

ScriptInterpreterPythonImpl::SynchronicityHandler::SynchronicityHandler(
    lldb::DebuggerSP debugger_sp, ScriptedCommandSynchronicity synchro)
    : m_debugger_sp(debugger_sp), m_synch_wanted(synchro),
      m_old_asynch(debugger_sp->GetAsyncExecution()) {
  if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous)
    m_debugger_sp->SetAsyncExecution(false);
  else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous)
    m_debugger_sp->SetAsyncExecution(true);
}

ScriptInterpreterPythonImpl::SynchronicityHandler::~SynchronicityHandler() {
  if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
    m_debugger_sp->SetAsyncExecution(m_old_asynch);
}

bool ScriptInterpreterPythonImpl::RunScriptBasedCommand(
    const char *impl_function, llvm::StringRef args,
    ScriptedCommandSynchronicity synchronicity,
    lldb_private::CommandReturnObject &cmd_retobj, Status &error,
    const lldb_private::ExecutionContext &exe_ctx) {
  if (!impl_function) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
  lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));

  if (!debugger_sp.get()) {
    error = Status::FromErrorString("invalid Debugger pointer");
    return false;
  }

  bool ret_val = false;

  {
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession |
                       (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
                   Locker::FreeLock | Locker::TearDownSession);

    SynchronicityHandler synch_handler(debugger_sp, synchronicity);

    std::string args_str = args.str();
    ret_val = SWIGBridge::LLDBSwigPythonCallCommand(
        impl_function, m_dictionary_name.c_str(), debugger_sp, args_str.c_str(),
        cmd_retobj, exe_ctx_ref_sp);
  }

  if (!ret_val) {
    error = Status::FromErrorString("unable to execute script function");
    return false;
  }
  if (cmd_retobj.GetStatus() == eReturnStatusFailed)
    return false;

  error.Clear();
  return ret_val;
}

/// In Python, a special attribute __doc__ contains the docstring for an object
/// (function, method, class, ...) if any is defined Otherwise, the attribute's
/// value is None.
bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item,
                                                          std::string &dest) {
  dest.clear();

  if (!item || !*item)
    return false;

  std::string command(item);
  command += ".__doc__";

  // Python is going to point this to valid data if ExecuteOneLineWithReturn
  // returns successfully.
  char *result_ptr = nullptr;

  if (ExecuteOneLineWithReturn(
          command, ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
          &result_ptr, ExecuteScriptOptions().SetEnableIO(false))) {
    if (result_ptr)
      dest.assign(result_ptr);
    return true;
  }

  StreamString str_stream;
  str_stream << "Function " << item
             << " was not found. Containing module might be missing.";
  dest = std::string(str_stream.GetString());

  return false;
}

std::unique_ptr<ScriptInterpreterLocker>
ScriptInterpreterPythonImpl::AcquireInterpreterLock() {
  std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(
      this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
      Locker::FreeLock | Locker::TearDownSession));
  return py_lock;
}

llvm::Error ScriptInterpreterPythonImpl::Initialize() {
  LLDB_SCOPED_TIMER();

  // RAII-based initialization which correctly handles multiple-initialization,
  // version- specific differences among Python 2 and Python 3, and saving and
  // restoring various other pieces of state that can get mucked with during
  // initialization.
  InitializePythonRAII initialize_guard;
  if (llvm::Error error = initialize_guard.DoInitialize())
    return error;

  LLDBSwigPyInit();

  // Update the path python uses to search for modules to include the current
  // directory.

  RunSimpleString("import sys");
  AddToSysPath(AddLocation::End, ".");

  // Don't denormalize paths when calling file_spec.GetPath().  On platforms
  // that use a backslash as the path separator, this will result in executing
  // python code containing paths with unescaped backslashes.  But Python also
  // accepts forward slashes, so to make life easier we just use that.
  if (FileSpec file_spec = GetPythonDir())
    AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
  if (FileSpec file_spec = HostInfo::GetShlibDir())
    AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));

  RunSimpleString("sys.dont_write_bytecode = 1; import "
                  "lldb.embedded_interpreter; from "
                  "lldb.embedded_interpreter import run_python_interpreter; "
                  "from lldb.embedded_interpreter import run_one_line");

#if LLDB_USE_PYTHON_SET_INTERRUPT
  // Python will not just overwrite its internal SIGINT handler but also the
  // one from the process. Backup the current SIGINT handler to prevent that
  // Python deletes it.
  RestoreSignalHandlerScope save_sigint(SIGINT);

  // Setup a default SIGINT signal handler that works the same way as the
  // normal Python REPL signal handler which raises a KeyboardInterrupt.
  // Also make sure to not pollute the user's REPL with the signal module nor
  // our utility function.
  RunSimpleString("def lldb_setup_sigint_handler():\n"
                  "  import signal;\n"
                  "  def signal_handler(sig, frame):\n"
                  "    raise KeyboardInterrupt()\n"
                  "  signal.signal(signal.SIGINT, signal_handler);\n"
                  "lldb_setup_sigint_handler();\n"
                  "del lldb_setup_sigint_handler\n");
#endif
  return llvm::Error::success();
}

void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location,
                                               std::string path) {
  std::string statement;
  if (location == AddLocation::Beginning) {
    statement.assign("sys.path.insert(0,\"");
    statement.append(path);
    statement.append("\")");
  } else {
    statement.assign("sys.path.append(\"");
    statement.append(path);
    statement.append("\")");
  }
  RunSimpleString(statement.c_str());
}

// We are intentionally NOT calling Py_Finalize here (this would be the logical
// place to call it).  Calling Py_Finalize here causes test suite runs to seg
// fault:  The test suite runs in Python.  It registers SBDebugger::Terminate to
// be called 'at_exit'.  When the test suite Python harness finishes up, it
// calls Py_Finalize, which calls all the 'at_exit' registered functions.
// SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate,
// which calls ScriptInterpreter::Terminate, which calls
// ScriptInterpreterPythonImpl::Terminate.  So if we call Py_Finalize here, we
// end up with Py_Finalize being called from within Py_Finalize, which results
// in a seg fault. Since this function only gets called when lldb is shutting
// down and going away anyway, the fact that we don't actually call Py_Finalize
// should not cause any problems (everything should shut down/go away anyway
// when the process exits).
//
// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); }
