diff --git a/lldb/include/lldb/API/SBCommandInterpreterRunOptions.h b/lldb/include/lldb/API/SBCommandInterpreterRunOptions.h --- a/lldb/include/lldb/API/SBCommandInterpreterRunOptions.h +++ b/lldb/include/lldb/API/SBCommandInterpreterRunOptions.h @@ -13,6 +13,11 @@ #include "lldb/API/SBDefines.h" +namespace lldb_private { +class CommandInterpreterRunOptions; +class CommandInterpreterRunResult; +} // namespace lldb_private + namespace lldb { class LLDB_API SBCommandInterpreterRunOptions { @@ -69,6 +74,29 @@ m_opaque_up; }; +class LLDB_API SBCommandInterpreterRunResult { + friend class SBDebugger; + friend class SBCommandInterpreter; + +public: + SBCommandInterpreterRunResult(); + SBCommandInterpreterRunResult(const SBCommandInterpreterRunResult &rhs); + ~SBCommandInterpreterRunResult(); + + SBCommandInterpreterRunResult & + operator=(const SBCommandInterpreterRunResult &rhs); + + int GetNumberOfErrors() const; + lldb::CommandInterpreterResult GetResult() const; + +private: + SBCommandInterpreterRunResult( + const lldb_private::CommandInterpreterRunResult &rhs); + + // This is set in the constructor and will always be valid. + std::unique_ptr m_opaque_up; +}; + } // namespace lldb #endif // LLDB_API_SBCOMMANDINTERPRETERRUNOPTIONS_H diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -331,6 +331,9 @@ int &num_errors, bool &quit_requested, bool &stopped_for_crash); + SBCommandInterpreterRunResult + RunCommandInterpreter(const SBCommandInterpreterRunOptions &options); + SBError RunREPL(lldb::LanguageType language, const char *repl_options); private: diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h --- a/lldb/include/lldb/API/SBDefines.h +++ b/lldb/include/lldb/API/SBDefines.h @@ -28,6 +28,7 @@ class LLDB_API SBCommand; class LLDB_API SBCommandInterpreter; class LLDB_API SBCommandInterpreterRunOptions; +class LLDB_API SBCommandInterpreterRunResult; class LLDB_API SBCommandPluginInterface; class LLDB_API SBCommandReturnObject; class LLDB_API SBCommunication; diff --git a/lldb/source/API/SBCommandInterpreterRunOptions.cpp b/lldb/source/API/SBCommandInterpreterRunOptions.cpp --- a/lldb/source/API/SBCommandInterpreterRunOptions.cpp +++ b/lldb/source/API/SBCommandInterpreterRunOptions.cpp @@ -163,6 +163,58 @@ return *m_opaque_up; } +SBCommandInterpreterRunResult::SBCommandInterpreterRunResult() + : m_opaque_up(new CommandInterpreterRunResult()) + +{ + LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommandInterpreterRunResult); +} + +SBCommandInterpreterRunResult::SBCommandInterpreterRunResult( + const SBCommandInterpreterRunResult &rhs) + : m_opaque_up(new CommandInterpreterRunResult()) { + LLDB_RECORD_CONSTRUCTOR(SBCommandInterpreterRunResult, + (const lldb::SBCommandInterpreterRunResult &), rhs); + + *m_opaque_up = *rhs.m_opaque_up; +} + +SBCommandInterpreterRunResult::SBCommandInterpreterRunResult( + const CommandInterpreterRunResult &rhs) + : m_opaque_up() { + m_opaque_up.reset(new CommandInterpreterRunResult(rhs)); +} + +SBCommandInterpreterRunResult::~SBCommandInterpreterRunResult() = default; + +SBCommandInterpreterRunResult &SBCommandInterpreterRunResult::operator=( + const SBCommandInterpreterRunResult &rhs) { + LLDB_RECORD_METHOD(lldb::SBCommandInterpreterRunResult &, + SBCommandInterpreterRunResult, + operator=,(const lldb::SBCommandInterpreterRunResult &), + rhs); + + if (this == &rhs) + return *this; + *m_opaque_up = *rhs.m_opaque_up; + return LLDB_RECORD_RESULT(*this); +} + +int SBCommandInterpreterRunResult::GetNumberOfErrors() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(int, SBCommandInterpreterRunResult, + GetNumberOfErrors); + + return m_opaque_up->GetNumErrors(); +} + +lldb::CommandInterpreterResult +SBCommandInterpreterRunResult::GetResult() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::CommandInterpreterResult, + SBCommandInterpreterRunResult, GetResult); + + return m_opaque_up->GetResult(); +} + namespace lldb_private { namespace repro { @@ -204,6 +256,16 @@ GetSpawnThread, ()); LLDB_REGISTER_METHOD(void, SBCommandInterpreterRunOptions, SetSpawnThread, (bool)); + LLDB_REGISTER_CONSTRUCTOR(SBCommandInterpreterRunResult, ()); + LLDB_REGISTER_CONSTRUCTOR(SBCommandInterpreterRunResult, + (const lldb::SBCommandInterpreterRunResult &)); + LLDB_REGISTER_METHOD(lldb::SBCommandInterpreterRunResult &, + SBCommandInterpreterRunResult, + operator=,(const lldb::SBCommandInterpreterRunResult &)); + LLDB_REGISTER_METHOD_CONST(int, SBCommandInterpreterRunResult, + GetNumberOfErrors, ()); + LLDB_REGISTER_METHOD_CONST(lldb::CommandInterpreterResult, + SBCommandInterpreterRunResult, GetResult, ()); } } // namespace repro diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -1200,6 +1200,22 @@ } } +SBCommandInterpreterRunResult SBDebugger::RunCommandInterpreter( + const SBCommandInterpreterRunOptions &options) { + LLDB_RECORD_METHOD(lldb::SBCommandInterpreterRunResult, SBDebugger, + RunCommandInterpreter, + (const lldb::SBCommandInterpreterRunOptions &), options); + + if (!m_opaque_sp) + return LLDB_RECORD_RESULT(SBCommandInterpreterRunResult()); + + CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter(); + CommandInterpreterRunResult result = + interp.RunCommandInterpreter(options.ref()); + + return LLDB_RECORD_RESULT(SBCommandInterpreterRunResult(result)); +} + SBError SBDebugger::RunREPL(lldb::LanguageType language, const char *repl_options) { LLDB_RECORD_METHOD(lldb::SBError, SBDebugger, RunREPL, @@ -1826,6 +1842,9 @@ (lldb::SBTypeNameSpecifier)); LLDB_REGISTER_METHOD(bool, SBDebugger, EnableLog, (const char *, const char **)); + LLDB_REGISTER_METHOD(lldb::SBCommandInterpreterRunResult, SBDebugger, + RunCommandInterpreter, + (const lldb::SBCommandInterpreterRunOptions &)); } } // namespace repro diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -588,10 +588,7 @@ const char *commands_data = commands_stream.GetData(); const size_t commands_size = commands_stream.GetSize(); - // The command file might have requested that we quit, this variable will - // track that. - bool quit_requested = false; - bool stopped_for_crash = false; + bool go_interactive = true; if ((commands_data != nullptr) && (commands_size != 0u)) { FILE *commands_file = PrepareCommandsForSourcing(commands_data, commands_size); @@ -603,23 +600,27 @@ m_debugger.SetInputFileHandle(commands_file, true); - // Set the debugger into Sync mode when running the command file. - // Otherwise command files - // that run the target won't run in a sensible way. + // Set the debugger into Sync mode when running the command file. Otherwise + // command files that run the target won't run in a sensible way. bool old_async = m_debugger.GetAsync(); m_debugger.SetAsync(false); - int num_errors = 0; SBCommandInterpreterRunOptions options; + options.SetAutoHandleEvents(true); + options.SetSpawnThread(false); options.SetStopOnError(true); - if (m_option_data.m_batch) - options.SetStopOnCrash(true); - - m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, - num_errors, quit_requested, - stopped_for_crash); - - if (m_option_data.m_batch && stopped_for_crash && + options.SetStopOnCrash(m_option_data.m_batch); + + SBCommandInterpreterRunResult results = + m_debugger.RunCommandInterpreter(options); + if (results.GetResult() == lldb::eCommandInterpreterResultQuitRequested) + go_interactive = false; + if (m_option_data.m_batch && + results.GetResult() != lldb::eCommandInterpreterResultInferiorCrash) + go_interactive = false; + + if (m_option_data.m_batch && + results.GetResult() == lldb::eCommandInterpreterResultInferiorCrash && !m_option_data.m_after_crash_commands.empty()) { SBStream crash_commands_stream; WriteCommandsForSourcing(eCommandPlacementAfterCrash, @@ -629,30 +630,20 @@ commands_file = PrepareCommandsForSourcing(crash_commands_data, crash_commands_size); if (commands_file != nullptr) { - bool local_quit_requested; - bool local_stopped_for_crash; m_debugger.SetInputFileHandle(commands_file, true); - - m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, - num_errors, local_quit_requested, - local_stopped_for_crash); - if (local_quit_requested) - quit_requested = true; + SBCommandInterpreterRunResult local_results = + m_debugger.RunCommandInterpreter(options); + if (local_results.GetResult() == + lldb::eCommandInterpreterResultQuitRequested) + go_interactive = false; } } m_debugger.SetAsync(old_async); } - // Now set the input file handle to STDIN and run the command - // interpreter again in interactive mode or repl mode and let the debugger - // take ownership of stdin - - bool go_interactive = true; - if (quit_requested) - go_interactive = false; - else if (m_option_data.m_batch && !stopped_for_crash) - go_interactive = false; - + // Now set the input file handle to STDIN and run the command interpreter + // again in interactive mode or repl mode and let the debugger take ownership + // of stdin. if (go_interactive) { m_debugger.SetInputFileHandle(stdin, true);