//===-- CommandInterpreter.cpp ----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/lldb-python.h"

#include <string>
#include <vector>
#include <stdlib.h>

#include "CommandObjectScript.h"
#include "lldb/Interpreter/CommandObjectRegexCommand.h"

#include "../Commands/CommandObjectApropos.h"
#include "../Commands/CommandObjectArgs.h"
#include "../Commands/CommandObjectBreakpoint.h"
#include "../Commands/CommandObjectDisassemble.h"
#include "../Commands/CommandObjectExpression.h"
#include "../Commands/CommandObjectFrame.h"
#include "../Commands/CommandObjectGUI.h"
#include "../Commands/CommandObjectHelp.h"
#include "../Commands/CommandObjectLog.h"
#include "../Commands/CommandObjectMemory.h"
#include "../Commands/CommandObjectPlatform.h"
#include "../Commands/CommandObjectPlugin.h"
#include "../Commands/CommandObjectProcess.h"
#include "../Commands/CommandObjectQuit.h"
#include "../Commands/CommandObjectRegister.h"
#include "../Commands/CommandObjectSettings.h"
#include "../Commands/CommandObjectSource.h"
#include "../Commands/CommandObjectCommands.h"
#include "../Commands/CommandObjectSyntax.h"
#include "../Commands/CommandObjectTarget.h"
#include "../Commands/CommandObjectThread.h"
#include "../Commands/CommandObjectType.h"
#include "../Commands/CommandObjectVersion.h"
#include "../Commands/CommandObjectWatchpoint.h"


#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"

#ifndef LLDB_DISABLE_LIBEDIT
#include "lldb/Host/Editline.h"
#endif
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"

#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Interpreter/ScriptInterpreterNone.h"
#include "lldb/Interpreter/ScriptInterpreterPython.h"


#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/TargetList.h"

#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;


