diff options
Diffstat (limited to 'source/Interpreter/CommandInterpreter.cpp')
| -rw-r--r-- | source/Interpreter/CommandInterpreter.cpp | 195 | 
1 files changed, 123 insertions, 72 deletions
| diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index fb0fc7f700a5..56c8f8c0ad6a 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -44,12 +44,14 @@  #include "lldb/Core/Debugger.h"  #include "lldb/Core/Log.h" +#include "lldb/Core/State.h"  #include "lldb/Core/Stream.h"  #include "lldb/Core/StreamFile.h"  #include "lldb/Core/Timer.h"  #include "lldb/Host/Editline.h"  #include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h"  #include "lldb/Interpreter/Args.h"  #include "lldb/Interpreter/CommandCompletions.h" @@ -66,6 +68,10 @@  #include "lldb/Utility/CleanUp.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Path.h" +  using namespace lldb;  using namespace lldb_private; @@ -73,10 +79,10 @@ using namespace lldb_private;  static PropertyDefinition  g_properties[] =  { -    { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." }, -    { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." }, -    { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will stop running a 'command source' script upon encountering an error." }, -    { NULL                  , OptionValue::eTypeInvalid, true, 0    , NULL, NULL, NULL } +    { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." }, +    { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." }, +    { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." }, +    { nullptr                  , OptionValue::eTypeInvalid, true, 0    , nullptr, nullptr, nullptr }  };  enum @@ -125,21 +131,21 @@ bool  CommandInterpreter::GetExpandRegexAliases () const  {      const uint32_t idx = ePropertyExpandRegexAliases; -    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); +    return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);  }  bool  CommandInterpreter::GetPromptOnQuit () const  {      const uint32_t idx = ePropertyPromptOnQuit; -    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); +    return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);  }  bool  CommandInterpreter::GetStopCmdSourceOnError () const  {      const uint32_t idx = ePropertyStopCmdSourceOnError; -    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); +    return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);  }  void @@ -324,7 +330,7 @@ CommandInterpreter::Initialize ()      if (cmd_obj_sp)      {          alias_arguments_vector_sp.reset (new OptionArgVector); -#if defined (__arm__) +#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)          ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);  #else          ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=" LLDB_DEFAULT_SHELL " --", alias_arguments_vector_sp); @@ -351,6 +357,15 @@ CommandInterpreter::Initialize ()      }  } +void +CommandInterpreter::Clear() +{ +    m_command_io_handler_sp.reset(); +     +    if (m_script_interpreter_ap) +        m_script_interpreter_ap->Clear(); +} +  const char *  CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)  { @@ -405,9 +420,9 @@ CommandInterpreter::LoadCommandDictionary ()                                        {"^(-.*)$", "breakpoint set %1"},                                        {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},                                        {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"}, -                                      {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}}; +                                      {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}}; -    size_t num_regexes = sizeof break_regexes/sizeof(char *[2]); +    size_t num_regexes = llvm::array_lengthof(break_regexes);      std::unique_ptr<CommandObjectRegexCommand>      break_regex_cmd_ap(new CommandObjectRegexCommand (*this, @@ -702,7 +717,7 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo          CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;          StringList local_matches; -        if (matches == NULL) +        if (matches == nullptr)              matches = &local_matches;          unsigned int num_cmd_matches = 0; @@ -830,17 +845,17 @@ CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliase      Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.      CommandObjectSP ret_val;   // Possibly empty return value. -    if (cmd_cstr == NULL) +    if (cmd_cstr == nullptr)          return ret_val;      if (cmd_words.GetArgumentCount() == 1) -        return GetCommandSP(cmd_cstr, include_aliases, true, NULL); +        return GetCommandSP(cmd_cstr, include_aliases, true, nullptr);      else      {          // We have a multi-word command (seemingly), so we need to do more work.          // First, get the cmd_obj_sp for the first word in the command. -        CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL); -        if (cmd_obj_sp.get() != NULL) +        CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, nullptr); +        if (cmd_obj_sp.get() != nullptr)          {              // Loop through the rest of the words in the command (everything passed in was supposed to be part of a               // command name), and find the appropriate sub-command SP for each command word.... @@ -850,7 +865,7 @@ CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliase                  if (cmd_obj_sp->IsMultiwordObject())                  {                      cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j)); -                    if (cmd_obj_sp.get() == NULL) +                    if (cmd_obj_sp.get() == nullptr)                          // The sub-command name was invalid.  Fail and return the empty 'ret_val'.                          return ret_val;                  } @@ -890,7 +905,7 @@ CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)          return command_obj;      // If there wasn't an exact match then look for an inexact one in just the commands -    command_obj = GetCommandSP(cmd_cstr, false, false, NULL).get(); +    command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get();      // Finally, if there wasn't an inexact match among the commands, look for an inexact      // match in both the commands and aliases. @@ -1156,7 +1171,7 @@ CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)      // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will      // eventually be invoked by the given command line. -    CommandObject *cmd_obj = NULL; +    CommandObject *cmd_obj = nullptr;      std::string white_space (" \t\v");      size_t start = command_string.find_first_not_of (white_space);      size_t end = 0; @@ -1171,7 +1186,7 @@ CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)                  end = command_string.size();              std::string cmd_word = command_string.substr (start, end - start); -            if (cmd_obj == NULL) +            if (cmd_obj == nullptr)                  // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid                   // command or alias.                  cmd_obj = GetCommandObject (cmd_word.c_str()); @@ -1325,7 +1340,7 @@ CommandInterpreter::BuildAliasResult (const char *alias_name,                                        std::string &alias_result,                                        CommandReturnObject &result)  { -    CommandObject *alias_cmd_obj = NULL; +    CommandObject *alias_cmd_obj = nullptr;      Args cmd_args (raw_input_string.c_str());      alias_cmd_obj = GetCommandObject (alias_name);      StreamString result_str; @@ -1363,7 +1378,7 @@ CommandInterpreter::BuildAliasResult (const char *alias_name,                          int index = GetOptionArgumentPosition (value.c_str());                          if (index == 0)                              result_str.Printf ("%s", value.c_str()); -                        else if (index >= cmd_args.GetArgumentCount()) +                        else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())                          {                              result.AppendErrorWithFormat @@ -1446,12 +1461,12 @@ CommandInterpreter::PreprocessCommand (std::string &command)                      options.SetTryAllThreads(true);                      options.SetTimeoutUsec(0); -                    ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),  +                    ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(),                                                                                  exe_ctx.GetFramePtr(),                                                                                 expr_result_valobj_sp,                                                                                 options); -                    if (expr_result == eExecutionCompleted) +                    if (expr_result == eExpressionCompleted)                      {                          Scalar scalar;                          if (expr_result_valobj_sp->ResolveValue (scalar)) @@ -1486,24 +1501,29 @@ CommandInterpreter::PreprocessCommand (std::string &command)                              switch (expr_result)                              { -                                case eExecutionSetupError:  +                                case eExpressionSetupError:                                       error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());                                      break; -                                case eExecutionCompleted: +                                case eExpressionParseError: +                                    error.SetErrorStringWithFormat ("expression parse error for the expression '%s'", expr_str.c_str()); +                                    break; +                                case eExpressionResultUnavailable: +                                    error.SetErrorStringWithFormat ("expression error fetching result for the expression '%s'", expr_str.c_str()); +                                case eExpressionCompleted:                                      break; -                                case eExecutionDiscarded: +                                case eExpressionDiscarded:                                      error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());                                      break; -                                case eExecutionInterrupted: +                                case eExpressionInterrupted:                                      error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());                                      break; -                                case eExecutionHitBreakpoint: +                                case eExpressionHitBreakpoint:                                      error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());                                      break; -                                case eExecutionTimedOut: +                                case eExpressionTimedOut:                                      error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());                                      break; -                                case eExecutionStoppedForDebug: +                                case eExpressionStoppedForDebug:                                      error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());                                      break;                              } @@ -1530,7 +1550,7 @@ CommandInterpreter::HandleCommand (const char *command_line,  {      bool done = false; -    CommandObject *cmd_obj = NULL; +    CommandObject *cmd_obj = nullptr;      bool wants_raw_input = false;      std::string command_string (command_line);      std::string original_command_string (command_line); @@ -1540,7 +1560,7 @@ CommandInterpreter::HandleCommand (const char *command_line,      // Make a scoped cleanup object that will clear the crash description string       // on exit of this function. -    lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription); +    lldb_utility::CleanUp <const char *> crash_description_cleanup(nullptr, Host::SetCrashDescription);      if (log)          log->Printf ("Processing command: %s", command_line); @@ -1574,7 +1594,7 @@ CommandInterpreter::HandleCommand (const char *command_line,          else if (command_string[non_space] == CommandHistory::g_repeat_char)          {              const char *history_string = m_command_history.FindString(command_string.c_str() + non_space); -            if (history_string == NULL) +            if (history_string == nullptr)              {                  result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());                  result.SetStatus(eReturnStatusFailed); @@ -1650,7 +1670,7 @@ CommandInterpreter::HandleCommand (const char *command_line,          char quote_char = '\0';          std::string suffix;          ExtractCommand (command_string, next_word, suffix, quote_char); -        if (cmd_obj == NULL) +        if (cmd_obj == nullptr)          {              std::string full_name;              if (GetAliasFullName(next_word.c_str(), full_name)) @@ -1710,7 +1730,7 @@ CommandInterpreter::HandleCommand (const char *command_line,              }          } -        if (cmd_obj == NULL) +        if (cmd_obj == nullptr)          {              const size_t num_matches = matches.GetSize();              if (matches.GetSize() > 1) { @@ -1823,13 +1843,13 @@ CommandInterpreter::HandleCommand (const char *command_line,      // Take care of things like setting up the history command & calling the appropriate Execute method on the      // CommandObject, with the appropriate arguments. -    if (cmd_obj != NULL) +    if (cmd_obj != nullptr)      {          if (add_to_history)          {              Args command_args (revised_command_line.GetData());              const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0); -            if (repeat_command != NULL) +            if (repeat_command != nullptr)                  m_repeat_command.assign(repeat_command);              else                  m_repeat_command.assign(original_command_string.c_str()); @@ -1931,7 +1951,7 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,          if (num_command_matches == 1              && cmd_obj && cmd_obj->IsMultiwordObject() -            && matches.GetStringAtIndex(0) != NULL +            && matches.GetStringAtIndex(0) != nullptr              && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)          {              if (parsed_line.GetArgumentCount() == 1) @@ -1956,7 +1976,7 @@ CommandInterpreter::HandleCompletionMatches (Args &parsed_line,          // to complete the command.          // First see if there is a matching initial command:          CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0)); -        if (command_object == NULL) +        if (command_object == nullptr)          {              return 0;          } @@ -2002,7 +2022,7 @@ CommandInterpreter::HandleCompletion (const char *current_line,          else if (first_arg[0] == CommandHistory::g_repeat_char)          {              const char *history_string = m_command_history.FindString (first_arg); -            if (history_string != NULL) +            if (history_string != nullptr)              {                  matches.Clear();                  matches.InsertStringAtIndex(0, history_string); @@ -2254,7 +2274,7 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,                          }                      } -                    else if (index >= cmd_args.GetArgumentCount()) +                    else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())                      {                          result.AppendErrorWithFormat                                      ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", @@ -2364,17 +2384,21 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)          // "-" and the name of the program. If this file doesn't exist, we fall          // back to just the "~/.lldbinit" file. We also obey any requests to not          // load the init files. -        const char *init_file_path = "~/.lldbinit"; +        llvm::SmallString<64> home_dir_path; +        llvm::sys::path::home_directory(home_dir_path); +        FileSpec profilePath(home_dir_path.c_str(), false); +        profilePath.AppendPathComponent(".lldbinit"); +        std::string init_file_path = profilePath.GetPath();          if (m_skip_app_init_files == false)          { -            FileSpec program_file_spec (Host::GetProgramFileSpec()); +            FileSpec program_file_spec(HostInfo::GetProgramFileSpec());              const char *program_name = program_file_spec.GetFilename().AsCString();              if (program_name)              {                  char program_init_file_name[PATH_MAX]; -                ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name); +                ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path.c_str(), program_name);                  init_file.SetFile (program_init_file_name, true);                  if (!init_file.Exists())                      init_file.Clear(); @@ -2382,7 +2406,7 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)          }          if (!init_file && !m_skip_lldbinit_files) -			init_file.SetFile (init_file_path, true); +			init_file.SetFile (init_file_path.c_str(), false);      }      // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting @@ -2392,7 +2416,7 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)      {          const bool saved_batch = SetBatchCommandMode (true);          HandleCommandsFromFile (init_file, -                                NULL,           // Execution context +                                nullptr,           // Execution context                                  eLazyBoolYes,   // Stop on continue                                  eLazyBoolNo,    // Stop on error                                  eLazyBoolNo,    // Don't echo commands @@ -2445,7 +2469,7 @@ CommandInterpreter::HandleCommands (const StringList &commands,      // If we've been given an execution context, set it at the start, but don't keep resetting it or we will      // cause series of commands that change the context, then do an operation that relies on that context to fail. -    if (override_context != NULL) +    if (override_context != nullptr)          UpdateExecutionContext (override_context);      if (!stop_on_continue) @@ -2475,9 +2499,9 @@ CommandInterpreter::HandleCommands (const StringList &commands,          if (!add_to_history)              m_command_source_depth++;          bool success = HandleCommand(cmd, add_to_history, tmp_result, -                                     NULL, /* override_context */ +                                     nullptr, /* override_context */                                       true, /* repeat_on_empty_command */ -                                     override_context != NULL /* no_context_switching */); +                                     override_context != nullptr /* no_context_switching */);          if (!add_to_history)              m_command_source_depth--; @@ -2490,20 +2514,20 @@ CommandInterpreter::HandleCommands (const StringList &commands,          if (!success || !tmp_result.Succeeded())          {              const char *error_msg = tmp_result.GetErrorData(); -            if (error_msg == NULL || error_msg[0] == '\0') +            if (error_msg == nullptr || error_msg[0] == '\0')                  error_msg = "<unknown error>.\n";              if (stop_on_error)              { -                result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' failed with %s", -                                         idx, cmd, error_msg); +                result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s", +                                                (uint64_t)idx, cmd, error_msg);                  result.SetStatus (eReturnStatusFailed);                  m_debugger.SetAsyncExecution (old_async_execution);                  return;              }              else if (print_results)              { -                result.AppendMessageWithFormat ("Command #%zu '%s' failed with %s", -                                                idx + 1,  +                result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s", +                                                (uint64_t)idx + 1,                                                  cmd,                                                   error_msg);              } @@ -2527,10 +2551,10 @@ CommandInterpreter::HandleCommands (const StringList &commands,                  // status in our real result before returning.  This is an error if the continue was not the                  // last command in the set of commands to be run.                  if (idx != num_lines - 1) -                    result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' continued the target.\n",  -                                                 idx + 1, cmd); +                    result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' continued the target.\n",  +                                                 (uint64_t)idx + 1, cmd);                  else -                    result.AppendMessageWithFormat ("Command #%zu '%s' continued the target.\n", idx + 1, cmd); +                    result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' continued the target.\n", (uint64_t)idx + 1, cmd);                  result.SetStatus(tmp_result.GetStatus());                  m_debugger.SetAsyncExecution (old_async_execution); @@ -2660,9 +2684,10 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,                                                                empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream                                                                empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream                                                                flags, -                                                              NULL, // Pass in NULL for "editline_name" so no history is saved, or written +                                                              nullptr, // Pass in NULL for "editline_name" so no history is saved, or written                                                                debugger.GetPrompt(),                                                                false, // Not multi-line +                                                              0,                                                                *this));              const bool old_async_execution = debugger.GetAsyncExecution(); @@ -2699,11 +2724,11 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,  ScriptInterpreter *  CommandInterpreter::GetScriptInterpreter (bool can_create)  { -    if (m_script_interpreter_ap.get() != NULL) +    if (m_script_interpreter_ap.get() != nullptr)          return m_script_interpreter_ap.get();      if (!can_create) -        return NULL; +        return nullptr;      // <rdar://problem/11751427>      // we need to protect the initialization of the script interpreter @@ -2928,7 +2953,7 @@ CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList  void  CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)  { -    if (override_context != NULL) +    if (override_context != nullptr)      {          m_exe_ctx_ref = *override_context;      } @@ -3041,6 +3066,24 @@ CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &      }  } +bool +CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler) +{ +    ExecutionContext exe_ctx (GetExecutionContext()); +    Process *process = exe_ctx.GetProcessPtr(); +     +    if (process) +    { +        StateType state = process->GetState(); +        if (StateIsRunningState(state)) +        { +            process->Halt(); +            return true; // Don't do any updating when we are running +        } +    } +    return false; +} +  void  CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,                                                    IOHandlerDelegate &delegate, @@ -3052,6 +3095,7 @@ CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,                                                        "lldb",       // Name of input reader for history                                                        prompt,       // Prompt                                                        true,         // Get multiple lines +                                                      0,            // Don't show line numbers                                                        delegate));   // IOHandlerDelegate      if (io_handler_sp) @@ -3077,6 +3121,7 @@ CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt,                                                        "lldb-python",    // Name of input reader for history                                                        prompt,           // Prompt                                                        true,             // Get multiple lines +                                                      0,                // Don't show line numbers                                                        delegate));       // IOHandlerDelegate      if (io_handler_sp) @@ -3100,17 +3145,23 @@ void  CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,                                            bool spawn_thread)  { -    const bool multiple_lines = false; // Only get one line at a time -    if (!m_command_io_handler_sp) -        m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, -                                                             m_debugger.GetInputFile(), -                                                             m_debugger.GetOutputFile(), -                                                             m_debugger.GetErrorFile(), -                                                             eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult, -                                                             "lldb", -                                                             m_debugger.GetPrompt(), -                                                             multiple_lines, -                                                             *this)); +    // Only get one line at a time +    const bool multiple_lines = false; +     +    // Always re-create the IOHandlerEditline in case the input +    // changed. The old instance might have had a non-interactive +    // input and now it does or vice versa. +    m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, +                                                         m_debugger.GetInputFile(), +                                                         m_debugger.GetOutputFile(), +                                                         m_debugger.GetErrorFile(), +                                                         eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult, +                                                         "lldb", +                                                         m_debugger.GetPrompt(), +                                                         multiple_lines, +                                                         0,            // Don't show line numbers +                                                         *this)); +      m_debugger.PushIOHandler(m_command_io_handler_sp);      if (auto_handle_events) | 