static PropertyDefinition
g_properties[] =
{
    { "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
{
    ePropertyExpandRegexAliases = 0,
    ePropertyPromptOnQuit = 1,
    ePropertyStopCmdSourceOnError = 2
};

ConstString &
CommandInterpreter::GetStaticBroadcasterClass ()
{
    static ConstString class_name ("lldb.commandInterpreter");
    return class_name;
}

CommandInterpreter::CommandInterpreter
(
    Debugger &debugger,
    ScriptLanguage script_language,
    bool synchronous_execution
) :
    Broadcaster (&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
    Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
    IOHandlerDelegate (IOHandlerDelegate::Completion::LLDBCommand),
    m_debugger (debugger),
    m_synchronous_execution (synchronous_execution),
    m_skip_lldbinit_files (false),
    m_skip_app_init_files (false),
    m_script_interpreter_ap (),
    m_command_io_handler_sp (),
    m_comment_char ('#'),
    m_batch_command_mode (false),
    m_truncation_warning(eNoTruncation),
    m_command_source_depth (0),
    m_num_errors(0),
    m_quit_requested(false),
    m_stopped_for_crash(false)

{
    debugger.SetScriptLanguage (script_language);
    SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
    SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
    SetEventName (eBroadcastBitQuitCommandReceived, "quit");    
    CheckInWithManager ();
    m_collection_sp->Initialize (g_properties);
}

bool
CommandInterpreter::GetExpandRegexAliases () const
{
    const uint32_t idx = ePropertyExpandRegexAliases;
    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 (nullptr, idx, g_properties[idx].default_uint_value != 0);
}

bool
CommandInterpreter::GetStopCmdSourceOnError () const
{
    const uint32_t idx = ePropertyStopCmdSourceOnError;
    return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
}

void
CommandInterpreter::Initialize ()
{
    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);

    CommandReturnObject result;

    LoadCommandDictionary ();

    // Set up some initial aliases.
    CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
    if (cmd_obj_sp)
    {
        AddAlias ("q", cmd_obj_sp);
        AddAlias ("exit", cmd_obj_sp);
    }
    
    cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
    if (cmd_obj_sp)
    {
        AddAlias ("attach", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("process detach",false);
    if (cmd_obj_sp)
    {
        AddAlias ("detach", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("process continue", false);
    if (cmd_obj_sp)
    {
        AddAlias ("c", cmd_obj_sp);
        AddAlias ("continue", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
    if (cmd_obj_sp)
        AddAlias ("b", cmd_obj_sp);

    cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
    if (cmd_obj_sp)
        AddAlias ("tbreak", cmd_obj_sp);

    cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
    if (cmd_obj_sp)
    {
        AddAlias ("stepi", cmd_obj_sp);
        AddAlias ("si", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false);
    if (cmd_obj_sp)
    {
        AddAlias ("nexti", cmd_obj_sp);
        AddAlias ("ni", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
    if (cmd_obj_sp)
    {
        AddAlias ("s", cmd_obj_sp);
        AddAlias ("step", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
    if (cmd_obj_sp)
    {
        AddAlias ("n", cmd_obj_sp);
        AddAlias ("next", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
    if (cmd_obj_sp)
    {
        AddAlias ("finish", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("frame select", false);
    if (cmd_obj_sp)
    {
        AddAlias ("f", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("thread select", false);
    if (cmd_obj_sp)
    {
        AddAlias ("t", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false);
    if (cmd_obj_sp)
    {
        AddAlias ("j", cmd_obj_sp);
        AddAlias ("jump", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
    if (cmd_obj_sp)
    {
        AddAlias ("l", cmd_obj_sp);
        AddAlias ("list", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
    if (cmd_obj_sp)
    {
        AddAlias ("env", cmd_obj_sp);
    }

    cmd_obj_sp = GetCommandSPExact ("memory read", false);
    if (cmd_obj_sp)
        AddAlias ("x", cmd_obj_sp);

    cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
    if (cmd_obj_sp)
        AddAlias ("up", cmd_obj_sp);

    cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
    if (cmd_obj_sp)
        AddAlias ("down", cmd_obj_sp);

    cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
    if (cmd_obj_sp)
        AddAlias ("display", cmd_obj_sp);
        
    cmd_obj_sp = GetCommandSPExact ("disassemble", false);
    if (cmd_obj_sp)
        AddAlias ("dis", cmd_obj_sp);

    cmd_obj_sp = GetCommandSPExact ("disassemble", false);
    if (cmd_obj_sp)
        AddAlias ("di", cmd_obj_sp);



    cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
    if (cmd_obj_sp)
        AddAlias ("undisplay", cmd_obj_sp);

    cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
    if (cmd_obj_sp)
        AddAlias ("bt", cmd_obj_sp);

    cmd_obj_sp = GetCommandSPExact ("target create", false);
    if (cmd_obj_sp)
        AddAlias ("file", cmd_obj_sp);

    cmd_obj_sp = GetCommandSPExact ("target modules", false);
    if (cmd_obj_sp)
        AddAlias ("image", cmd_obj_sp);


    OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
    
    cmd_obj_sp = GetCommandSPExact ("expression", false);
    if (cmd_obj_sp)
    {        
        ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
        AddAlias ("p", cmd_obj_sp);
        AddAlias ("print", cmd_obj_sp);
        AddAlias ("call", cmd_obj_sp);
        AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
        AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
        AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);

        alias_arguments_vector_sp.reset (new OptionArgVector);
        ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp);
        AddAlias ("po", cmd_obj_sp);
        AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
    }
    
    cmd_obj_sp = GetCommandSPExact ("process kill", false);
    if (cmd_obj_sp)
    {
        AddAlias ("kill", cmd_obj_sp);
    }
    
    cmd_obj_sp = GetCommandSPExact ("process launch", false);
    if (cmd_obj_sp)
    {
        alias_arguments_vector_sp.reset (new OptionArgVector);
#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
        ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
#else
        std::string shell_option;
        shell_option.append("--shell=");
        shell_option.append(HostInfo::GetDefaultShell().GetPath());
        shell_option.append(" --");
        ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp);
#endif
        AddAlias ("r", cmd_obj_sp);
        AddAlias ("run", cmd_obj_sp);
        AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp);
        AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp);
    }
    
    cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
    if (cmd_obj_sp)
    {
        AddAlias ("add-dsym", cmd_obj_sp);
    }
    
    cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
    if (cmd_obj_sp)
    {
        alias_arguments_vector_sp.reset (new OptionArgVector);
        ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp);
        AddAlias ("rbreak", cmd_obj_sp);
        AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp);
    }
}

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)
{
    // This function has not yet been implemented.

    // Look for any embedded script command
    // If found,
    //    get interpreter object from the command dictionary,
    //    call execute_one_command on it,
    //    get the results as a string,
    //    substitute that string for current stuff.

    return arg;
}


void
CommandInterpreter::LoadCommandDictionary ()
{
    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);

    lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
    
    m_command_dict["apropos"]   = CommandObjectSP (new CommandObjectApropos (*this));
    m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
    m_command_dict["command"]   = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
    m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
    m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
    m_command_dict["frame"]     = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
    m_command_dict["gui"]       = CommandObjectSP (new CommandObjectGUI (*this));
    m_command_dict["help"]      = CommandObjectSP (new CommandObjectHelp (*this));
    m_command_dict["log"]       = CommandObjectSP (new CommandObjectLog (*this));
    m_command_dict["memory"]    = CommandObjectSP (new CommandObjectMemory (*this));
    m_command_dict["platform"]  = CommandObjectSP (new CommandObjectPlatform (*this));
    m_command_dict["plugin"]    = CommandObjectSP (new CommandObjectPlugin (*this));
    m_command_dict["process"]   = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
    m_command_dict["quit"]      = CommandObjectSP (new CommandObjectQuit (*this));
    m_command_dict["register"]  = CommandObjectSP (new CommandObjectRegister (*this));
    m_command_dict["script"]    = CommandObjectSP (new CommandObjectScript (*this, script_language));
    m_command_dict["settings"]  = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
    m_command_dict["source"]    = CommandObjectSP (new CommandObjectMultiwordSource (*this));
    m_command_dict["target"]    = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
    m_command_dict["thread"]    = CommandObjectSP (new CommandObjectMultiwordThread (*this));
    m_command_dict["type"]      = CommandObjectSP (new CommandObjectType (*this));
    m_command_dict["version"]   = CommandObjectSP (new CommandObjectVersion (*this));
    m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));

    const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
                                      {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"},
                                      {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
                                      {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
                                      {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
                                      {"^(-.*)$", "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'"}};
    
    size_t num_regexes = llvm::array_lengthof(break_regexes);
        
    std::unique_ptr<CommandObjectRegexCommand>
    break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                      "_regexp-break",
                                                      "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.\n",
                                                      "\n_regexp-break <filename>:<linenum> # _regexp-break main.c:12      // Break on line 12 of main.c\n"
                                                      "_regexp-break <linenum>            # _regexp-break 12             // Break on line 12 of current file\n"
                                                      "_regexp-break <address>            # _regexp-break 0x1234000      // Break on address 0x1234000\n"
                                                      "_regexp-break <name>               # _regexp-break main           // Break in 'main' after the prologue\n"
                                                      "_regexp-break &<name>              # _regexp-break &main          // Break on the first instruction in 'main'\n"
                                                      "_regexp-break <module>`<name>      # _regexp-break libc.so`malloc // Break in 'malloc' only in the 'libc.so' shared library\n"
                                                      "_regexp-break /<source-regex>/     # _regexp-break /break here/   // Break on all lines that match the regular expression 'break here' in the current file.\n",
                                                      2,
                                                      CommandCompletions::eSymbolCompletion |
                                                      CommandCompletions::eSourceFileCompletion,
                                                      false));

    if (break_regex_cmd_ap.get())
    {
        bool success = true;
        for (size_t i = 0; i < num_regexes; i++)
        {
            success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
            if (!success)
                break;
        }
        success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");

        if (success)
        {
            CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
            m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                      "_regexp-tbreak",
                                                      "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
                                                      "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
                                                       2,
                                                       CommandCompletions::eSymbolCompletion |
                                                       CommandCompletions::eSourceFileCompletion,
                                                       false));

    if (tbreak_regex_cmd_ap.get())
    {
        bool success = true;
        for (size_t i = 0; i < num_regexes; i++)
        {
            // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
            char buffer[1024];
            int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
            assert (num_printed < 1024);
	    // Quiet unused variable warning for release builds.
	    (void) num_printed;
            success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
            if (!success)
                break;
        }
        success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");

        if (success)
        {
            CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
            m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                       "_regexp-attach",
                                                       "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.",
                                                       "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]",
                                                       2,
                                                       0,
                                                       false));
    if (attach_regex_cmd_ap.get())
    {
        if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
            attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach'
            attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") &&
            attach_regex_cmd_ap->AddRegexCommand("^$", "process attach"))
        {
            CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
            m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
        }
    }
    
    std::unique_ptr<CommandObjectRegexCommand>
    down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                     "_regexp-down",
                                                     "Go down \"n\" frames in the stack (1 frame by default).",
                                                     "_regexp-down [n]",
                                                     2,
                                                     0,
                                                     false));
    if (down_regex_cmd_ap.get())
    {
        if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
            down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
        {
            CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
            m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
        }
    }
    
    std::unique_ptr<CommandObjectRegexCommand>
    up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                   "_regexp-up",
                                                   "Go up \"n\" frames in the stack (1 frame by default).",
                                                   "_regexp-up [n]",
                                                   2,
                                                   0,
                                                   false));
    if (up_regex_cmd_ap.get())
    {
        if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
            up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
        {
            CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
            m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                        "_regexp-display",
                                                        "Add an expression evaluation stop-hook.",
                                                        "_regexp-display expression",
                                                        2,
                                                        0,
                                                        false));
    if (display_regex_cmd_ap.get())
    {
        if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
        {
            CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
            m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                          "_regexp-undisplay",
                                                          "Remove an expression evaluation stop-hook.",
                                                          "_regexp-undisplay stop-hook-number",
                                                          2,
                                                          0,
                                                          false));
    if (undisplay_regex_cmd_ap.get())
    {
        if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
        {
            CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
            m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
                                                             "gdb-remote",
                                                             "Connect to a remote GDB server.  If no hostname is provided, localhost is assumed.",
                                                             "gdb-remote [<hostname>:]<portnum>",
                                                             2,
                                                             0,
                                                             false));
    if (connect_gdb_remote_cmd_ap.get())
    {
        if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
            connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1"))
        {
            CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
            m_command_dict[command_sp->GetCommandName ()] = command_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
                                                             "kdp-remote",
                                                             "Connect to a remote KDP server.  udp port 41139 is the default port number.",
                                                             "kdp-remote <hostname>[:<portnum>]",
                                                             2,
                                                             0,
                                                             false));
    if (connect_kdp_remote_cmd_ap.get())
    {
        if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
            connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
        {
            CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
            m_command_dict[command_sp->GetCommandName ()] = command_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                   "_regexp-bt",
                                                   "Show a backtrace.  An optional argument is accepted; if that argument is a number, it specifies the number of frames to display.  If that argument is 'all', full backtraces of all threads are displayed.",
                                                   "bt [<digit>|all]",
                                                   2,
                                                   0,
                                                   false));
    if (bt_regex_cmd_ap.get())
    {
        // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
        // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
        // so now "bt 3" is the preferred form, in line with gdb.
        if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") &&
            bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") &&
            bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
            bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace"))
        {
            CommandObjectSP command_sp(bt_regex_cmd_ap.release());
            m_command_dict[command_sp->GetCommandName ()] = command_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                     "_regexp-list",
                                                     "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
                                                     "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]",
                                                     2,
                                                     CommandCompletions::eSourceFileCompletion,
                                                     false));
    if (list_regex_cmd_ap.get())
    {
        if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
            list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") &&
            list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") &&
            list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
            list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") &&
            list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") &&
            list_regex_cmd_ap->AddRegexCommand("^$", "source list"))
        {
            CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
            m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                    "_regexp-env",
                                                    "Implements a shortcut to viewing and setting environment variables.",
                                                    "_regexp-env\n_regexp-env FOO=BAR",
                                                    2,
                                                    0,
                                                    false));
    if (env_regex_cmd_ap.get())
    {
        if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
            env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1"))
        {
            CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
            m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp;
        }
    }

    std::unique_ptr<CommandObjectRegexCommand>
    jump_regex_cmd_ap(new CommandObjectRegexCommand (*this,
                                                    "_regexp-jump",
                                                    "Sets the program counter to a new address.",
                                                    "_regexp-jump [<line>]\n"
                                                    "_regexp-jump [<+-lineoffset>]\n"
                                                    "_regexp-jump [<file>:<line>]\n"
                                                    "_regexp-jump [*<addr>]\n",
                                                     2,
                                                     0,
                                                     false));
    if (jump_regex_cmd_ap.get())
    {
        if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") &&
            jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") &&
            jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") &&
            jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1"))
        {
            CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release());
            m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp;
        }
    }

}

int
CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
                                                          StringList &matches)
{
    CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);

    if (include_aliases)
    {
        CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
    }

    return matches.GetSize();
}

CommandObjectSP
CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
{
    CommandObject::CommandMap::iterator pos;
    CommandObjectSP command_sp;

    std::string cmd(cmd_cstr);

    if (HasCommands())
    {
        pos = m_command_dict.find(cmd);
        if (pos != m_command_dict.end())
            command_sp = pos->second;
    }

    if (include_aliases && HasAliases())
    {
        pos = m_alias_dict.find(cmd);
        if (pos != m_alias_dict.end())
            command_sp = pos->second;
    }

    if (HasUserCommands())
    {
        pos = m_user_dict.find(cmd);
        if (pos != m_user_dict.end())
            command_sp = pos->second;
    }

    if (!exact && !command_sp)
    {
        // We will only get into here if we didn't find any exact matches.
        
        CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;

        StringList local_matches;
        if (matches == nullptr)
            matches = &local_matches;

        unsigned int num_cmd_matches = 0;
        unsigned int num_alias_matches = 0;
        unsigned int num_user_matches = 0;
        
        // Look through the command dictionaries one by one, and if we get only one match from any of
        // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
        
        if (HasCommands())
        {
            num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
        }

        if (num_cmd_matches == 1)
        {
            cmd.assign(matches->GetStringAtIndex(0));
            pos = m_command_dict.find(cmd);
            if (pos != m_command_dict.end())
                real_match_sp = pos->second;
        }

        if (include_aliases && HasAliases())
        {
            num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);

        }

        if (num_alias_matches == 1)
        {
            cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
            pos = m_alias_dict.find(cmd);
            if (pos != m_alias_dict.end())
                alias_match_sp = pos->second;
        }

        if (HasUserCommands())
        {
            num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
        }

        if (num_user_matches == 1)
        {
            cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));

            pos = m_user_dict.find (cmd);
            if (pos != m_user_dict.end())
                user_match_sp = pos->second;
        }
        
        // If we got exactly one match, return that, otherwise return the match list.
        
        if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
        {
            if (num_cmd_matches)
                return real_match_sp;
            else if (num_alias_matches)
                return alias_match_sp;
            else
                return user_match_sp;
        }
    }
    else if (matches && command_sp)
    {
        matches->AppendString (cmd_cstr);
    }


    return command_sp;
}

bool
CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
{
    if (name && name[0])
    {
        std::string name_sstr(name);
        bool found = (m_command_dict.find (name_sstr) != m_command_dict.end());
        if (found && !can_replace)
            return false;
        if (found && m_command_dict[name_sstr]->IsRemovable() == false)
            return false;
        m_command_dict[name_sstr] = cmd_sp;
        return true;
    }
    return false;
}

bool
CommandInterpreter::AddUserCommand (std::string name, 
                                    const lldb::CommandObjectSP &cmd_sp,
                                    bool can_replace)
{
    if (!name.empty())
    {
        
        const char* name_cstr = name.c_str();
        
        // do not allow replacement of internal commands
        if (CommandExists(name_cstr))
        {
            if (can_replace == false)
                return false;
            if (m_command_dict[name]->IsRemovable() == false)
                return false;
        }
        
        if (UserCommandExists(name_cstr))
        {
            if (can_replace == false)
                return false;
            if (m_user_dict[name]->IsRemovable() == false)
                return false;
        }
        
        m_user_dict[name] = cmd_sp;
        return true;
    }
    return false;
}

CommandObjectSP
CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
{
    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 == nullptr)
        return ret_val;
    
    if (cmd_words.GetArgumentCount() == 1)
        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, 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....
            size_t end = cmd_words.GetArgumentCount();
            for (size_t j= 1; j < end; ++j)
            {
                if (cmd_obj_sp->IsMultiwordObject())
                {
                    cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
                    if (cmd_obj_sp.get() == nullptr)
                        // The sub-command name was invalid.  Fail and return the empty 'ret_val'.
                        return ret_val;
                }
                else
                    // We have more words in the command name, but we don't have a multiword object. Fail and return 
                    // empty 'ret_val'.
                    return ret_val;
            }
            // We successfully looped through all the command words and got valid command objects for them.  Assign the 
            // last object retrieved to 'ret_val'.
            ret_val = cmd_obj_sp;
        }
    }
    return ret_val;
}

CommandObject *
CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
{
    return GetCommandSPExact (cmd_cstr, include_aliases).get();
}

CommandObject *
CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
{
    CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();

    // If we didn't find an exact match to the command string in the commands, look in
    // the aliases.
    
    if (command_obj)
        return command_obj;

    command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();

    if (command_obj)
        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, nullptr).get();

    // Finally, if there wasn't an inexact match among the commands, look for an inexact
    // match in both the commands and aliases.
    
    if (command_obj)
    {
        if (matches)
            matches->AppendString(command_obj->GetCommandName());
        return command_obj;
    }
    
    return GetCommandSP(cmd_cstr, true, false, matches).get();
}

bool
CommandInterpreter::CommandExists (const char *cmd)
{
    return m_command_dict.find(cmd) != m_command_dict.end();
}

bool
CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, 
                                            const char *options_args, 
                                            OptionArgVectorSP &option_arg_vector_sp)
{
    bool success = true;
    OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
    
    if (!options_args || (strlen (options_args) < 1))
        return true;

    std::string options_string (options_args);
    Args args (options_args);
    CommandReturnObject result;
    // Check to see if the command being aliased can take any command options.
    Options *options = cmd_obj_sp->GetOptions ();
    if (options)
    {
        // See if any options were specified as part of the alias;  if so, handle them appropriately.
        options->NotifyOptionParsingStarting ();
        args.Unshift ("dummy_arg");
        args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
        args.Shift ();
        if (result.Succeeded())
            options->VerifyPartialOptions (result);
        if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
        {
            result.AppendError ("Unable to create requested alias.\n");
            return false;
        }
    }
    
    if (!options_string.empty())
    {
        if (cmd_obj_sp->WantsRawCommandString ())
            option_arg_vector->push_back (OptionArgPair ("<argument>",
                                                          OptionArgValue (-1,
                                                                          options_string)));
        else
        {
            const size_t argc = args.GetArgumentCount();
            for (size_t i = 0; i < argc; ++i)
                if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
                    option_arg_vector->push_back 
                                (OptionArgPair ("<argument>",
                                                OptionArgValue (-1,
                                                                std::string (args.GetArgumentAtIndex (i)))));
        }
    }
        
    return success;
}

bool
CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
{
    bool exact_match  = (m_alias_dict.find(cmd) != m_alias_dict.end());
    if (exact_match)
    {
        full_name.assign(cmd);
        return exact_match;
    }
    else
    {
        StringList matches;
        size_t num_alias_matches;
        num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
        if (num_alias_matches == 1)
        {
            // Make sure this isn't shadowing a command in the regular command space:
            StringList regular_matches;
            const bool include_aliases = false;
            const bool exact = false;
            CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, &regular_matches));
            if (cmd_obj_sp || regular_matches.GetSize() > 0)
                return false;
            else
            {
                full_name.assign (matches.GetStringAtIndex(0));
                return true;
            }
        }
        else
            return false;
    }
}

bool
CommandInterpreter::AliasExists (const char *cmd)
{
    return m_alias_dict.find(cmd) != m_alias_dict.end();
}

bool
CommandInterpreter::UserCommandExists (const char *cmd)
{
    return m_user_dict.find(cmd) != m_user_dict.end();
}

void
CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
{
    command_obj_sp->SetIsAlias (true);
    m_alias_dict[alias_name] = command_obj_sp;
}

bool
CommandInterpreter::RemoveAlias (const char *alias_name)
{
    CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
    if (pos != m_alias_dict.end())
    {
        m_alias_dict.erase(pos);
        return true;
    }
    return false;
}

bool
CommandInterpreter::RemoveCommand (const char *cmd)
{
    auto pos = m_command_dict.find(cmd);
    if (pos != m_command_dict.end())
    {
        if (pos->second->IsRemovable())
        {
            // Only regular expression objects or python commands are removable
            m_command_dict.erase(pos);
            return true;
        }
    }
    return false;
}
bool
CommandInterpreter::RemoveUser (const char *alias_name)
{
    CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
    if (pos != m_user_dict.end())
    {
        m_user_dict.erase(pos);
        return true;
    }
    return false;
}

void
CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
{
    help_string.Printf ("'%s", command_name);
    OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);

    if (option_arg_vector_sp)
    {
        OptionArgVector *options = option_arg_vector_sp.get();
        for (size_t i = 0; i < options->size(); ++i)
        {
            OptionArgPair cur_option = (*options)[i];
            std::string opt = cur_option.first;
            OptionArgValue value_pair = cur_option.second;
            std::string value = value_pair.second;
            if (opt.compare("<argument>") == 0)
            {
                help_string.Printf (" %s", value.c_str());
            }
            else
            {
                help_string.Printf (" %s", opt.c_str());
                if ((value.compare ("<no-argument>") != 0)
                    && (value.compare ("<need-argument") != 0))
                {
                    help_string.Printf (" %s", value.c_str());
                }
            }
        }
    }

    help_string.Printf ("'");
}

size_t
CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
{
    CommandObject::CommandMap::const_iterator pos;
    CommandObject::CommandMap::const_iterator end = dict.end();
    size_t max_len = 0;

    for (pos = dict.begin(); pos != end; ++pos)
    {
        size_t len = pos->first.size();
        if (max_len < len)
            max_len = len;
    }
    return max_len;
}

void
CommandInterpreter::GetHelp (CommandReturnObject &result,
                             uint32_t cmd_types)
{
    const char * help_prologue = GetDebugger().GetIOHandlerHelpPrologue();
    if (help_prologue != NULL)
    {
        OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue);
    }

    CommandObject::CommandMap::const_iterator pos;
    size_t max_len = FindLongestCommandWord (m_command_dict);
    
    if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
    {
        result.AppendMessage("Debugger commands:");
        result.AppendMessage("");

        for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
        {
            if (!(cmd_types & eCommandTypesHidden) && (pos->first.compare(0, 1, "_") == 0))
                continue;

            OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
                                     max_len);
        }
        result.AppendMessage("");

    }

    if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
    {
        result.AppendMessageWithFormat("Current command abbreviations "
                                       "(type '%shelp command alias' for more info):\n",
                                       GetCommandPrefix());
        result.AppendMessage("");
        max_len = FindLongestCommandWord (m_alias_dict);

        for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
        {
            StreamString sstr;
            StreamString translation_and_help;
            std::string entry_name = pos->first;
            std::string second_entry = pos->second.get()->GetCommandName();
            GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
            
            translation_and_help.Printf ("(%s)  %s", sstr.GetData(), pos->second->GetHelp());
            OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", 
                                     translation_and_help.GetData(), max_len);
        }
        result.AppendMessage("");
    }

    if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
    {
        result.AppendMessage ("Current user-defined commands:");
        result.AppendMessage("");
        max_len = FindLongestCommandWord (m_user_dict);
        for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
        {
            OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
                                     max_len);
        }
        result.AppendMessage("");
    }

    result.AppendMessageWithFormat("For more information on any command, type '%shelp <command-name>'.\n",
                                   GetCommandPrefix());
}

CommandObject *
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 = nullptr;
    std::string white_space (" \t\v");
    size_t start = command_string.find_first_not_of (white_space);
    size_t end = 0;
    bool done = false;
    while (!done)
    {
        if (start != std::string::npos)
        {
            // Get the next word from command_string.
            end = command_string.find_first_of (white_space, start);
            if (end == std::string::npos)
                end = command_string.size();
            std::string cmd_word = command_string.substr (start, end - start);
            
            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());
            else if (cmd_obj->IsMultiwordObject ())
            {
                // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
                CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
                if (sub_cmd_obj)
                    cmd_obj = sub_cmd_obj;
                else // cmd_word was not a valid sub-command word, so we are donee
                    done = true;
            }
            else  
                // We have a cmd_obj and it is not a multi-word object, so we are done.
                done = true;

            // If we didn't find a valid command object, or our command object is not a multi-word object, or
            // we are at the end of the command_string, then we are done.  Otherwise, find the start of the
            // next word.
            
            if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
                done = true;
            else
                start = command_string.find_first_not_of (white_space, end);
        }
        else
            // Unable to find any more words.
            done = true;
    }
    
    if (end == command_string.size())
        command_string.clear();
    else
        command_string = command_string.substr(end);
    
    return cmd_obj;
}

static const char *k_white_space = " \t\v";
static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
static void
StripLeadingSpaces (std::string &s)
{
    if (!s.empty())
    {
        size_t pos = s.find_first_not_of (k_white_space);
        if (pos == std::string::npos)
            s.clear();
        else if (pos == 0)
            return;
        s.erase (0, pos);
    }
}

static size_t
FindArgumentTerminator (const std::string &s)
{
    const size_t s_len = s.size();
    size_t offset = 0;
    while (offset < s_len)
    {
        size_t pos = s.find ("--", offset);
        if (pos == std::string::npos)
            break;
        if (pos > 0)
        {
            if (isspace(s[pos-1]))
            {
                // Check if the string ends "\s--" (where \s is a space character)
                // or if we have "\s--\s".
                if ((pos + 2 >= s_len) || isspace(s[pos+2]))
                {
                    return pos;
                }
            }
        }
        offset = pos + 2;
    }
    return std::string::npos;
}

static bool
ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
{
    command.clear();
    suffix.clear();
    StripLeadingSpaces (command_string);

    bool result = false;
    quote_char = '\0';
    
    if (!command_string.empty())
    {
        const char first_char = command_string[0];
        if (first_char == '\'' || first_char == '"')
        {
            quote_char = first_char;
            const size_t end_quote_pos = command_string.find (quote_char, 1);
            if (end_quote_pos == std::string::npos)
            {
                command.swap (command_string);
                command_string.erase ();
            }
            else
            {
                command.assign (command_string, 1, end_quote_pos - 1);
                if (end_quote_pos + 1 < command_string.size())
                    command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
                else
                    command_string.erase ();
            }
        }
        else
        {
            const size_t first_space_pos = command_string.find_first_of (k_white_space);
            if (first_space_pos == std::string::npos)
            {
                command.swap (command_string);
                command_string.erase();
            }
            else
            {
                command.assign (command_string, 0, first_space_pos);
                command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
            }
        }
        result = true;
    }
    
    
    if (!command.empty())
    {
        // actual commands can't start with '-' or '_'
        if (command[0] != '-' && command[0] != '_')
        {
            size_t pos = command.find_first_not_of(k_valid_command_chars);
            if (pos > 0 && pos != std::string::npos)
            {
                suffix.assign (command.begin() + pos, command.end());
                command.erase (pos);
            }
        }
    }

    return result;
}

CommandObject *
CommandInterpreter::BuildAliasResult (const char *alias_name, 
                                      std::string &raw_input_string, 
                                      std::string &alias_result,
                                      CommandReturnObject &result)
{
    CommandObject *alias_cmd_obj = nullptr;
    Args cmd_args (raw_input_string);
    alias_cmd_obj = GetCommandObject (alias_name);
    StreamString result_str;
    
    if (alias_cmd_obj)
    {
        std::string alias_name_str = alias_name;
        if ((cmd_args.GetArgumentCount() == 0)
            || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
            cmd_args.Unshift (alias_name);
            
        result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
        OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);

        if (option_arg_vector_sp.get())
        {
            OptionArgVector *option_arg_vector = option_arg_vector_sp.get();

            for (size_t i = 0; i < option_arg_vector->size(); ++i)
            {
                OptionArgPair option_pair = (*option_arg_vector)[i];
                OptionArgValue value_pair = option_pair.second;
                int value_type = value_pair.first;
                std::string option = option_pair.first;
                std::string value = value_pair.second;
                if (option.compare ("<argument>") == 0)
                    result_str.Printf (" %s", value.c_str());
                else
                {
                    result_str.Printf (" %s", option.c_str());
                    if (value_type != OptionParser::eOptionalArgument)
                        result_str.Printf (" ");
                    if (value.compare ("<OptionParser::eNoArgument>") != 0)
                    {
                        int index = GetOptionArgumentPosition (value.c_str());
                        if (index == 0)
                            result_str.Printf ("%s", value.c_str());
                        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",
                             index);
                            result.SetStatus (eReturnStatusFailed);
                            return alias_cmd_obj;
                        }
                        else
                        {
                            size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
                            if (strpos != std::string::npos)
                                raw_input_string = raw_input_string.erase (strpos, 
                                                                          strlen (cmd_args.GetArgumentAtIndex (index)));
                            result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
                        }
                    }
                }
            }
        }
        
        alias_result = result_str.GetData();
    }
    return alias_cmd_obj;
}

Error
CommandInterpreter::PreprocessCommand (std::string &command)
{
    // The command preprocessor needs to do things to the command 
    // line before any parsing of arguments or anything else is done.
    // The only current stuff that gets proprocessed is anyting enclosed
    // in backtick ('`') characters is evaluated as an expression and
    // the result of the expression must be a scalar that can be substituted
    // into the command. An example would be:
    // (lldb) memory read `$rsp + 20`
    Error error; // Error for any expressions that might not evaluate
    size_t start_backtick;
    size_t pos = 0;
    while ((start_backtick = command.find ('`', pos)) != std::string::npos)
    {
        if (start_backtick > 0 && command[start_backtick-1] == '\\')
        {
            // The backtick was preceeded by a '\' character, remove the slash
            // and don't treat the backtick as the start of an expression
            command.erase(start_backtick-1, 1);
            // No need to add one to start_backtick since we just deleted a char
            pos = start_backtick; 
        }
        else
        {
            const size_t expr_content_start = start_backtick + 1;
            const size_t end_backtick = command.find ('`', expr_content_start);
            if (end_backtick == std::string::npos)
                return error;
            else if (end_backtick == expr_content_start)
            {
                // Empty expression (two backticks in a row)
                command.erase (start_backtick, 2);
            }
            else
            {
                std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
                
                ExecutionContext exe_ctx(GetExecutionContext());
                Target *target = exe_ctx.GetTargetPtr();
                // Get a dummy target to allow for calculator mode while processing backticks.
                // This also helps break the infinite loop caused when target is null.
                if (!target)
                    target = m_debugger.GetDummyTarget();
                if (target)
                {
                    ValueObjectSP expr_result_valobj_sp;
                    
                    EvaluateExpressionOptions options;
                    options.SetCoerceToId(false);
                    options.SetUnwindOnError(true);
                    options.SetIgnoreBreakpoints(true);
                    options.SetKeepInMemory(false);
                    options.SetTryAllThreads(true);
                    options.SetTimeoutUsec(0);
                    
                    ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 
                                                                                exe_ctx.GetFramePtr(),
                                                                                expr_result_valobj_sp,
                                                                                options);
                    
                    if (expr_result == eExpressionCompleted)
                    {
                        Scalar scalar;
                        if (expr_result_valobj_sp)
                            expr_result_valobj_sp = expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(expr_result_valobj_sp->GetDynamicValueType(), true);
                        if (expr_result_valobj_sp->ResolveValue (scalar))
                        {
                            command.erase (start_backtick, end_backtick - start_backtick + 1);
                            StreamString value_strm;
                            const bool show_type = false;
                            scalar.GetValue (&value_strm, show_type);
                            size_t value_string_size = value_strm.GetSize();
                            if (value_string_size)
                            {
                                command.insert (start_backtick, value_strm.GetData(), value_string_size);
                                pos = start_backtick + value_string_size;
                                continue;
                            }
                            else
                            {
                                error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
                            }
                        }
                        else
                        {
                            error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
                        }
                    }
                    else
                    {
                        if (expr_result_valobj_sp)
                            error = expr_result_valobj_sp->GetError();
                        if (error.Success())
                        {

                            switch (expr_result)
                            {
                                case eExpressionSetupError: 
                                    error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
                                    break;
                                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 eExpressionDiscarded:
                                    error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
                                    break;
                                case eExpressionInterrupted:
                                    error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
                                    break;
                                case eExpressionHitBreakpoint:
                                    error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
                                    break;
                                case eExpressionTimedOut:
                                    error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
                                    break;
                                case eExpressionStoppedForDebug:
                                    error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());
                                    break;
                            }
                        }
                    }
                }
            }
            if (error.Fail())
                break;
        }
    }
    return error;
}


bool
CommandInterpreter::HandleCommand (const char *command_line, 
                                   LazyBool lazy_add_to_history,
                                   CommandReturnObject &result,
                                   ExecutionContext *override_context,
                                   bool repeat_on_empty_command,
                                   bool no_context_switching)

{

    bool done = false;
    CommandObject *cmd_obj = nullptr;
    bool wants_raw_input = false;
    std::string command_string (command_line);
    std::string original_command_string (command_line);
    
    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
    Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", 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(nullptr, Host::SetCrashDescription);

    if (log)
        log->Printf ("Processing command: %s", command_line);

    Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
    
    if (!no_context_switching)
        UpdateExecutionContext (override_context);
    
    bool add_to_history;
    if (lazy_add_to_history == eLazyBoolCalculate)
        add_to_history = (m_command_source_depth == 0);
    else
        add_to_history = (lazy_add_to_history == eLazyBoolYes);
    
    bool empty_command = false;
    bool comment_command = false;
    if (command_string.empty())
        empty_command = true;
    else
    {
        const char *k_space_characters = "\t\n\v\f\r ";

        size_t non_space = command_string.find_first_not_of (k_space_characters);
        // Check for empty line or comment line (lines whose first
        // non-space character is the comment character for this interpreter)
        if (non_space == std::string::npos)
            empty_command = true;
        else if (command_string[non_space] == m_comment_char)
             comment_command = true;
        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 == nullptr)
            {
                result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            add_to_history = false;
            command_string = history_string;
            original_command_string = history_string;
        }
    }
    
    if (empty_command)
    {
        if (repeat_on_empty_command)
        {
            if (m_command_history.IsEmpty())
            {
                result.AppendError ("empty command");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else
            {
                command_line = m_repeat_command.c_str();
                command_string = command_line;
                original_command_string = command_line;
                if (m_repeat_command.empty())
                {
                    result.AppendErrorWithFormat("No auto repeat.\n");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            add_to_history = false;
        }
        else
        {
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
            return true;
        }
    }
    else if (comment_command)
    {
        result.SetStatus (eReturnStatusSuccessFinishNoResult);
        return true;
    }
    
    
    Error error (PreprocessCommand (command_string));
    
    if (error.Fail())
    {
        result.AppendError (error.AsCString());
        result.SetStatus(eReturnStatusFailed);
        return false;
    }
    // Phase 1.
    
    // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
    // is for the specified command, and whether or not it wants raw input.  This gets complicated by the fact that
    // the user could have specified an alias, and in translating the alias there may also be command options and/or
    // even data (including raw text strings) that need to be found and inserted into the command line as part of
    // the translation.  So this first step is plain look-up & replacement, resulting in three things:  1). the command
    // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
    // replacements taken care of; 3). whether or not the Execute function wants raw input or not.

    StreamString revised_command_line;
    size_t actual_cmd_name_len = 0;
    std::string next_word;
    StringList matches;
    while (!done)
    {
        char quote_char = '\0';
        std::string suffix;
        ExtractCommand (command_string, next_word, suffix, quote_char);
        if (cmd_obj == nullptr)
        {
            std::string full_name;
            if (GetAliasFullName(next_word.c_str(), full_name))
            {
                std::string alias_result;
                cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result);
                revised_command_line.Printf ("%s", alias_result.c_str());
                if (cmd_obj)
                {
                    wants_raw_input = cmd_obj->WantsRawCommandString ();
                    actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
                }
            }
            else
            {
                cmd_obj = GetCommandObject (next_word.c_str(), &matches);
                if (cmd_obj)
                {
                    actual_cmd_name_len += next_word.length();
                    revised_command_line.Printf ("%s", next_word.c_str());
                    wants_raw_input = cmd_obj->WantsRawCommandString ();
                }
                else
                {
                    revised_command_line.Printf ("%s", next_word.c_str());
                }
            }
        }
        else
        {
            if (cmd_obj->IsMultiwordObject ())
            {
                CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str());
                if (sub_cmd_obj)
                {
                    actual_cmd_name_len += next_word.length() + 1;
                    revised_command_line.Printf (" %s", next_word.c_str());
                    cmd_obj = sub_cmd_obj;
                    wants_raw_input = cmd_obj->WantsRawCommandString ();
                }
                else
                {
                    if (quote_char)
                        revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
                    else
                        revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
                    done = true;
                }
            }
            else
            {
                if (quote_char)
                    revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
                else
                    revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
                done = true;
            }
        }

        if (cmd_obj == nullptr)
        {
            const size_t num_matches = matches.GetSize();
            if (matches.GetSize() > 1) {
                StreamString error_msg;
                error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());

                for (uint32_t i = 0; i < num_matches; ++i) {
                    error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i));
                }
                result.AppendRawError (error_msg.GetString().c_str());
            } else {
                // We didn't have only one match, otherwise we wouldn't get here.
                assert(num_matches == 0);
                result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
            }
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        if (cmd_obj->IsMultiwordObject ())
        {
            if (!suffix.empty())
            {

                result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n",
                                              cmd_obj->GetCommandName(),
                                              next_word.empty() ? "" : next_word.c_str(),
                                              next_word.empty() ? " -- " : " ",
                                              suffix.c_str());
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
        }
        else
        {
            // If we found a normal command, we are done
            done = true;
            if (!suffix.empty())
            {
                switch (suffix[0])
                {
                case '/':
                    // GDB format suffixes
                    {
                        Options *command_options = cmd_obj->GetOptions();
                        if (command_options && command_options->SupportsLongOption("gdb-format"))
                        {
                            std::string gdb_format_option ("--gdb-format=");
                            gdb_format_option += (suffix.c_str() + 1);
    
                            bool inserted = false;
                            std::string &cmd = revised_command_line.GetString();
                            size_t arg_terminator_idx = FindArgumentTerminator (cmd);
                            if (arg_terminator_idx != std::string::npos)
                            {
                                // Insert the gdb format option before the "--" that terminates options
                                gdb_format_option.append(1,' ');
                                cmd.insert(arg_terminator_idx, gdb_format_option);
                                inserted = true;
                            }

                            if (!inserted)
                                revised_command_line.Printf (" %s", gdb_format_option.c_str());
                        
                            if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
                                revised_command_line.PutCString (" --");
                        }
                        else
                        {
                            result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n", 
                                                          cmd_obj->GetCommandName());
                            result.SetStatus (eReturnStatusFailed);
                            return false;
                        }
                    }
                    break;

                default:
                    result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n", 
                                                  suffix.c_str());
                    result.SetStatus (eReturnStatusFailed);
                    return false;
        
                }
            }
        }
        if (command_string.length() == 0)
            done = true;
            
    }

    if (!command_string.empty())
        revised_command_line.Printf (" %s", command_string.c_str());

    // End of Phase 1.
    // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
    // specified was valid; revised_command_line contains the complete command line (including command name(s)),
    // fully translated with all substitutions & translations taken care of (still in raw text format); and
    // wants_raw_input specifies whether the Execute method expects raw input or not.

 
    if (log)
    {
        log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
        log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
        log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
    }

    // Phase 2.
    // 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 != 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 != nullptr)
                m_repeat_command.assign(repeat_command);
            else
                m_repeat_command.assign(original_command_string.c_str());
            
            m_command_history.AppendString (original_command_string);
        }
        
        command_string = revised_command_line.GetData();
        std::string command_name (cmd_obj->GetCommandName());
        std::string remainder;
        if (actual_cmd_name_len < command_string.length()) 
            remainder = command_string.substr (actual_cmd_name_len);  // Note: 'actual_cmd_name_len' may be considerably shorter
                                                           // than cmd_obj->GetCommandName(), because name completion
                                                           // allows users to enter short versions of the names,
                                                           // e.g. 'br s' for 'breakpoint set'.
        
        // Remove any initial spaces
        std::string white_space (" \t\v");
        size_t pos = remainder.find_first_not_of (white_space);
        if (pos != 0 && pos != std::string::npos)
            remainder.erase(0, pos);

        if (log)
            log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
    
        cmd_obj->Execute (remainder.c_str(), result);
    }
    else
    {
        // We didn't find the first command object, so complete the first argument.
        Args command_args (revised_command_line.GetData());
        StringList matches;
        int num_matches;
        int cursor_index = 0;
        int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
        bool word_complete;
        num_matches = HandleCompletionMatches (command_args, 
                                               cursor_index,
                                               cursor_char_position,
                                               0, 
                                               -1, 
                                               word_complete,
                                               matches);
        
        if (num_matches > 0)
        {
            std::string error_msg;
            error_msg.assign ("ambiguous command '");
            error_msg.append(command_args.GetArgumentAtIndex(0));
            error_msg.append ("'.");
            
            error_msg.append (" Possible completions:");
            for (int i = 0; i < num_matches; i++)
            {
                error_msg.append ("\n\t");
                error_msg.append (matches.GetStringAtIndex (i));
            }
            error_msg.append ("\n");
            result.AppendRawError (error_msg.c_str());
        }
        else
            result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
        
        result.SetStatus (eReturnStatusFailed);
    }
    
    if (log)
      log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));

    return result.Succeeded();
}

int
CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
                                             int &cursor_index,
                                             int &cursor_char_position,
                                             int match_start_point,
                                             int max_return_elements,
                                             bool &word_complete,
                                             StringList &matches)
{
    int num_command_matches = 0;
    bool look_for_subcommand = false;
    
    // For any of the command completions a unique match will be a complete word.
    word_complete = true;

    if (cursor_index == -1)
    {
        // We got nothing on the command line, so return the list of commands
        bool include_aliases = true;
        num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
    }
    else if (cursor_index == 0)
    {
        // The cursor is in the first argument, so just do a lookup in the dictionary.
        CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
        num_command_matches = matches.GetSize();

        if (num_command_matches == 1
            && cmd_obj && cmd_obj->IsMultiwordObject()
            && matches.GetStringAtIndex(0) != nullptr
            && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
        {
            if (parsed_line.GetArgumentCount() == 1)
            {
                word_complete = true;
            }
            else
            {
                look_for_subcommand = true;
                num_command_matches = 0;
                matches.DeleteStringAtIndex(0);
                parsed_line.AppendArgument ("");
                cursor_index++;
                cursor_char_position = 0;
            }
        }
    }

    if (cursor_index > 0 || look_for_subcommand)
    {
        // We are completing further on into a commands arguments, so find the command and tell it
        // to complete the command.
        // First see if there is a matching initial command:
        CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
        if (command_object == nullptr)
        {
            return 0;
        }
        else
        {
            parsed_line.Shift();
            cursor_index--;
            num_command_matches = command_object->HandleCompletion (parsed_line, 
                                                                    cursor_index, 
                                                                    cursor_char_position,
                                                                    match_start_point, 
                                                                    max_return_elements,
                                                                    word_complete, 
                                                                    matches);
        }
    }

    return num_command_matches;

}

int
CommandInterpreter::HandleCompletion (const char *current_line,
                                      const char *cursor,
                                      const char *last_char,
                                      int match_start_point,
                                      int max_return_elements,
                                      StringList &matches)
{
    // We parse the argument up to the cursor, so the last argument in parsed_line is
    // the one containing the cursor, and the cursor is after the last character.

    Args parsed_line(llvm::StringRef(current_line, last_char - current_line));
    Args partial_parsed_line(llvm::StringRef(current_line, cursor - current_line));

    // Don't complete comments, and if the line we are completing is just the history repeat character, 
    // substitute the appropriate history line.
    const char *first_arg = parsed_line.GetArgumentAtIndex(0);
    if (first_arg)
    {
        if (first_arg[0] == m_comment_char)
            return 0;
        else if (first_arg[0] == CommandHistory::g_repeat_char)
        {
            const char *history_string = m_command_history.FindString (first_arg);
            if (history_string != nullptr)
            {
                matches.Clear();
                matches.InsertStringAtIndex(0, history_string);
                return -2;
            }
            else
                return 0;

        }
    }
    
    
    int num_args = partial_parsed_line.GetArgumentCount();
    int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
    int cursor_char_position;

    if (cursor_index == -1)
        cursor_char_position = 0;
    else
        cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
        
    if (cursor > current_line && cursor[-1] == ' ')
    {
        // We are just after a space.  If we are in an argument, then we will continue
        // parsing, but if we are between arguments, then we have to complete whatever the next
        // element would be.
        // We can distinguish the two cases because if we are in an argument (e.g. because the space is
        // protected by a quote) then the space will also be in the parsed argument...
        
        const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
        if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
        {
            parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0');
            cursor_index++;
            cursor_char_position = 0;
        }
    }

    int num_command_matches;

    matches.Clear();

    // Only max_return_elements == -1 is supported at present:
    assert (max_return_elements == -1);
    bool word_complete;
    num_command_matches = HandleCompletionMatches (parsed_line, 
                                                   cursor_index, 
                                                   cursor_char_position, 
                                                   match_start_point,
                                                   max_return_elements,
                                                   word_complete,
                                                   matches);

    if (num_command_matches <= 0)
            return num_command_matches;

    if (num_args == 0)
    {
        // If we got an empty string, insert nothing.
        matches.InsertStringAtIndex(0, "");
    }
    else
    {
        // Now figure out if there is a common substring, and if so put that in element 0, otherwise
        // put an empty string in element 0.
        std::string command_partial_str;
        if (cursor_index >= 0)
            command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), 
                                       parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);

        std::string common_prefix;
        matches.LongestCommonPrefix (common_prefix);
        const size_t partial_name_len = command_partial_str.size();

        // If we matched a unique single command, add a space...
        // Only do this if the completer told us this was a complete word, however...
        if (num_command_matches == 1 && word_complete)
        {
            char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
            if (quote_char != '\0')
                common_prefix.push_back(quote_char);

            common_prefix.push_back(' ');
        }
        common_prefix.erase (0, partial_name_len);
        matches.InsertStringAtIndex(0, common_prefix.c_str());
    }
    return num_command_matches;
}


CommandInterpreter::~CommandInterpreter ()
{
}

void
CommandInterpreter::UpdatePrompt (const char *new_prompt)
{
    EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));;
    BroadcastEvent (prompt_change_event_sp);
    if (m_command_io_handler_sp)
        m_command_io_handler_sp->SetPrompt(new_prompt);
}


bool 
CommandInterpreter::Confirm (const char *message, bool default_answer)
{
    // Check AutoConfirm first:
    if (m_debugger.GetAutoConfirm())
        return default_answer;
    
    IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger,
                                                     message,
                                                     default_answer);
    IOHandlerSP io_handler_sp (confirm);
    m_debugger.RunIOHandler (io_handler_sp);
    return confirm->GetResponse();
}
    
OptionArgVectorSP
CommandInterpreter::GetAliasOptions (const char *alias_name)
{
    OptionArgMap::iterator pos;
    OptionArgVectorSP ret_val;

    std::string alias (alias_name);

    if (HasAliasOptions())
    {
        pos = m_alias_options.find (alias);
        if (pos != m_alias_options.end())
          ret_val = pos->second;
    }

    return ret_val;
}

void
CommandInterpreter::RemoveAliasOptions (const char *alias_name)
{
    OptionArgMap::iterator pos = m_alias_options.find(alias_name);
    if (pos != m_alias_options.end())
    {
        m_alias_options.erase (pos);
    }
}

void
CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
{
    m_alias_options[alias_name] = option_arg_vector_sp;
}

bool
CommandInterpreter::HasCommands ()
{
    return (!m_command_dict.empty());
}

bool
CommandInterpreter::HasAliases ()
{
    return (!m_alias_dict.empty());
}

bool
CommandInterpreter::HasUserCommands ()
{
    return (!m_user_dict.empty());
}

bool
CommandInterpreter::HasAliasOptions ()
{
    return (!m_alias_options.empty());
}

void
CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
                                           const char *alias_name,
                                           Args &cmd_args,
                                           std::string &raw_input_string,
                                           CommandReturnObject &result)
{
    OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
    
    bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();

    // Make sure that the alias name is the 0th element in cmd_args
    std::string alias_name_str = alias_name;
    if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
        cmd_args.Unshift (alias_name);
    
    Args new_args (alias_cmd_obj->GetCommandName());
    if (new_args.GetArgumentCount() == 2)
        new_args.Shift();
    
    if (option_arg_vector_sp.get())
    {
        if (wants_raw_input)
        {
            // We have a command that both has command options and takes raw input.  Make *sure* it has a
            // " -- " in the right place in the raw_input_string.
            size_t pos = raw_input_string.find(" -- ");
            if (pos == std::string::npos)
            {
                // None found; assume it goes at the beginning of the raw input string
                raw_input_string.insert (0, " -- ");
            }
        }

        OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
        const size_t old_size = cmd_args.GetArgumentCount();
        std::vector<bool> used (old_size + 1, false);
        
        used[0] = true;

        for (size_t i = 0; i < option_arg_vector->size(); ++i)
        {
            OptionArgPair option_pair = (*option_arg_vector)[i];
            OptionArgValue value_pair = option_pair.second;
            int value_type = value_pair.first;
            std::string option = option_pair.first;
            std::string value = value_pair.second;
            if (option.compare ("<argument>") == 0)
            {
                if (!wants_raw_input
                    || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
                    new_args.AppendArgument (value.c_str());
            }
            else
            {
                if (value_type != OptionParser::eOptionalArgument)
                    new_args.AppendArgument (option.c_str());
                if (value.compare ("<no-argument>") != 0)
                {
                    int index = GetOptionArgumentPosition (value.c_str());
                    if (index == 0)
                    {
                        // value was NOT a positional argument; must be a real value
                        if (value_type != OptionParser::eOptionalArgument)
                            new_args.AppendArgument (value.c_str());
                        else
                        {
                            char buffer[255];
                            ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
                            new_args.AppendArgument (buffer);
                        }

                    }
                    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",
                                     index);
                        result.SetStatus (eReturnStatusFailed);
                        return;
                    }
                    else
                    {
                        // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
                        size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
                        if (strpos != std::string::npos)
                        {
                            raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
                        }

                        if (value_type != OptionParser::eOptionalArgument)
                            new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
                        else
                        {
                            char buffer[255];
                            ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(), 
                                        cmd_args.GetArgumentAtIndex (index));
                            new_args.AppendArgument (buffer);
                        }
                        used[index] = true;
                    }
                }
            }
        }

        for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j)
        {
            if (!used[j] && !wants_raw_input)
                new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
        }

        cmd_args.Clear();
        cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
    }
    else
    {
        result.SetStatus (eReturnStatusSuccessFinishNoResult);
        // This alias was not created with any options; nothing further needs to be done, unless it is a command that
        // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
        // input string.
        if (wants_raw_input)
        {
            cmd_args.Clear();
            cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
        }
        return;
    }

    result.SetStatus (eReturnStatusSuccessFinishNoResult);
    return;
}


int
CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
{
    int position = 0;   // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
                        // of zero.

    char *cptr = (char *) in_string;

    // Does it start with '%'
    if (cptr[0] == '%')
    {
        ++cptr;

        // Is the rest of it entirely digits?
        if (isdigit (cptr[0]))
        {
            const char *start = cptr;
            while (isdigit (cptr[0]))
                ++cptr;

            // We've gotten to the end of the digits; are we at the end of the string?
            if (cptr[0] == '\0')
                position = atoi (start);
        }
    }

    return position;
}

void
CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
{
    FileSpec init_file;
    if (in_cwd)
    {
        // In the current working directory we don't load any program specific
        // .lldbinit files, we only look for a "./.lldbinit" file.
        if (m_skip_lldbinit_files)
            return;

        init_file.SetFile ("./.lldbinit", true);
    }
    else
    {
        // If we aren't looking in the current working directory we are looking
        // in the home directory. We will first see if there is an application
        // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a 
        // "-" 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.
        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(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.c_str(), program_name);
                init_file.SetFile (program_init_file_name, true);
                if (!init_file.Exists())
                    init_file.Clear();
            }
        }
        
        if (!init_file && !m_skip_lldbinit_files)
			init_file.SetFile (init_file_path.c_str(), false);
    }

    // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
    // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).

    if (init_file.Exists())
    {
        const bool saved_batch = SetBatchCommandMode (true);
        CommandInterpreterRunOptions options;
        options.SetSilent (true);
        options.SetStopOnError (false);
        options.SetStopOnContinue (true);

        HandleCommandsFromFile (init_file,
                                nullptr,           // Execution context
                                options,
                                result);
        SetBatchCommandMode (saved_batch);
    }
    else
    {
        // nothing to be done if the file doesn't exist
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
    }
}

const char *
CommandInterpreter::GetCommandPrefix()
{
    const char * prefix = GetDebugger().GetIOHandlerCommandPrefix();
    return prefix == NULL ? "" : prefix;
}

PlatformSP
CommandInterpreter::GetPlatform (bool prefer_target_platform)
{
    PlatformSP platform_sp;
    if (prefer_target_platform)
    {
        ExecutionContext exe_ctx(GetExecutionContext());
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
            platform_sp = target->GetPlatform();
    }

    if (!platform_sp)
        platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
    return platform_sp;
}

void
CommandInterpreter::HandleCommands (const StringList &commands, 
                                    ExecutionContext *override_context,
                                    CommandInterpreterRunOptions &options,
                                    CommandReturnObject &result)
{
    size_t num_lines = commands.GetSize();
    
    // If we are going to continue past a "continue" then we need to run the commands synchronously.
    // Make sure you reset this value anywhere you return from the function.
    
    bool old_async_execution = m_debugger.GetAsyncExecution();
    
    // 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 != nullptr)
        UpdateExecutionContext (override_context);
            
    if (!options.GetStopOnContinue())
    {
        m_debugger.SetAsyncExecution (false);
    }

    for (size_t idx = 0; idx < num_lines; idx++)
    {
        const char *cmd = commands.GetStringAtIndex(idx);
        if (cmd[0] == '\0')
            continue;
            
        if (options.GetEchoCommands())
        {
            result.AppendMessageWithFormat ("%s %s\n", 
                                            m_debugger.GetPrompt(),
                                            cmd);
        }

        CommandReturnObject tmp_result;
        // If override_context is not NULL, pass no_context_switching = true for
        // HandleCommand() since we updated our context already.
        
        // We might call into a regex or alias command, in which case the add_to_history will get lost.  This
        // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
        if (!options.GetAddToHistory())
            m_command_source_depth++;
        bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result,
                                     nullptr, /* override_context */
                                     true, /* repeat_on_empty_command */
                                     override_context != nullptr /* no_context_switching */);
        if (!options.GetAddToHistory())
            m_command_source_depth--;
        
        if (options.GetPrintResults())
        {
            if (tmp_result.Succeeded())
              result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
        }
                
        if (!success || !tmp_result.Succeeded())
        {
            const char *error_msg = tmp_result.GetErrorData();
            if (error_msg == nullptr || error_msg[0] == '\0')
                error_msg = "<unknown error>.\n";
            if (options.GetStopOnError())
            {
                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 (options.GetPrintResults())
            {
                result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s",
                                                (uint64_t)idx + 1,
                                                cmd, 
                                                error_msg);
            }
        }
        
        if (result.GetImmediateOutputStream())
            result.GetImmediateOutputStream()->Flush();
        
        if (result.GetImmediateErrorStream())
            result.GetImmediateErrorStream()->Flush();
        
        // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
        // could be running (for instance in Breakpoint Commands.
        // So we check the return value to see if it is has running in it.
        if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
                || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
        {
            if (options.GetStopOnContinue())
            {
                // If we caused the target to proceed, and we're going to stop in that case, set the
                // 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 #%" PRIu64 ": '%s' continued the target.\n", 
                                                 (uint64_t)idx + 1, cmd);
                else
                    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);

                return;
            }
        }

        // Also check for "stop on crash here:
        bool should_stop = false;
        if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash())
        {
            TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
            if (target_sp)
            {
                ProcessSP process_sp (target_sp->GetProcessSP());
                if (process_sp)
                {
                    for (ThreadSP thread_sp : process_sp->GetThreadList().Threads())
                    {
                        StopReason reason = thread_sp->GetStopReason();
                        if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation)
                        {
                            should_stop = true;
                            break;
                        }
                    }
                }
            }
            if (should_stop)
            {
                if (idx != num_lines - 1)
                    result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n",
                                                 (uint64_t)idx + 1, cmd);
                else
                    result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd);
                    
                result.SetStatus(tmp_result.GetStatus());
                m_debugger.SetAsyncExecution (old_async_execution);

                return;
            }
        }
        
    }
    
    result.SetStatus (eReturnStatusSuccessFinishResult);
    m_debugger.SetAsyncExecution (old_async_execution);

    return;
}

// Make flags that we can pass into the IOHandler so our delegates can do the right thing
enum {
    eHandleCommandFlagStopOnContinue = (1u << 0),
    eHandleCommandFlagStopOnError    = (1u << 1),
    eHandleCommandFlagEchoCommand    = (1u << 2),
    eHandleCommandFlagPrintResult    = (1u << 3),
    eHandleCommandFlagStopOnCrash    = (1u << 4)
};

void
CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, 
                                            ExecutionContext *context, 
                                            CommandInterpreterRunOptions &options,
                                            CommandReturnObject &result)
{
    if (cmd_file.Exists())
    {
        StreamFileSP input_file_sp (new StreamFile());
        
        std::string cmd_file_path = cmd_file.GetPath();
        Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead);
        
        if (error.Success())
        {
            Debugger &debugger = GetDebugger();

            uint32_t flags = 0;

            if (options.m_stop_on_continue == eLazyBoolCalculate)
            {
                if (m_command_source_flags.empty())
                {
                    // Stop on continue by default
                    flags |= eHandleCommandFlagStopOnContinue;
                }
                else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue)
                {
                    flags |= eHandleCommandFlagStopOnContinue;
                }
            }
            else if (options.m_stop_on_continue == eLazyBoolYes)
            {
                flags |= eHandleCommandFlagStopOnContinue;
            }

            if (options.m_stop_on_error == eLazyBoolCalculate)
            {
                if (m_command_source_flags.empty())
                {
                    if (GetStopCmdSourceOnError())
                        flags |= eHandleCommandFlagStopOnError;
                }
                else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError)
                {
                    flags |= eHandleCommandFlagStopOnError;
                }
            }
            else if (options.m_stop_on_error == eLazyBoolYes)
            {
                flags |= eHandleCommandFlagStopOnError;
            }

            if (options.GetStopOnCrash())
            {
                if (m_command_source_flags.empty())
                {
                    // Echo command by default
                    flags |= eHandleCommandFlagStopOnCrash;
                }
                else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash)
                {
                    flags |= eHandleCommandFlagStopOnCrash;
                }
            }

            if (options.m_echo_commands == eLazyBoolCalculate)
            {
                if (m_command_source_flags.empty())
                {
                    // Echo command by default
                    flags |= eHandleCommandFlagEchoCommand;
                }
                else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand)
                {
                    flags |= eHandleCommandFlagEchoCommand;
                }
            }
            else if (options.m_echo_commands == eLazyBoolYes)
            {
                flags |= eHandleCommandFlagEchoCommand;
            }

            if (options.m_print_results == eLazyBoolCalculate)
            {
                if (m_command_source_flags.empty())
                {
                    // Print output by default
                    flags |= eHandleCommandFlagPrintResult;
                }
                else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult)
                {
                    flags |= eHandleCommandFlagPrintResult;
                }
            }
            else if (options.m_print_results == eLazyBoolYes)
            {
                flags |= eHandleCommandFlagPrintResult;
            }

            if (flags & eHandleCommandFlagPrintResult)
            {
                debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str());
            }

            // Used for inheriting the right settings when "command source" might have
            // nested "command source" commands
            lldb::StreamFileSP empty_stream_sp;
            m_command_source_flags.push_back(flags);
            IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
                                                              IOHandler::Type::CommandInterpreter,
                                                              input_file_sp,
                                                              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,
                                                              nullptr, // Pass in NULL for "editline_name" so no history is saved, or written
                                                              debugger.GetPrompt(),
                                                              NULL,
                                                              false, // Not multi-line
                                                              debugger.GetUseColor(),
                                                              0,
                                                              *this));
            const bool old_async_execution = debugger.GetAsyncExecution();
            
            // Set synchronous execution if we are not stopping on continue
            if ((flags & eHandleCommandFlagStopOnContinue) == 0)
                debugger.SetAsyncExecution (false);

            m_command_source_depth++;
            
            debugger.RunIOHandler(io_handler_sp);
            if (!m_command_source_flags.empty())
                m_command_source_flags.pop_back();
            m_command_source_depth--;
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
            debugger.SetAsyncExecution (old_async_execution);
        }
        else
        {
            result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString());
            result.SetStatus (eReturnStatusFailed);
        }
        

    }
    else
    {
        result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n", 
                                      cmd_file.GetFilename().AsCString("<Unknown>"));
        result.SetStatus (eReturnStatusFailed);
        return;
    }
}

ScriptInterpreter *
CommandInterpreter::GetScriptInterpreter (bool can_create)
{
    if (m_script_interpreter_ap.get() != nullptr)
        return m_script_interpreter_ap.get();
    
    if (!can_create)
        return nullptr;
 
    // <rdar://problem/11751427>
    // we need to protect the initialization of the script interpreter
    // otherwise we could end up with two threads both trying to create
    // their instance of it, and for some languages (e.g. Python)
    // this is a bulletproof recipe for disaster!
    // this needs to be a function-level static because multiple Debugger instances living in the same process
    // still need to be isolated and not try to initialize Python concurrently
    static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
    Mutex::Locker interpreter_lock(g_interpreter_mutex);
    
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
    if (log)
        log->Printf("Initializing the ScriptInterpreter now\n");
    
    lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
    switch (script_lang)
    {
        case eScriptLanguagePython:
#ifndef LLDB_DISABLE_PYTHON
            m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
            break;
#else
            // Fall through to the None case when python is disabled
#endif
        case eScriptLanguageNone:
            m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
            break;
    };
    
    return m_script_interpreter_ap.get();
}



bool
CommandInterpreter::GetSynchronous ()
{
    return m_synchronous_execution;
}

void
CommandInterpreter::SetSynchronous (bool value)
{
    m_synchronous_execution  = value;
}

void
CommandInterpreter::OutputFormattedHelpText (Stream &strm,
                                             const char *prefix,
                                             const char *help_text)
{
    const uint32_t max_columns = m_debugger.GetTerminalWidth();
    if (prefix == NULL)
        prefix = "";

    size_t prefix_width = strlen(prefix);
    size_t line_width_max = max_columns - prefix_width;
    const char *help_text_end = help_text + strlen(help_text);
    const char *line_start = help_text;
    if (line_width_max < 16)
        line_width_max = help_text_end - help_text + prefix_width;

    strm.IndentMore (prefix_width);
    while (line_start < help_text_end)
    {
        // Break each line at the first newline or last space/tab before
        // the maximum number of characters that fit on a line.  Lines with no
        // natural break are left unbroken to wrap.
        const char *line_end = help_text_end;
        const char *line_scan = line_start;
        const char *line_scan_end = help_text_end;
        while (line_scan < line_scan_end)
        {
            char next = *line_scan;
            if (next == '\t' || next == ' ')
            {
                line_end = line_scan;
                line_scan_end = line_start + line_width_max;
            }
            else if (next == '\n' || next == '\0')
            {
                line_end = line_scan;
                break;
            }
            ++line_scan;
        }
        
        // Prefix the first line, indent subsequent lines to line up
        if (line_start == help_text)
            strm.Write (prefix, prefix_width);
        else
            strm.Indent();
        strm.Write (line_start, line_end - line_start);
        strm.EOL();

        // When a line breaks at whitespace consume it before continuing
        line_start = line_end;
        char next = *line_start;
        if (next == '\n')
            ++line_start;
        else while (next == ' ' || next == '\t')
            next = *(++line_start);
    }
    strm.IndentLess (prefix_width);
}

void
CommandInterpreter::OutputFormattedHelpText (Stream &strm,
                                             const char *word_text,
                                             const char *separator,
                                             const char *help_text,
                                             size_t max_word_len)
{
    StreamString prefix_stream;
    prefix_stream.Printf ("  %-*s %s ",  (int)max_word_len, word_text, separator);
    OutputFormattedHelpText (strm, prefix_stream.GetData(), help_text);
}

void
CommandInterpreter::OutputHelpText (Stream &strm,
                                    const char *word_text,
                                    const char *separator,
                                    const char *help_text,
                                    uint32_t max_word_len)
{
    int indent_size = max_word_len + strlen (separator) + 2;
    
    strm.IndentMore (indent_size);
    
    StreamString text_strm;
    text_strm.Printf ("%-*s %s %s",  max_word_len, word_text, separator, help_text);
    
    const uint32_t max_columns = m_debugger.GetTerminalWidth();
    
    size_t len = text_strm.GetSize();
    const char *text = text_strm.GetData();
        
    uint32_t chars_left = max_columns;

    for (uint32_t i = 0; i < len; i++)
    {
        if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
        {
            chars_left = max_columns - indent_size;
            strm.EOL();
            strm.Indent();
        }
        else
        {
            strm.PutChar(text[i]);
            chars_left--;
        }
        
    }
    
    strm.EOL();
    strm.IndentLess(indent_size);
}

void
CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
                                            StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
{
    CommandObject::CommandMap::const_iterator pos;

    if (search_builtin_commands)
    {
        for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
        {
            const char *command_name = pos->first.c_str();
            CommandObject *cmd_obj = pos->second.get();

            if (cmd_obj->HelpTextContainsWord (search_word))
            {
                commands_found.AppendString (command_name);
                commands_help.AppendString (cmd_obj->GetHelp());
            }

            if (cmd_obj->IsMultiwordObject())
                cmd_obj->AproposAllSubCommands (command_name,
                                                search_word,
                                                commands_found,
                                                commands_help);
          
        }
    }
    
    if (search_user_commands)
    {
        for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
        {
            const char *command_name = pos->first.c_str();
            CommandObject *cmd_obj = pos->second.get();

            if (cmd_obj->HelpTextContainsWord (search_word))
            {
                commands_found.AppendString (command_name);
                commands_help.AppendString (cmd_obj->GetHelp());
            }

            if (cmd_obj->IsMultiwordObject())
                cmd_obj->AproposAllSubCommands (command_name,
                                                search_word,
                                                commands_found,
                                                commands_help);
          
        }
    }
}

void
CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
{
    if (override_context != nullptr)
    {
        m_exe_ctx_ref = *override_context;
    }
    else
    {
        const bool adopt_selected = true;
        m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
    }
}


size_t
CommandInterpreter::GetProcessOutput ()
{
    //  The process has stuff waiting for stderr; get it and write it out to the appropriate place.
    char stdio_buffer[1024];
    size_t len;
    size_t total_bytes = 0;
    Error error;
    TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
    if (target_sp)
    {
        ProcessSP process_sp (target_sp->GetProcessSP());
        if (process_sp)
        {
            while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
            {
                size_t bytes_written = len;
                m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written);
                total_bytes += len;
            }
            while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
            {
                size_t bytes_written = len;
                m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written);
                total_bytes += len;
            }
        }
    }
    return total_bytes;
}

void
CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
{
    const bool is_interactive = io_handler.GetIsInteractive();
    if (is_interactive == false)
    {
        // When we are not interactive, don't execute blank lines. This will happen
        // sourcing a commands file. We don't want blank lines to repeat the previous
        // command and cause any errors to occur (like redefining an alias, get an error
        // and stop parsing the commands file).
        if (line.empty())
            return;
        
        // When using a non-interactive file handle (like when sourcing commands from a file)
        // we need to echo the command out so we don't just see the command output and no
        // command...
        if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
            io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
    }

    lldb_private::CommandReturnObject result;
    HandleCommand(line.c_str(), eLazyBoolCalculate, result);
    
    // Now emit the command output text from the command we just executed
    if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult))
    {
        // Display any STDOUT/STDERR _prior_ to emitting the command result text
        GetProcessOutput ();
        
        if (!result.GetImmediateOutputStream())
        {
            const char *output = result.GetOutputData();
            if (output && output[0])
                io_handler.GetOutputStreamFile()->PutCString(output);
        }
    
        // Now emit the command error text from the command we just executed
        if (!result.GetImmediateErrorStream())
        {
            const char *error = result.GetErrorData();
            if (error && error[0])
                io_handler.GetErrorStreamFile()->PutCString(error);
        }
    }
    
    switch (result.GetStatus())
    {
        case eReturnStatusInvalid:
        case eReturnStatusSuccessFinishNoResult:
        case eReturnStatusSuccessFinishResult:
        case eReturnStatusStarted:
            break;

        case eReturnStatusSuccessContinuingNoResult:
        case eReturnStatusSuccessContinuingResult:
            if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
                io_handler.SetIsDone(true);
            break;

        case eReturnStatusFailed:
            m_num_errors++;
            if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
                io_handler.SetIsDone(true);
            break;
            
        case eReturnStatusQuit:
            m_quit_requested = true;
            io_handler.SetIsDone(true);
            break;
    }

    // Finally, if we're going to stop on crash, check that here:
    if (!m_quit_requested
        && result.GetDidChangeProcessState()
        && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash))
    {
        bool should_stop = false;
        TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
        if (target_sp)
        {
            ProcessSP process_sp (target_sp->GetProcessSP());
            if (process_sp)
            {
                for (ThreadSP thread_sp : process_sp->GetThreadList().Threads())
                {
                    StopReason reason = thread_sp->GetStopReason();
                    if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation)
                    {
                        should_stop = true;
                        break;
                    }
                }
            }
        }
        if (should_stop)
        {
            io_handler.SetIsDone(true);
            m_stopped_for_crash = true;
        }
    }
}

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
        }
    }

    ScriptInterpreter *script_interpreter = GetScriptInterpreter (false);
    if (script_interpreter)
    {
        if (script_interpreter->Interrupt())
            return true;
    }
    return false;
}

void
CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,
                                                  IOHandlerDelegate &delegate,
                                                  bool asynchronously,
                                                  void *baton)
{
    Debugger &debugger = GetDebugger();
    IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
                                                      IOHandler::Type::CommandList,
                                                      "lldb",       // Name of input reader for history
                                                      prompt,       // Prompt
                                                      NULL,         // Continuation prompt
                                                      true,         // Get multiple lines
                                                      debugger.GetUseColor(),
                                                      0,            // Don't show line numbers
                                                      delegate));   // IOHandlerDelegate
    
    if (io_handler_sp)
    {
        io_handler_sp->SetUserData (baton);
        if (asynchronously)
            debugger.PushIOHandler(io_handler_sp);
        else
            debugger.RunIOHandler(io_handler_sp);
    }
    
}


void
CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt,
                                                    IOHandlerDelegate &delegate,
                                                    bool asynchronously,
                                                    void *baton)
{
    Debugger &debugger = GetDebugger();
    IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
                                                      IOHandler::Type::PythonCode,
                                                      "lldb-python",    // Name of input reader for history
                                                      prompt,           // Prompt
                                                      NULL,             // Continuation prompt
                                                      true,             // Get multiple lines
                                                      debugger.GetUseColor(),
                                                      0,                // Don't show line numbers
                                                      delegate));       // IOHandlerDelegate
    
    if (io_handler_sp)
    {
        io_handler_sp->SetUserData (baton);
        if (asynchronously)
            debugger.PushIOHandler(io_handler_sp);
        else
            debugger.RunIOHandler(io_handler_sp);
    }

}

bool
CommandInterpreter::IsActive ()
{
    return m_debugger.IsTopIOHandler (m_command_io_handler_sp);
}

lldb::IOHandlerSP
CommandInterpreter::GetIOHandler(bool force_create, CommandInterpreterRunOptions *options)
{
    // 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.
    if (force_create || !m_command_io_handler_sp)
    {
        // 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.
        uint32_t flags = 0;
        
        if (options)
        {
            if (options->m_stop_on_continue == eLazyBoolYes)
                flags |= eHandleCommandFlagStopOnContinue;
            if (options->m_stop_on_error == eLazyBoolYes)
                flags |= eHandleCommandFlagStopOnError;
            if (options->m_stop_on_crash == eLazyBoolYes)
                flags |= eHandleCommandFlagStopOnCrash;
            if (options->m_echo_commands != eLazyBoolNo)
                flags |= eHandleCommandFlagEchoCommand;
            if (options->m_print_results != eLazyBoolNo)
                flags |= eHandleCommandFlagPrintResult;
        }
        else
        {
            flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult;
        }
        
        m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger,
                                                             IOHandler::Type::CommandInterpreter,
                                                             m_debugger.GetInputFile(),
                                                             m_debugger.GetOutputFile(),
                                                             m_debugger.GetErrorFile(),
                                                             flags,
                                                             "lldb",
                                                             m_debugger.GetPrompt(),
                                                             NULL,                      // Continuation prompt
                                                             false,                     // Don't enable multiple line input, just single line commands
                                                             m_debugger.GetUseColor(),
                                                             0,            // Don't show line numbers
                                                             *this));
    }
    return m_command_io_handler_sp;
}

void
CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
                                          bool spawn_thread,
                                          CommandInterpreterRunOptions &options)
{
    // Always re-create the command intepreter when we run it in case
    // any file handles have changed.
    bool force_create = true;
    m_debugger.PushIOHandler(GetIOHandler(force_create, &options));
    m_stopped_for_crash = false;
    
    if (auto_handle_events)
        m_debugger.StartEventHandlerThread();
    
    if (spawn_thread)
    {
        m_debugger.StartIOHandlerThread();
    }
    else
    {
        m_debugger.ExecuteIOHandlers();
        
        if (auto_handle_events)
            m_debugger.StopEventHandlerThread();
    }
    
}

