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

#include "CommandObjectCommands.h"
#include "CommandObjectHelp.h"
#include "CommandObjectRegexCommand.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandHistory.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/StringList.h"
#include "llvm/ADT/StringRef.h"
#include <optional>

using namespace lldb;
using namespace lldb_private;

// CommandObjectCommandsSource

#define LLDB_OPTIONS_source
#include "CommandOptions.inc"

class CommandObjectCommandsSource : public CommandObjectParsed {
public:
  CommandObjectCommandsSource(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "command source",
            "Read and execute LLDB commands from the file <filename>.",
            nullptr) {
    AddSimpleArgumentList(eArgTypeFilename);
  }

  ~CommandObjectCommandsSource() override = default;

  std::optional<std::string> GetRepeatCommand(Args &current_command_args,
                                              uint32_t index) override {
    return std::string("");
  }

  Options *GetOptions() override { return &m_options; }

protected:
  class CommandOptions : public Options {
  public:
    CommandOptions()
        : m_stop_on_error(true), m_silent_run(false), m_stop_on_continue(true),
          m_cmd_relative_to_command_file(false) {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'e':
        error = m_stop_on_error.SetValueFromString(option_arg);
        break;

      case 'c':
        error = m_stop_on_continue.SetValueFromString(option_arg);
        break;

      case 'C':
        m_cmd_relative_to_command_file = true;
        break;

      case 's':
        error = m_silent_run.SetValueFromString(option_arg);
        break;

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_stop_on_error.Clear();
      m_silent_run.Clear();
      m_stop_on_continue.Clear();
      m_cmd_relative_to_command_file.Clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_source_options);
    }

    // Instance variables to hold the values for command options.

    OptionValueBoolean m_stop_on_error;
    OptionValueBoolean m_silent_run;
    OptionValueBoolean m_stop_on_continue;
    OptionValueBoolean m_cmd_relative_to_command_file;
  };

  void DoExecute(Args &command, CommandReturnObject &result) override {
    if (command.GetArgumentCount() != 1) {
      result.AppendErrorWithFormat(
          "'%s' takes exactly one executable filename argument.\n",
          GetCommandName().str().c_str());
      return;
    }

    FileSpec source_dir = {};
    if (m_options.m_cmd_relative_to_command_file) {
      source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
      if (!source_dir) {
        result.AppendError("command source -C can only be specified "
                           "from a command file");
        result.SetStatus(eReturnStatusFailed);
        return;
      }
    }

    FileSpec cmd_file(command[0].ref());
    if (source_dir) {
      // Prepend the source_dir to the cmd_file path:
      if (!cmd_file.IsRelative()) {
        result.AppendError("command source -C can only be used "
                           "with a relative path.");
        result.SetStatus(eReturnStatusFailed);
        return;
      }
      cmd_file.MakeAbsolute(source_dir);
    }

    FileSystem::Instance().Resolve(cmd_file);

    CommandInterpreterRunOptions options;
    // If any options were set, then use them
    if (m_options.m_stop_on_error.OptionWasSet() ||
        m_options.m_silent_run.OptionWasSet() ||
        m_options.m_stop_on_continue.OptionWasSet()) {
      if (m_options.m_stop_on_continue.OptionWasSet())
        options.SetStopOnContinue(
            m_options.m_stop_on_continue.GetCurrentValue());

      if (m_options.m_stop_on_error.OptionWasSet())
        options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());

      // Individual silent setting is override for global command echo settings.
      if (m_options.m_silent_run.GetCurrentValue()) {
        options.SetSilent(true);
      } else {
        options.SetPrintResults(true);
        options.SetPrintErrors(true);
        options.SetEchoCommands(m_interpreter.GetEchoCommands());
        options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands());
      }
    }

    m_interpreter.HandleCommandsFromFile(cmd_file, options, result);
  }

  CommandOptions m_options;
};

#pragma mark CommandObjectCommandsAlias
// CommandObjectCommandsAlias

#define LLDB_OPTIONS_alias
#include "CommandOptions.inc"

static const char *g_python_command_instructions =
    "Enter your Python command(s). Type 'DONE' to end.\n"
    "You must define a Python function with this signature:\n"
    "def my_command_impl(debugger, args, exe_ctx, result, internal_dict):\n";

class CommandObjectCommandsAlias : public CommandObjectRaw {
protected:
  class CommandOptions : public OptionGroup {
  public:
    CommandOptions() = default;

    ~CommandOptions() override = default;

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_alias_options);
    }

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
                          ExecutionContext *execution_context) override {
      Status error;

      const int short_option = GetDefinitions()[option_idx].short_option;
      std::string option_str(option_value);

      switch (short_option) {
      case 'h':
        m_help.SetCurrentValue(option_str);
        m_help.SetOptionWasSet();
        break;

      case 'H':
        m_long_help.SetCurrentValue(option_str);
        m_long_help.SetOptionWasSet();
        break;

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_help.Clear();
      m_long_help.Clear();
    }

    OptionValueString m_help;
    OptionValueString m_long_help;
  };

  OptionGroupOptions m_option_group;
  CommandOptions m_command_options;

public:
  Options *GetOptions() override { return &m_option_group; }

  CommandObjectCommandsAlias(CommandInterpreter &interpreter)
      : CommandObjectRaw(
            interpreter, "command alias",
            "Define a custom command in terms of an existing command.") {
    m_option_group.Append(&m_command_options);
    m_option_group.Finalize();

    SetHelpLong(
        "'alias' allows the user to create a short-cut or abbreviation for long \
commands, multi-word commands, and commands that take particular options.  \
Below are some simple examples of how one might use the 'alias' command:"
        R"(

(lldb) command alias sc script

    Creates the abbreviation 'sc' for the 'script' command.

(lldb) command alias bp breakpoint

)"
        "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
breakpoint commands are two-word commands, the user would still need to \
enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
        R"(

(lldb) command alias bpl breakpoint list

    Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.

)"
        "An alias can include some options for the command, with the values either \
filled in at the time the alias is created, or specified as positional \
arguments, to be filled in when the alias is invoked.  The following example \
shows how to create aliases with options:"
        R"(

(lldb) command alias bfl breakpoint set -f %1 -l %2

)"
        "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
options already part of the alias.  So if the user wants to set a breakpoint \
by file and line without explicitly having to use the -f and -l options, the \
user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
for the actual arguments that will be passed when the alias command is used.  \
The number in the placeholder refers to the position/order the actual value \
occupies when the alias is used.  All the occurrences of '%1' in the alias \
will be replaced with the first argument, all the occurrences of '%2' in the \
alias will be replaced with the second argument, and so on.  This also allows \
actual arguments to be used multiple times within an alias (see 'process \
launch' example below)."
        R"(

)"
        "Note: the positional arguments must substitute as whole words in the resultant \
command, so you can't at present do something like this to append the file extension \
\".cpp\":"
        R"(

(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2

)"
        "For more complex aliasing, use the \"command regex\" command instead.  In the \
'bfl' case above, the actual file value will be filled in with the first argument \
following 'bfl' and the actual line number value will be filled in with the second \
argument.  The user would use this alias as follows:"
        R"(

(lldb) command alias bfl breakpoint set -f %1 -l %2
(lldb) bfl my-file.c 137

This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.

Another example:

(lldb) command alias pltty process launch -s -o %1 -e %1
(lldb) pltty /dev/tty0

    Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'

)"
        "If the user always wanted to pass the same value to a particular option, the \
alias could be defined with that value directly in the alias as a constant, \
rather than using a positional placeholder:"
        R"(

(lldb) command alias bl3 breakpoint set -f %1 -l 3

    Always sets a breakpoint on line 3 of whatever file is indicated.

)"

        "If the alias abbreviation or the full alias command collides with another \
existing command, the command resolver will prefer to use the alias over any \
other command as far as there is only one alias command match.");

    CommandArgumentEntry arg1;
    CommandArgumentEntry arg2;
    CommandArgumentEntry arg3;
    CommandArgumentData alias_arg;
    CommandArgumentData cmd_arg;
    CommandArgumentData options_arg;

    // Define the first (and only) variant of this arg.
    alias_arg.arg_type = eArgTypeAliasName;
    alias_arg.arg_repetition = eArgRepeatPlain;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg1.push_back(alias_arg);

    // Define the first (and only) variant of this arg.
    cmd_arg.arg_type = eArgTypeCommandName;
    cmd_arg.arg_repetition = eArgRepeatPlain;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg2.push_back(cmd_arg);

    // Define the first (and only) variant of this arg.
    options_arg.arg_type = eArgTypeAliasOptions;
    options_arg.arg_repetition = eArgRepeatOptional;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg3.push_back(options_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg1);
    m_arguments.push_back(arg2);
    m_arguments.push_back(arg3);
  }

  ~CommandObjectCommandsAlias() override = default;

protected:
  void DoExecute(llvm::StringRef raw_command_line,
                 CommandReturnObject &result) override {
    if (raw_command_line.empty()) {
      result.AppendError("'command alias' requires at least two arguments");
      return;
    }

    ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
    m_option_group.NotifyOptionParsingStarting(&exe_ctx);

    OptionsWithRaw args_with_suffix(raw_command_line);

    if (args_with_suffix.HasArgs())
      if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,
                                 m_option_group, exe_ctx))
        return;

    llvm::StringRef raw_command_string = args_with_suffix.GetRawPart();
    Args args(raw_command_string);

    if (args.GetArgumentCount() < 2) {
      result.AppendError("'command alias' requires at least two arguments");
      return;
    }

    // Get the alias command.

    auto alias_command = args[0].ref();
    if (alias_command.starts_with("-")) {
      result.AppendError("aliases starting with a dash are not supported");
      if (alias_command == "--help" || alias_command == "--long-help") {
        result.AppendWarning("if trying to pass options to 'command alias' add "
                             "a -- at the end of the options");
      }
      return;
    }

    // Strip the new alias name off 'raw_command_string'  (leave it on args,
    // which gets passed to 'Execute', which does the stripping itself.
    size_t pos = raw_command_string.find(alias_command);
    if (pos == 0) {
      raw_command_string = raw_command_string.substr(alias_command.size());
      pos = raw_command_string.find_first_not_of(' ');
      if ((pos != std::string::npos) && (pos > 0))
        raw_command_string = raw_command_string.substr(pos);
    } else {
      result.AppendError("Error parsing command string.  No alias created.");
      return;
    }

    // Verify that the command is alias-able.
    if (m_interpreter.CommandExists(alias_command)) {
      result.AppendErrorWithFormat(
          "'%s' is a permanent debugger command and cannot be redefined.\n",
          args[0].c_str());
      return;
    }

    if (m_interpreter.UserMultiwordCommandExists(alias_command)) {
      result.AppendErrorWithFormat(
          "'%s' is a user container command and cannot be overwritten.\n"
          "Delete it first with 'command container delete'\n",
          args[0].c_str());
      return;
    }

    // Get CommandObject that is being aliased. The command name is read from
    // the front of raw_command_string. raw_command_string is returned with the
    // name of the command object stripped off the front.
    llvm::StringRef original_raw_command_string = raw_command_string;
    CommandObject *cmd_obj =
        m_interpreter.GetCommandObjectForCommand(raw_command_string);

    if (!cmd_obj) {
      result.AppendErrorWithFormat("invalid command given to 'command alias'. "
                                   "'%s' does not begin with a valid command."
                                   "  No alias created.",
                                   original_raw_command_string.str().c_str());
    } else if (!cmd_obj->WantsRawCommandString()) {
      // Note that args was initialized with the original command, and has not
      // been updated to this point. Therefore can we pass it to the version of
      // Execute that does not need/expect raw input in the alias.
      HandleAliasingNormalCommand(args, result);
    } else {
      HandleAliasingRawCommand(alias_command, raw_command_string, *cmd_obj,
                               result);
    }
  }

  bool HandleAliasingRawCommand(llvm::StringRef alias_command,
                                llvm::StringRef raw_command_string,
                                CommandObject &cmd_obj,
                                CommandReturnObject &result) {
    // Verify & handle any options/arguments passed to the alias command

    OptionArgVectorSP option_arg_vector_sp =
        OptionArgVectorSP(new OptionArgVector);

    const bool include_aliases = true;
    // Look up the command using command's name first.  This is to resolve
    // aliases when you are making nested aliases.  But if you don't find
    // it that way, then it wasn't an alias and we can just use the object
    // we were passed in.
    CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact(
            cmd_obj.GetCommandName(), include_aliases);
    if (!cmd_obj_sp)
      cmd_obj_sp = cmd_obj.shared_from_this();

    if (m_interpreter.AliasExists(alias_command) ||
        m_interpreter.UserCommandExists(alias_command)) {
      result.AppendWarningWithFormat(
          "Overwriting existing definition for '%s'.\n",
          alias_command.str().c_str());
    }
    if (CommandAlias *alias = m_interpreter.AddAlias(
            alias_command, cmd_obj_sp, raw_command_string)) {
      if (m_command_options.m_help.OptionWasSet())
        alias->SetHelp(m_command_options.m_help.GetCurrentValue());
      if (m_command_options.m_long_help.OptionWasSet())
        alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else {
      result.AppendError("Unable to create requested alias.\n");
    }
    return result.Succeeded();
  }

  bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
    size_t argc = args.GetArgumentCount();

    if (argc < 2) {
      result.AppendError("'command alias' requires at least two arguments");
      return false;
    }

    // Save these in std::strings since we're going to shift them off.
    const std::string alias_command(std::string(args[0].ref()));
    const std::string actual_command(std::string(args[1].ref()));

    args.Shift(); // Shift the alias command word off the argument vector.
    args.Shift(); // Shift the old command word off the argument vector.

    // Verify that the command is alias'able, and get the appropriate command
    // object.

    if (m_interpreter.CommandExists(alias_command)) {
      result.AppendErrorWithFormat(
          "'%s' is a permanent debugger command and cannot be redefined.\n",
          alias_command.c_str());
      return false;
    }

    if (m_interpreter.UserMultiwordCommandExists(alias_command)) {
      result.AppendErrorWithFormat(
          "'%s' is user container command and cannot be overwritten.\n"
          "Delete it first with 'command container delete'",
          alias_command.c_str());
      return false;
    }

    CommandObjectSP command_obj_sp(
        m_interpreter.GetCommandSPExact(actual_command, true));
    CommandObjectSP subcommand_obj_sp;
    bool use_subcommand = false;
    if (!command_obj_sp) {
      result.AppendErrorWithFormat("'%s' is not an existing command.\n",
                                   actual_command.c_str());
      return false;
    }
    CommandObject *cmd_obj = command_obj_sp.get();
    CommandObject *sub_cmd_obj = nullptr;
    OptionArgVectorSP option_arg_vector_sp =
        OptionArgVectorSP(new OptionArgVector);

    while (cmd_obj->IsMultiwordObject() && !args.empty()) {
      auto sub_command = args[0].ref();
      assert(!sub_command.empty());
      subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
      if (!subcommand_obj_sp) {
        result.AppendErrorWithFormat(
            "'%s' is not a valid sub-command of '%s'.  "
            "Unable to create alias.\n",
            args[0].c_str(), actual_command.c_str());
        return false;
      }

      sub_cmd_obj = subcommand_obj_sp.get();
      use_subcommand = true;
      args.Shift(); // Shift the sub_command word off the argument vector.
      cmd_obj = sub_cmd_obj;
    }

    // Verify & handle any options/arguments passed to the alias command

    std::string args_string;

    if (!args.empty()) {
      CommandObjectSP tmp_sp =
          m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName());
      if (use_subcommand)
        tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName());

      args.GetCommandString(args_string);
    }

    if (m_interpreter.AliasExists(alias_command) ||
        m_interpreter.UserCommandExists(alias_command)) {
      result.AppendWarningWithFormat(
          "Overwriting existing definition for '%s'.\n", alias_command.c_str());
    }

    if (CommandAlias *alias = m_interpreter.AddAlias(
            alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
            args_string)) {
      if (m_command_options.m_help.OptionWasSet())
        alias->SetHelp(m_command_options.m_help.GetCurrentValue());
      if (m_command_options.m_long_help.OptionWasSet())
        alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else {
      result.AppendError("Unable to create requested alias.\n");
      return false;
    }

    return result.Succeeded();
  }
};

#pragma mark CommandObjectCommandsUnalias
// CommandObjectCommandsUnalias

class CommandObjectCommandsUnalias : public CommandObjectParsed {
public:
  CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "command unalias",
            "Delete one or more custom commands defined by 'command alias'.",
            nullptr) {
    AddSimpleArgumentList(eArgTypeAliasName);
  }

  ~CommandObjectCommandsUnalias() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
      return;

    for (const auto &ent : m_interpreter.GetAliases()) {
      request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
    }
  }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    CommandObject::CommandMap::iterator pos;
    CommandObject *cmd_obj;

    if (args.empty()) {
      result.AppendError("must call 'unalias' with a valid alias");
      return;
    }

    auto command_name = args[0].ref();
    cmd_obj = m_interpreter.GetCommandObject(command_name);
    if (!cmd_obj) {
      result.AppendErrorWithFormat(
          "'%s' is not a known command.\nTry 'help' to see a "
          "current list of commands.\n",
          args[0].c_str());
      return;
    }

    if (m_interpreter.CommandExists(command_name)) {
      if (cmd_obj->IsRemovable()) {
        result.AppendErrorWithFormat(
            "'%s' is not an alias, it is a debugger command which can be "
            "removed using the 'command delete' command.\n",
            args[0].c_str());
      } else {
        result.AppendErrorWithFormat(
            "'%s' is a permanent debugger command and cannot be removed.\n",
            args[0].c_str());
      }
      return;
    }

    if (!m_interpreter.RemoveAlias(command_name)) {
      if (m_interpreter.AliasExists(command_name))
        result.AppendErrorWithFormat(
            "Error occurred while attempting to unalias '%s'.\n",
            args[0].c_str());
      else
        result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
                                     args[0].c_str());
      return;
    }

    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }
};

#pragma mark CommandObjectCommandsDelete
// CommandObjectCommandsDelete

class CommandObjectCommandsDelete : public CommandObjectParsed {
public:
  CommandObjectCommandsDelete(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "command delete",
            "Delete one or more custom commands defined by 'command regex'.",
            nullptr) {
    AddSimpleArgumentList(eArgTypeCommandName);
  }

  ~CommandObjectCommandsDelete() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
      return;

    for (const auto &ent : m_interpreter.GetCommands()) {
      if (ent.second->IsRemovable())
        request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
    }
  }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    CommandObject::CommandMap::iterator pos;

    if (args.empty()) {
      result.AppendErrorWithFormat("must call '%s' with one or more valid user "
                                   "defined regular expression command names",
                                   GetCommandName().str().c_str());
      return;
    }

    auto command_name = args[0].ref();
    if (!m_interpreter.CommandExists(command_name)) {
      StreamString error_msg_stream;
      const bool generate_upropos = true;
      const bool generate_type_lookup = false;
      CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
          &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
          generate_upropos, generate_type_lookup);
      result.AppendError(error_msg_stream.GetString());
      return;
    }

    if (!m_interpreter.RemoveCommand(command_name)) {
      result.AppendErrorWithFormat(
          "'%s' is a permanent debugger command and cannot be removed.\n",
          args[0].c_str());
      return;
    }

    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }
};

// CommandObjectCommandsAddRegex

#define LLDB_OPTIONS_regex
#include "CommandOptions.inc"

#pragma mark CommandObjectCommandsAddRegex

class CommandObjectCommandsAddRegex : public CommandObjectParsed,
                                      public IOHandlerDelegateMultiline {
public:
  CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "command regex",
            "Define a custom command in terms of "
            "existing commands by matching "
            "regular expressions.",
            "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
        IOHandlerDelegateMultiline("",
                                   IOHandlerDelegate::Completion::LLDBCommand) {
    SetHelpLong(
        R"(
)"
        "This command allows the user to create powerful regular expression commands \
with substitutions. The regular expressions and substitutions are specified \
using the regular expression substitution format of:"
        R"(

    s/<regex>/<subst>/

)"
        "<regex> is a regular expression that can use parenthesis to capture regular \
expression input and substitute the captured matches in the output using %1 \
for the first match, %2 for the second, and so on."
        R"(

)"
        "The regular expressions can all be specified on the command line if more than \
one argument is provided. If just the command name is provided on the command \
line, then the regular expressions and substitutions can be entered on separate \
lines, followed by an empty line to terminate the command definition."
        R"(

EXAMPLES

)"
        "The following example will define a regular expression command named 'f' that \
will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
a number follows 'f':"
        R"(

    (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
    AddSimpleArgumentList(eArgTypeSEDStylePair, eArgRepeatOptional);
  }

  ~CommandObjectCommandsAddRegex() override = default;

protected:
  void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
    if (interactive) {
      if (lldb::LockableStreamFileSP output_sp =
              io_handler.GetOutputStreamFileSP()) {
        LockedStreamFile locked_stream = output_sp->Lock();
        locked_stream.PutCString(
            "Enter one or more sed substitution commands in "
            "the form: 's/<regex>/<subst>/'.\nTerminate the "
            "substitution list with an empty line.\n");
      }
    }
  }

  void IOHandlerInputComplete(IOHandler &io_handler,
                              std::string &data) override {
    io_handler.SetIsDone(true);
    if (m_regex_cmd_up) {
      StringList lines;
      if (lines.SplitIntoLines(data)) {
        bool check_only = false;
        for (const std::string &line : lines) {
          Status error = AppendRegexSubstitution(line, check_only);
          if (error.Fail()) {
            if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
              GetDebugger().GetAsyncOutputStream()->Printf("error: %s\n",
                                                           error.AsCString());
          }
        }
      }
      if (m_regex_cmd_up->HasRegexEntries()) {
        CommandObjectSP cmd_sp(m_regex_cmd_up.release());
        m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
      }
    }
  }

  void DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc == 0) {
      result.AppendError("usage: 'command regex <command-name> "
                         "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
      return;
    }

    Status error;
    auto name = command[0].ref();
    m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>(
        m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 0,
        true);

    if (argc == 1) {
      Debugger &debugger = GetDebugger();
      bool color_prompt = debugger.GetUseColor();
      const bool multiple_lines = true; // Get multiple lines
      IOHandlerSP io_handler_sp(new IOHandlerEditline(
          debugger, IOHandler::Type::Other,
          "lldb-regex",          // Name of input reader for history
          llvm::StringRef("> "), // Prompt
          llvm::StringRef(),     // Continuation prompt
          multiple_lines, color_prompt,
          0, // Don't show line numbers
          *this));

      if (io_handler_sp) {
        debugger.RunIOHandlerAsync(io_handler_sp);
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
      }
    } else {
      for (auto &entry : command.entries().drop_front()) {
        bool check_only = false;
        error = AppendRegexSubstitution(entry.ref(), check_only);
        if (error.Fail())
          break;
      }

      if (error.Success()) {
        AddRegexCommandToInterpreter();
      }
    }
    if (error.Fail()) {
      result.AppendError(error.AsCString());
    }
  }

  Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
                                 bool check_only) {
    Status error;

    if (!m_regex_cmd_up) {
      return Status::FromErrorStringWithFormat(
          "invalid regular expression command object for: '%.*s'",
          (int)regex_sed.size(), regex_sed.data());
      return error;
    }

    size_t regex_sed_size = regex_sed.size();

    if (regex_sed_size <= 1) {
      return Status::FromErrorStringWithFormat(
          "regular expression substitution string is too short: '%.*s'",
          (int)regex_sed.size(), regex_sed.data());
      return error;
    }

    if (regex_sed[0] != 's') {
      return Status::FromErrorStringWithFormat(
          "regular expression substitution string "
          "doesn't start with 's': '%.*s'",
          (int)regex_sed.size(), regex_sed.data());
      return error;
    }
    const size_t first_separator_char_pos = 1;
    // use the char that follows 's' as the regex separator character so we can
    // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
    const char separator_char = regex_sed[first_separator_char_pos];
    const size_t second_separator_char_pos =
        regex_sed.find(separator_char, first_separator_char_pos + 1);

    if (second_separator_char_pos == std::string::npos) {
      return Status::FromErrorStringWithFormat(
          "missing second '%c' separator char after '%.*s' in '%.*s'",
          separator_char,
          (int)(regex_sed.size() - first_separator_char_pos - 1),
          regex_sed.data() + (first_separator_char_pos + 1),
          (int)regex_sed.size(), regex_sed.data());
      return error;
    }

    const size_t third_separator_char_pos =
        regex_sed.find(separator_char, second_separator_char_pos + 1);

    if (third_separator_char_pos == std::string::npos) {
      return Status::FromErrorStringWithFormat(
          "missing third '%c' separator char after '%.*s' in '%.*s'",
          separator_char,
          (int)(regex_sed.size() - second_separator_char_pos - 1),
          regex_sed.data() + (second_separator_char_pos + 1),
          (int)regex_sed.size(), regex_sed.data());
      return error;
    }

    if (third_separator_char_pos != regex_sed_size - 1) {
      // Make sure that everything that follows the last regex separator char
      if (regex_sed.find_first_not_of("\t\n\v\f\r ",
                                      third_separator_char_pos + 1) !=
          std::string::npos) {
        return Status::FromErrorStringWithFormat(
            "extra data found after the '%.*s' regular expression substitution "
            "string: '%.*s'",
            (int)third_separator_char_pos + 1, regex_sed.data(),
            (int)(regex_sed.size() - third_separator_char_pos - 1),
            regex_sed.data() + (third_separator_char_pos + 1));
        return error;
      }
    } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
      return Status::FromErrorStringWithFormat(
          "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
          separator_char, separator_char, separator_char, (int)regex_sed.size(),
          regex_sed.data());
      return error;
    } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
      return Status::FromErrorStringWithFormat(
          "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
          separator_char, separator_char, separator_char, (int)regex_sed.size(),
          regex_sed.data());
      return error;
    }

    if (!check_only) {
      std::string regex(std::string(regex_sed.substr(
          first_separator_char_pos + 1,
          second_separator_char_pos - first_separator_char_pos - 1)));
      std::string subst(std::string(regex_sed.substr(
          second_separator_char_pos + 1,
          third_separator_char_pos - second_separator_char_pos - 1)));
      m_regex_cmd_up->AddRegexCommand(regex, subst);
    }
    return error;
  }

  void AddRegexCommandToInterpreter() {
    if (m_regex_cmd_up) {
      if (m_regex_cmd_up->HasRegexEntries()) {
        CommandObjectSP cmd_sp(m_regex_cmd_up.release());
        m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
      }
    }
  }

private:
  std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up;

  class CommandOptions : public Options {
  public:
    CommandOptions() = default;

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'h':
        m_help.assign(std::string(option_arg));
        break;
      case 's':
        m_syntax.assign(std::string(option_arg));
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_help.clear();
      m_syntax.clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_regex_options);
    }

    llvm::StringRef GetHelp() { return m_help; }

    llvm::StringRef GetSyntax() { return m_syntax; }

  protected:
    // Instance variables to hold the values for command options.

    std::string m_help;
    std::string m_syntax;
  };

  Options *GetOptions() override { return &m_options; }

  CommandOptions m_options;
};

class CommandObjectPythonFunction : public CommandObjectRaw {
public:
  CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
                              std::string funct, std::string help,
                              ScriptedCommandSynchronicity synch,
                              CompletionType completion_type)
      : CommandObjectRaw(interpreter, name), m_function_name(funct),
        m_synchro(synch), m_completion_type(completion_type) {
    if (!help.empty())
      SetHelp(help);
    else {
      StreamString stream;
      stream.Printf("For more information run 'help %s'", name.c_str());
      SetHelp(stream.GetString());
    }
  }

  ~CommandObjectPythonFunction() override = default;

  bool IsRemovable() const override { return true; }

  const std::string &GetFunctionName() { return m_function_name; }

  ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }

  llvm::StringRef GetHelpLong() override {
    if (m_fetched_help_long)
      return CommandObjectRaw::GetHelpLong();

    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
    if (!scripter)
      return CommandObjectRaw::GetHelpLong();

    std::string docstring;
    m_fetched_help_long =
        scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
    if (!docstring.empty())
      SetHelpLong(docstring);
    return CommandObjectRaw::GetHelpLong();
  }

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), m_completion_type, request, nullptr);
  }

  bool WantsCompletion() override { return true; }

protected:
  void DoExecute(llvm::StringRef raw_command_line,
                 CommandReturnObject &result) override {
    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();

    m_interpreter.IncreaseCommandUsage(*this);

    Status error;

    result.SetStatus(eReturnStatusInvalid);

    if (!scripter || !scripter->RunScriptBasedCommand(
                         m_function_name.c_str(), raw_command_line, m_synchro,
                         result, error, m_exe_ctx)) {
      result.AppendError(error.AsCString());
    } else {
      // Don't change the status if the command already set it...
      if (result.GetStatus() == eReturnStatusInvalid) {
        if (result.GetOutputString().empty())
          result.SetStatus(eReturnStatusSuccessFinishNoResult);
        else
          result.SetStatus(eReturnStatusSuccessFinishResult);
      }
    }
  }

private:
  std::string m_function_name;
  ScriptedCommandSynchronicity m_synchro;
  bool m_fetched_help_long = false;
  CompletionType m_completion_type = eNoCompletion;
};

/// This class implements a "raw" scripted command.  lldb does no parsing of the
/// command line, instead passing the line unaltered (except for backtick
/// substitution).
class CommandObjectScriptingObjectRaw : public CommandObjectRaw {
public:
  CommandObjectScriptingObjectRaw(CommandInterpreter &interpreter,
                                  std::string name,
                                  StructuredData::GenericSP cmd_obj_sp,
                                  ScriptedCommandSynchronicity synch,
                                  CompletionType completion_type)
      : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
        m_synchro(synch), m_fetched_help_short(false),
        m_fetched_help_long(false), m_completion_type(completion_type) {
    StreamString stream;
    stream.Printf("For more information run 'help %s'", name.c_str());
    SetHelp(stream.GetString());
    if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter())
      GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
  }

  ~CommandObjectScriptingObjectRaw() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), m_completion_type, request, nullptr);
  }

  bool WantsCompletion() override { return true; }

  bool IsRemovable() const override { return true; }

  ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }

  std::optional<std::string> GetRepeatCommand(Args &args,
                                              uint32_t index) override {
    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
    if (!scripter)
      return std::nullopt;

    return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args);
  }

  llvm::StringRef GetHelp() override {
    if (m_fetched_help_short)
      return CommandObjectRaw::GetHelp();
    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
    if (!scripter)
      return CommandObjectRaw::GetHelp();
    std::string docstring;
    m_fetched_help_short =
        scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
    if (!docstring.empty())
      SetHelp(docstring);

    return CommandObjectRaw::GetHelp();
  }

  llvm::StringRef GetHelpLong() override {
    if (m_fetched_help_long)
      return CommandObjectRaw::GetHelpLong();

    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
    if (!scripter)
      return CommandObjectRaw::GetHelpLong();

    std::string docstring;
    m_fetched_help_long =
        scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
    if (!docstring.empty())
      SetHelpLong(docstring);
    return CommandObjectRaw::GetHelpLong();
  }

protected:
  void DoExecute(llvm::StringRef raw_command_line,
                 CommandReturnObject &result) override {
    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();

    Status error;

    result.SetStatus(eReturnStatusInvalid);

    if (!scripter ||
        !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
                                         m_synchro, result, error, m_exe_ctx)) {
      result.AppendError(error.AsCString());
    } else {
      // Don't change the status if the command already set it...
      if (result.GetStatus() == eReturnStatusInvalid) {
        if (result.GetOutputString().empty())
          result.SetStatus(eReturnStatusSuccessFinishNoResult);
        else
          result.SetStatus(eReturnStatusSuccessFinishResult);
      }
    }
  }

private:
  StructuredData::GenericSP m_cmd_obj_sp;
  ScriptedCommandSynchronicity m_synchro;
  bool m_fetched_help_short : 1;
  bool m_fetched_help_long : 1;
  CompletionType m_completion_type = eNoCompletion;
};


/// This command implements a lldb parsed scripted command.  The command
/// provides a definition of the options and arguments, and a option value
/// setting callback, and then the command's execution function gets passed
/// just the parsed arguments.
/// Note, implementing a command in Python using these base interfaces is a bit
/// of a pain, but it is much easier to export this low level interface, and
/// then make it nicer on the Python side, than to try to do that in a
/// script language neutral way.
/// So I've also added a base class in Python that provides a table-driven
/// way of defining the options and arguments, which automatically fills the
/// option values, making them available as properties in Python.
/// 
class CommandObjectScriptingObjectParsed : public CommandObjectParsed {
private: 
  class CommandOptions : public Options {
  public:
    CommandOptions(CommandInterpreter &interpreter, 
        StructuredData::GenericSP cmd_obj_sp) : m_interpreter(interpreter), 
            m_cmd_obj_sp(cmd_obj_sp) {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      ScriptInterpreter *scripter = 
        m_interpreter.GetDebugger().GetScriptInterpreter();
      if (!scripter) {
        return Status::FromErrorString(
            "No script interpreter for SetOptionValue.");
        return error;
      }
      if (!m_cmd_obj_sp) {
        return Status::FromErrorString(
            "SetOptionValue called with empty cmd_obj.");
        return error;
      }
      if (!m_options_definition_up) {
        return Status::FromErrorString(
            "SetOptionValue called before options definitions "
            "were created.");
        return error;
      }
      // Pass the long option, since you aren't actually required to have a
      // short_option, and for those options the index or short option character
      // aren't meaningful on the python side.
      const char * long_option = 
        m_options_definition_up.get()[option_idx].long_option;
      bool success = scripter->SetOptionValueForCommandObject(m_cmd_obj_sp, 
        execution_context, long_option, option_arg);
      if (!success)
        return Status::FromErrorStringWithFormatv(
            "Error setting option: {0} to {1}", long_option, option_arg);
      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      ScriptInterpreter *scripter = 
        m_interpreter.GetDebugger().GetScriptInterpreter();
      if (!scripter || !m_cmd_obj_sp)
        return;

      scripter->OptionParsingStartedForCommandObject(m_cmd_obj_sp);
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      if (!m_options_definition_up)
        return {};
      return llvm::ArrayRef(m_options_definition_up.get(), m_num_options);
    }
    
    static Status ParseUsageMaskFromArray(StructuredData::ObjectSP obj_sp, 
        size_t counter, uint32_t &usage_mask) {
      // If the usage entry is not provided, we use LLDB_OPT_SET_ALL.
      // If the usage mask is a UINT, the option belongs to that group.
      // If the usage mask is a vector of UINT's, the option belongs to all the
      // groups listed.
      // If a subelement of the vector is a vector of two ints, then the option
      // belongs to the inclusive range from the first to the second element.
      Status error;
      if (!obj_sp) {
        usage_mask = LLDB_OPT_SET_ALL;
        return error;
      }
      
      usage_mask = 0;
      
      StructuredData::UnsignedInteger *uint_val = 
          obj_sp->GetAsUnsignedInteger();
      if (uint_val) {
        // If this is an integer, then this specifies a single group:
        uint32_t value = uint_val->GetValue();
        if (value == 0) {
          return Status::FromErrorStringWithFormatv(
              "0 is not a valid group for option {0}", counter);
        }
        usage_mask = (1 << (value - 1));
        return error;
      }
      // Otherwise it has to be an array:
      StructuredData::Array *array_val = obj_sp->GetAsArray();
      if (!array_val) {
        return Status::FromErrorStringWithFormatv(
            "required field is not a array for option {0}", counter);
      }
      // This is the array ForEach for accumulating a group usage mask from
      // an array of string descriptions of groups.
      auto groups_accumulator 
          = [counter, &usage_mask, &error] 
            (StructuredData::Object *obj) -> bool {
        StructuredData::UnsignedInteger *int_val = obj->GetAsUnsignedInteger();
        if (int_val) {
          uint32_t value = int_val->GetValue();
          if (value == 0) {
            error = Status::FromErrorStringWithFormatv(
                "0 is not a valid group for element {0}", counter);
            return false;
          }
          usage_mask |= (1 << (value - 1));
          return true;
        }
        StructuredData::Array *arr_val = obj->GetAsArray();
        if (!arr_val) {
          error = Status::FromErrorStringWithFormatv(
              "Group element not an int or array of integers for element {0}",
              counter);
          return false; 
        }
        size_t num_range_elem = arr_val->GetSize();
        if (num_range_elem != 2) {
          error = Status::FromErrorStringWithFormatv(
              "Subranges of a group not a start and a stop for element {0}",
              counter);
          return false; 
        }
        int_val = arr_val->GetItemAtIndex(0)->GetAsUnsignedInteger();
        if (!int_val) {
          error = Status::FromErrorStringWithFormatv(
              "Start element of a subrange of a "
              "group not unsigned int for element {0}",
              counter);
          return false; 
        }
        uint32_t start = int_val->GetValue();
        int_val = arr_val->GetItemAtIndex(1)->GetAsUnsignedInteger();
        if (!int_val) {
          error = Status::FromErrorStringWithFormatv(
              "End element of a subrange of a group"
              " not unsigned int for element {0}",
              counter);
          return false; 
        }
        uint32_t end = int_val->GetValue();
        if (start == 0 || end == 0 || start > end) {
          error = Status::FromErrorStringWithFormatv(
              "Invalid subrange of a group: {0} - "
              "{1} for element {2}",
              start, end, counter);
          return false;
        }
        for (uint32_t i = start; i <= end; i++) {
          usage_mask |= (1 << (i - 1));
        }
        return true;
      };
      array_val->ForEach(groups_accumulator);
      return error;
    }
    
    
    Status SetOptionsFromArray(StructuredData::Dictionary &options) {
      Status error;
      m_num_options = options.GetSize();
      m_options_definition_up.reset(new OptionDefinition[m_num_options]);
      // We need to hand out pointers to contents of these vectors; we reserve
      // as much as we'll need up front so they don't get freed on resize...
      m_usage_container.resize(m_num_options);
      m_enum_storage.resize(m_num_options);
      m_enum_vector.resize(m_num_options);
      
      size_t counter = 0;
      size_t short_opt_counter = 0;
      // This is the Array::ForEach function for adding option elements:
      auto add_element = [this, &error, &counter, &short_opt_counter] 
          (llvm::StringRef long_option, StructuredData::Object *object) -> bool {
        StructuredData::Dictionary *opt_dict = object->GetAsDictionary();
        if (!opt_dict) {
          error = Status::FromErrorString(
              "Value in options dictionary is not a dictionary");
          return false;
        }
        OptionDefinition &option_def = m_options_definition_up.get()[counter];
        
        // We aren't exposing the validator yet, set it to null
        option_def.validator = nullptr;
        // We don't require usage masks, so set it to one group by default:
        option_def.usage_mask = 1;
        
        // Now set the fields of the OptionDefinition Array from the dictionary:
        //
        // Note that I don't check for unknown fields in the option dictionaries
        // so a scriptor can add extra elements that are helpful when they go to
        // do "set_option_value"
        
        // Usage Mask:
        StructuredData::ObjectSP obj_sp = opt_dict->GetValueForKey("groups");
        if (obj_sp) {
          error = ParseUsageMaskFromArray(obj_sp, counter, 
                                          option_def.usage_mask);
          if (error.Fail())
            return false;
        }

        // Required:
        option_def.required = false;
        obj_sp = opt_dict->GetValueForKey("required");
        if (obj_sp) {
          StructuredData::Boolean *boolean_val = obj_sp->GetAsBoolean();
          if (!boolean_val) {
            error = Status::FromErrorStringWithFormatv(
                "'required' field is not a boolean "
                "for option {0}",
                counter);
            return false;
          } 
          option_def.required = boolean_val->GetValue();      
        }
        
        // Short Option:
        int short_option;
        obj_sp = opt_dict->GetValueForKey("short_option");
        if (obj_sp) {
          // The value is a string, so pull the 
          llvm::StringRef short_str = obj_sp->GetStringValue();
          if (short_str.empty()) {
            error = Status::FromErrorStringWithFormatv(
                "short_option field empty for "
                "option {0}",
                counter);
            return false;
          } else if (short_str.size() != 1) {
            error = Status::FromErrorStringWithFormatv(
                "short_option field has extra "
                "characters for option {0}",
                counter);
            return false;
          }
          short_option = (int) short_str[0];
        } else {
          // If the short option is not provided, then we need a unique value 
          // less than the lowest printable ASCII character.
          short_option = short_opt_counter++;
        }
        option_def.short_option = short_option;
        
        // Long Option is the key from the outer dict:
        if (long_option.empty()) {
          error = Status::FromErrorStringWithFormatv(
              "empty long_option for option {0}", counter);
          return false;
        }
        auto inserted = g_string_storer.insert(long_option.str());
        option_def.long_option = ((*(inserted.first)).data());
        
        // Value Type:
        obj_sp = opt_dict->GetValueForKey("value_type");
        if (obj_sp) {
          StructuredData::UnsignedInteger *uint_val 
              = obj_sp->GetAsUnsignedInteger();
          if (!uint_val) {
            error = Status::FromErrorStringWithFormatv(
                "Value type must be an unsigned "
                "integer");
            return false;
          }
          uint64_t val_type = uint_val->GetValue();
          if (val_type >= eArgTypeLastArg) {
            error =
                Status::FromErrorStringWithFormatv("Value type {0} beyond the "
                                                   "CommandArgumentType bounds",
                                                   val_type);
            return false;
          }
          option_def.argument_type = (CommandArgumentType) val_type;
          option_def.option_has_arg = true;
        } else {
          option_def.argument_type = eArgTypeNone;
          option_def.option_has_arg = false;
        }
        
        // Completion Type:
        obj_sp = opt_dict->GetValueForKey("completion_type");
        if (obj_sp) {
          StructuredData::UnsignedInteger *uint_val = obj_sp->GetAsUnsignedInteger();
          if (!uint_val) {
            error = Status::FromErrorStringWithFormatv(
                "Completion type must be an "
                "unsigned integer for option {0}",
                counter);
            return false;
          }
          uint64_t completion_type = uint_val->GetValue();
          if (completion_type > eCustomCompletion) {
            error = Status::FromErrorStringWithFormatv(
                "Completion type for option {0} "
                "beyond the CompletionType bounds",
                completion_type);
            return false;
          }
          option_def.completion_type = (CommandArgumentType) completion_type;
        } else
          option_def.completion_type = eNoCompletion;

        // Usage Text:
        obj_sp = opt_dict->GetValueForKey("help");
        if (!obj_sp) {
          error = Status::FromErrorStringWithFormatv(
              "required usage missing from option "
              "{0}",
              counter);
          return false;
        }
        llvm::StringRef usage_stref;
        usage_stref = obj_sp->GetStringValue();
        if (usage_stref.empty()) {
          error = Status::FromErrorStringWithFormatv(
              "empty usage text for option {0}", counter);
          return false;
        }
        m_usage_container[counter] = usage_stref.str().c_str();
        option_def.usage_text = m_usage_container[counter].data();

        // Enum Values:
        
        obj_sp = opt_dict->GetValueForKey("enum_values");
        if (obj_sp) {
          StructuredData::Array *array = obj_sp->GetAsArray();
          if (!array) {
            error = Status::FromErrorStringWithFormatv(
                "enum values must be an array for "
                "option {0}",
                counter);
            return false;
          }
          size_t num_elem = array->GetSize();
          size_t enum_ctr = 0;
          m_enum_storage[counter] = std::vector<EnumValueStorage>(num_elem);
          std::vector<EnumValueStorage> &curr_elem = m_enum_storage[counter];
          
          // This is the Array::ForEach function for adding enum elements:
          // Since there are only two fields to specify the enum, use a simple
          // two element array with value first, usage second.
          // counter is only used for reporting so I pass it by value here.
          auto add_enum = [&enum_ctr, &curr_elem, counter, &error] 
              (StructuredData::Object *object) -> bool {
            StructuredData::Array *enum_arr = object->GetAsArray();
            if (!enum_arr) {
              error = Status::FromErrorStringWithFormatv(
                  "Enum values for option {0} not "
                  "an array",
                  counter);
              return false;
            }
            size_t num_enum_elements = enum_arr->GetSize();
            if (num_enum_elements != 2) {
              error = Status::FromErrorStringWithFormatv(
                  "Wrong number of elements: {0} "
                  "for enum {1} in option {2}",
                  num_enum_elements, enum_ctr, counter);
              return false;
            }
            // Enum Value:
            StructuredData::ObjectSP obj_sp = enum_arr->GetItemAtIndex(0);
            llvm::StringRef val_stref = obj_sp->GetStringValue();
            std::string value_cstr_str = val_stref.str().c_str();
            
            // Enum Usage:
            obj_sp = enum_arr->GetItemAtIndex(1);
            if (!obj_sp) {
              error = Status::FromErrorStringWithFormatv(
                  "No usage for enum {0} in option "
                  "{1}",
                  enum_ctr, counter);
              return false;
            }
            llvm::StringRef usage_stref = obj_sp->GetStringValue();
            std::string usage_cstr_str = usage_stref.str().c_str();
            curr_elem[enum_ctr] = EnumValueStorage(value_cstr_str, 
                usage_cstr_str, enum_ctr);
            
            enum_ctr++;
            return true;
          }; // end of add_enum
          
          array->ForEach(add_enum);
          if (!error.Success())
            return false;
          // We have to have a vector of elements to set in the options, make 
          // that here:
          for (auto &elem : curr_elem)
            m_enum_vector[counter].emplace_back(elem.element);

          option_def.enum_values = llvm::ArrayRef(m_enum_vector[counter]);
        }
        counter++;
        return true;
      }; // end of add_element
      
      options.ForEach(add_element);
      return error;
    }

    size_t GetNumOptions() { return m_num_options; }

    void PrepareOptionsForCompletion(CompletionRequest &request,
                                     OptionElementVector &option_vec,
                                     ExecutionContext *exe_ctx) {
      // I'm not sure if we'll get into trouble doing an option parsing start
      // and end in this context.  If so, then I'll have to directly tell the
      // scripter to do this.
      OptionParsingStarting(exe_ctx);
      auto opt_defs = GetDefinitions();

      // Iterate through the options we found so far, and push them into
      // the scripted side.
      for (auto option_elem : option_vec) {
        int cur_defs_index = option_elem.opt_defs_index;
        // If we don't recognize this option we can't set it.
        if (cur_defs_index == OptionArgElement::eUnrecognizedArg ||
            cur_defs_index == OptionArgElement::eBareDash ||
            cur_defs_index == OptionArgElement::eBareDoubleDash)
          continue;
        bool option_has_arg = opt_defs[cur_defs_index].option_has_arg;
        llvm::StringRef cur_arg_value;
        if (option_has_arg) {
          int cur_arg_pos = option_elem.opt_arg_pos;
          if (cur_arg_pos != OptionArgElement::eUnrecognizedArg &&
              cur_arg_pos != OptionArgElement::eBareDash &&
              cur_arg_pos != OptionArgElement::eBareDoubleDash) {
            cur_arg_value =
                request.GetParsedLine().GetArgumentAtIndex(cur_arg_pos);
          }
        }
        SetOptionValue(cur_defs_index, cur_arg_value, exe_ctx);
      }
      OptionParsingFinished(exe_ctx);
    }

    void
    ProcessCompletionDict(CompletionRequest &request,
                          StructuredData::DictionarySP &completion_dict_sp) {
      // We don't know how to process an empty completion dict, our callers have
      // to do that.
      assert(completion_dict_sp && "Must have valid completion dict");
      // First handle the case of a single completion:
      llvm::StringRef completion;
      // If the dictionary has one element "no-completion" then we return here
      if (completion_dict_sp->GetValueForKeyAsString("no-completion",
                                                     completion))
        return;

      if (completion_dict_sp->GetValueForKeyAsString("completion",
                                                     completion)) {
        llvm::StringRef mode_str;
        CompletionMode mode = CompletionMode::Normal;
        if (completion_dict_sp->GetValueForKeyAsString("mode", mode_str)) {
          if (mode_str == "complete")
            mode = CompletionMode::Normal;
          else if (mode_str == "partial")
            mode = CompletionMode::Partial;
          else {
            // FIXME - how do I report errors here?
            return;
          }
        }
        request.AddCompletion(completion, "", mode);
        return;
      }
      // The completions are required, the descriptions are not:
      StructuredData::Array *completions;
      StructuredData::Array *descriptions;
      if (completion_dict_sp->GetValueForKeyAsArray("values", completions)) {
        completion_dict_sp->GetValueForKeyAsArray("descriptions", descriptions);
        size_t num_completions = completions->GetSize();
        for (size_t idx = 0; idx < num_completions; idx++) {
          auto val = completions->GetItemAtIndexAsString(idx);
          if (!val)
            // FIXME: How do I report this error?
            return;

          if (descriptions) {
            auto desc = descriptions->GetItemAtIndexAsString(idx);
            request.AddCompletion(*val, desc ? *desc : "");
          } else
            request.AddCompletion(*val);
        }
      }
    }

    void
    HandleOptionArgumentCompletion(lldb_private::CompletionRequest &request,
                                   OptionElementVector &option_vec,
                                   int opt_element_index,
                                   CommandInterpreter &interpreter) override {
      ScriptInterpreter *scripter =
          interpreter.GetDebugger().GetScriptInterpreter();

      if (!scripter)
        return;

      ExecutionContext exe_ctx = interpreter.GetExecutionContext();
      PrepareOptionsForCompletion(request, option_vec, &exe_ctx);

      auto defs = GetDefinitions();

      size_t defs_index = option_vec[opt_element_index].opt_defs_index;
      llvm::StringRef option_name = defs[defs_index].long_option;
      bool is_enum = defs[defs_index].enum_values.size() != 0;
      if (option_name.empty())
        return;
      // If this is an enum, we don't call the custom completer, just let the
      // regular option completer handle that:
      StructuredData::DictionarySP completion_dict_sp;
      if (!is_enum)
        completion_dict_sp =
            scripter->HandleOptionArgumentCompletionForScriptedCommand(
                m_cmd_obj_sp, option_name, request.GetCursorCharPos());

      if (!completion_dict_sp) {
        Options::HandleOptionArgumentCompletion(request, option_vec,
                                                opt_element_index, interpreter);
        return;
      }

      ProcessCompletionDict(request, completion_dict_sp);
    }

  private:
    struct EnumValueStorage {
      EnumValueStorage() {
        element.string_value = "value not set";
        element.usage = "usage not set";
        element.value = 0;
      }
      
      EnumValueStorage(std::string in_str_val, std::string in_usage, 
          size_t in_value) : value(std::move(in_str_val)), usage(std::move(in_usage)) {
        SetElement(in_value);
      }
      
      EnumValueStorage(const EnumValueStorage &in) : value(in.value), 
          usage(in.usage) {
        SetElement(in.element.value);
      }
      
      EnumValueStorage &operator=(const EnumValueStorage &in) {
        value = in.value;
        usage = in.usage;
        SetElement(in.element.value);
        return *this;
      }
      
      void SetElement(size_t in_value) {
        element.value = in_value;
        element.string_value = value.data();
        element.usage = usage.data(); 
      }
      
      std::string value;
      std::string usage;
      OptionEnumValueElement element;
    };
    // We have to provide char * values for the long option, usage and enum
    // values, that's what the option definitions hold.
    // The long option strings are quite likely to be reused in other added
    // commands, so those are stored in a global set: g_string_storer.
    // But the usages are much less likely to be reused, so those are stored in
    // a vector in the command instance.  It gets resized to the correct size
    // and then filled with null-terminated strings in the std::string, so the 
    // are valid C-strings that won't move around.
    // The enum values and descriptions are treated similarly - these aren't
    // all that common so it's not worth the effort to dedup them.  
    size_t m_num_options = 0;
    std::unique_ptr<OptionDefinition> m_options_definition_up;
    std::vector<std::vector<EnumValueStorage>> m_enum_storage;
    std::vector<std::vector<OptionEnumValueElement>> m_enum_vector;
    std::vector<std::string> m_usage_container;
    CommandInterpreter &m_interpreter;
    StructuredData::GenericSP m_cmd_obj_sp;
    static std::unordered_set<std::string> g_string_storer;
  };

public:
  static CommandObjectSP Create(CommandInterpreter &interpreter, 
                std::string name,
                StructuredData::GenericSP cmd_obj_sp,
                ScriptedCommandSynchronicity synch, 
                CommandReturnObject &result) {
    CommandObjectSP new_cmd_sp(new CommandObjectScriptingObjectParsed(
        interpreter, name, cmd_obj_sp, synch));

    CommandObjectScriptingObjectParsed *parsed_cmd 
        = static_cast<CommandObjectScriptingObjectParsed *>(new_cmd_sp.get());
    // Now check all the failure modes, and report if found.
    Status opt_error = parsed_cmd->GetOptionsError();
    Status arg_error = parsed_cmd->GetArgsError();

    if (opt_error.Fail())
      result.AppendErrorWithFormat("failed to parse option definitions: %s",
                                   opt_error.AsCString());
    if (arg_error.Fail())
      result.AppendErrorWithFormat("%sfailed to parse argument definitions: %s",
                                   opt_error.Fail() ? ", also " : "", 
                                   arg_error.AsCString());

    if (!result.Succeeded())
      return {};

    return new_cmd_sp;
  }

  CommandObjectScriptingObjectParsed(CommandInterpreter &interpreter,
                               std::string name,
                               StructuredData::GenericSP cmd_obj_sp,
                               ScriptedCommandSynchronicity synch)
      : CommandObjectParsed(interpreter, name.c_str()), 
        m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), 
        m_options(interpreter, cmd_obj_sp), m_fetched_help_short(false), 
        m_fetched_help_long(false) {
    StreamString stream;
    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
    if (!scripter) {
      m_options_error = Status::FromErrorString("No script interpreter");
      return;
    }

    // Set the flags:
    GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));

    // Now set up the options definitions from the options:
    StructuredData::ObjectSP options_object_sp 
        = scripter->GetOptionsForCommandObject(cmd_obj_sp);
    // It's okay not to have an options dict.
    if (options_object_sp) {
      // The options come as a dictionary of dictionaries.  The key of the
      // outer dict is the long option name (since that's required).  The
      // value holds all the other option specification bits.
      StructuredData::Dictionary *options_dict 
          = options_object_sp->GetAsDictionary();
      // but if it exists, it has to be an array.
      if (options_dict) {
        m_options_error = m_options.SetOptionsFromArray(*(options_dict));
        // If we got an error don't bother with the arguments...
        if (m_options_error.Fail())
          return;
      } else {
        m_options_error = Status::FromErrorString("Options array not an array");
        return;
      }
    }
    // Then fetch the args.  Since the arguments can have usage masks you need
    // an array of arrays.
    StructuredData::ObjectSP args_object_sp 
      = scripter->GetArgumentsForCommandObject(cmd_obj_sp);
    if (args_object_sp) {
      StructuredData::Array *args_array = args_object_sp->GetAsArray();        
      if (!args_array) {
        m_args_error =
            Status::FromErrorString("Argument specification is not an array");
        return;
      }
      size_t counter = 0;
      
      // This is the Array::ForEach function that handles the
      // CommandArgumentEntry arrays one by one:
      auto arg_array_adder = [this, &counter] (StructuredData::Object *object) 
          -> bool {
        // This is the Array::ForEach function to add argument entries:
        CommandArgumentEntry this_entry;
        size_t elem_counter = 0;
        auto args_adder = [this, counter, &elem_counter, &this_entry] 
            (StructuredData::Object *object) -> bool {
          // The arguments definition has three fields, the argument type, the
          // repeat and the usage mask. 
          CommandArgumentType arg_type = eArgTypeNone;
          ArgumentRepetitionType arg_repetition = eArgRepeatOptional;
          uint32_t arg_opt_set_association;

          auto report_error = [this, elem_counter,
                               counter](const char *err_txt) -> bool {
            m_args_error = Status::FromErrorStringWithFormatv(
                "Element {0} of arguments "
                "list element {1}: %s.",
                elem_counter, counter, err_txt);
            return false;
          };

          StructuredData::Dictionary *arg_dict = object->GetAsDictionary();
          if (!arg_dict) {
            report_error("is not a dictionary.");
            return false;
          }
          // Argument Type:
          StructuredData::ObjectSP obj_sp 
              = arg_dict->GetValueForKey("arg_type");
          if (obj_sp) {
            StructuredData::UnsignedInteger *uint_val 
                = obj_sp->GetAsUnsignedInteger();
            if (!uint_val) {
              report_error("value type must be an unsigned integer");
              return false;
            }
            uint64_t arg_type_int = uint_val->GetValue();
            if (arg_type_int >= eArgTypeLastArg) {
              report_error("value type beyond ArgumentRepetitionType bounds");
              return false;
            }
            arg_type = (CommandArgumentType) arg_type_int;
          }
          // Repeat Value:
          obj_sp = arg_dict->GetValueForKey("repeat");
          std::optional<ArgumentRepetitionType> repeat;
          if (obj_sp) {
            llvm::StringRef repeat_str = obj_sp->GetStringValue();
            if (repeat_str.empty()) {
              report_error("repeat value is empty");
              return false;
            }
            repeat = ArgRepetitionFromString(repeat_str);
            if (!repeat) {
              report_error("invalid repeat value");
              return false;
            }
            arg_repetition = *repeat;
          } 
          
          // Usage Mask:
          obj_sp = arg_dict->GetValueForKey("groups");
          m_args_error = CommandOptions::ParseUsageMaskFromArray(obj_sp, 
              counter, arg_opt_set_association);
          this_entry.emplace_back(arg_type, arg_repetition, 
              arg_opt_set_association);
          elem_counter++;
          return true;
        };
        StructuredData::Array *args_array = object->GetAsArray();
        if (!args_array) {
          m_args_error =
              Status::FromErrorStringWithFormatv("Argument definition element "
                                                 "{0} is not an array",
                                                 counter);
        }
        
        args_array->ForEach(args_adder);
        if (m_args_error.Fail())
          return false;
        if (this_entry.empty()) {
          m_args_error =
              Status::FromErrorStringWithFormatv("Argument definition element "
                                                 "{0} is empty",
                                                 counter);
          return false;
        }
        m_arguments.push_back(this_entry);
        counter++;
        return true;
      }; // end of arg_array_adder
      // Here we actually parse the args definition:
      args_array->ForEach(arg_array_adder);
    }
  }

  ~CommandObjectScriptingObjectParsed() override = default;

  Status GetOptionsError() { return m_options_error.Clone(); }
  Status GetArgsError() { return m_args_error.Clone(); }
  bool WantsCompletion() override { return true; }

private:
  void PrepareOptionsForCompletion(CompletionRequest &request,
                                   OptionElementVector &option_vec) {
    // First, we have to tell the Scripted side to set the values in its
    // option store, then we call into the handle_completion passing in
    // an array of the args, the arg index and the cursor position in the arg.
    // We want the script side to have a chance to clear its state, so tell
    // it argument parsing has started:
    Options *options = GetOptions();
    // If there are not options, this will be nullptr, and in that case we
    // can just skip setting the options on the scripted side:
    if (options)
      m_options.PrepareOptionsForCompletion(request, option_vec, &m_exe_ctx);
  }

public:
  void HandleArgumentCompletion(CompletionRequest &request,
                                OptionElementVector &option_vec) override {
    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();

    if (!scripter)
      return;

    // Set up the options values on the scripted side:
    PrepareOptionsForCompletion(request, option_vec);

    // Now we have to make up the argument list.
    // The ParseForCompletion only identifies tokens in the m_parsed_line
    // it doesn't remove the options leaving only the args as it does for
    // the regular Parse, so we have to filter out the option ones using the
    // option_element_vector:

    Options *options = GetOptions();
    auto defs = options->GetDefinitions();

    std::unordered_set<size_t> option_slots;
    for (const auto &elem : option_vec) {
      if (elem.opt_defs_index == -1)
        continue;
      option_slots.insert(elem.opt_pos);
      if (defs[elem.opt_defs_index].option_has_arg)
        option_slots.insert(elem.opt_arg_pos);
    }

    std::vector<llvm::StringRef> args_vec;
    Args &args = request.GetParsedLine();
    size_t num_args = args.GetArgumentCount();
    size_t cursor_idx = request.GetCursorIndex();
    size_t args_elem_pos = cursor_idx;

    for (size_t idx = 0; idx < num_args; idx++) {
      if (option_slots.count(idx) == 0)
        args_vec.push_back(args[idx].ref());
      else if (idx < cursor_idx)
        args_elem_pos--;
    }
    StructuredData::DictionarySP completion_dict_sp =
        scripter->HandleArgumentCompletionForScriptedCommand(
            m_cmd_obj_sp, args_vec, args_elem_pos, request.GetCursorCharPos());

    if (!completion_dict_sp) {
      CommandObject::HandleArgumentCompletion(request, option_vec);
      return;
    }

    m_options.ProcessCompletionDict(request, completion_dict_sp);
  }

  bool IsRemovable() const override { return true; }

  ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }

  std::optional<std::string> GetRepeatCommand(Args &args,
                                              uint32_t index) override {
    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
    if (!scripter)
      return std::nullopt;

    return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args);
  }

  llvm::StringRef GetHelp() override {
    if (m_fetched_help_short)
      return CommandObjectParsed::GetHelp();
    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
    if (!scripter)
      return CommandObjectParsed::GetHelp();
    std::string docstring;
    m_fetched_help_short =
        scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
    if (!docstring.empty())
      SetHelp(docstring);

    return CommandObjectParsed::GetHelp();
  }

  llvm::StringRef GetHelpLong() override {
    if (m_fetched_help_long)
      return CommandObjectParsed::GetHelpLong();

    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
    if (!scripter)
      return CommandObjectParsed::GetHelpLong();

    std::string docstring;
    m_fetched_help_long =
        scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
    if (!docstring.empty())
      SetHelpLong(docstring);
    return CommandObjectParsed::GetHelpLong();
  }

  Options *GetOptions() override {
    // CommandObjectParsed requires that a command with no options return
    // nullptr.
    if (m_options.GetNumOptions() == 0)
      return nullptr;
    return &m_options;
  }

protected:
  void DoExecute(Args &args,
                 CommandReturnObject &result) override {
    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();

    Status error;

    result.SetStatus(eReturnStatusInvalid);
    
    if (!scripter ||
        !scripter->RunScriptBasedParsedCommand(m_cmd_obj_sp, args,
                                         m_synchro, result, error, m_exe_ctx)) {
      result.AppendError(error.AsCString());
    } else {
      // Don't change the status if the command already set it...
      if (result.GetStatus() == eReturnStatusInvalid) {
        if (result.GetOutputString().empty())
          result.SetStatus(eReturnStatusSuccessFinishNoResult);
        else
          result.SetStatus(eReturnStatusSuccessFinishResult);
      }
    }
  }

private:
  StructuredData::GenericSP m_cmd_obj_sp;
  ScriptedCommandSynchronicity m_synchro;
  CommandOptions m_options;
  Status m_options_error;
  Status m_args_error;
  bool m_fetched_help_short : 1;
  bool m_fetched_help_long : 1;
};

std::unordered_set<std::string>
    CommandObjectScriptingObjectParsed::CommandOptions::g_string_storer;

// CommandObjectCommandsScriptImport
#define LLDB_OPTIONS_script_import
#include "CommandOptions.inc"

class CommandObjectCommandsScriptImport : public CommandObjectParsed {
public:
  CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "command script import",
                            "Import a scripting module in LLDB.", nullptr) {
    AddSimpleArgumentList(eArgTypeFilename, eArgRepeatPlus);
  }

  ~CommandObjectCommandsScriptImport() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  class CommandOptions : public Options {
  public:
    CommandOptions() = default;

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'r':
        // NO-OP
        break;
      case 'c':
        relative_to_command_file = true;
        break;
      case 's':
        silent = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      relative_to_command_file = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_script_import_options);
    }
    bool relative_to_command_file = false;
    bool silent = false;
  };

  void DoExecute(Args &command, CommandReturnObject &result) override {
    if (command.empty()) {
      result.AppendError("command script import needs one or more arguments");
      return;
    }

    FileSpec source_dir = {};
    if (m_options.relative_to_command_file) {
      source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
      if (!source_dir) {
        result.AppendError("command script import -c can only be specified "
                           "from a command file");
        return;
      }
    }

    for (auto &entry : command.entries()) {
      Status error;

      LoadScriptOptions options;
      options.SetInitSession(true);
      options.SetSilent(m_options.silent);

      // FIXME: this is necessary because CommandObject::CheckRequirements()
      // assumes that commands won't ever be recursively invoked, but it's
      // actually possible to craft a Python script that does other "command
      // script imports" in __lldb_init_module the real fix is to have
      // recursive commands possible with a CommandInvocation object separate
      // from the CommandObject itself, so that recursive command invocations
      // won't stomp on each other (wrt to execution contents, options, and
      // more)
      m_exe_ctx.Clear();
      if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
              entry.c_str(), options, error, /*module_sp=*/nullptr,
              source_dir)) {
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
      } else {
        result.AppendErrorWithFormat("module importing failed: %s",
                                     error.AsCString());
      }
    }
  }

  CommandOptions m_options;
};

#define LLDB_OPTIONS_script_add
#include "CommandOptions.inc"

class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
                                       public IOHandlerDelegateMultiline {
public:
  CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "command script add",
                            "Add a scripted function as an LLDB command.",
                            "Add a scripted function as an lldb command. "
                            "If you provide a single argument, the command "
                            "will be added at the root level of the command "
                            "hierarchy.  If there are more arguments they "
                            "must be a path to a user-added container "
                            "command, and the last element will be the new "
                            "command name."),
        IOHandlerDelegateMultiline("DONE") {
    AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus);
  }

  ~CommandObjectCommandsScriptAdd() override = default;

  Options *GetOptions() override { return &m_options; }

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
                                                      opt_element_vector);
  }

protected:
  class CommandOptions : public Options {
  public:
    CommandOptions() = default;

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'f':
        if (!option_arg.empty())
          m_funct_name = std::string(option_arg);
        break;
      case 'c':
        if (!option_arg.empty())
          m_class_name = std::string(option_arg);
        break;
      case 'h':
        if (!option_arg.empty())
          m_short_help = std::string(option_arg);
        break;
      case 'o':
        m_overwrite_lazy = eLazyBoolYes;
        break;
      case 'p':
        m_parsed_command = true;
        break;
      case 's':
        m_synchronicity =
            (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
                option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
        if (!error.Success())
          return Status::FromErrorStringWithFormat(
              "unrecognized value for synchronicity '%s'",
              option_arg.str().c_str());
        break;
      case 'C': {
        Status error;
        OptionDefinition definition = GetDefinitions()[option_idx];
        lldb::CompletionType completion_type =
            static_cast<lldb::CompletionType>(OptionArgParser::ToOptionEnum(
                option_arg, definition.enum_values, eNoCompletion, error));
        if (!error.Success())
          return Status::FromErrorStringWithFormat(
              "unrecognized value for command completion type '%s'",
              option_arg.str().c_str());
        m_completion_type = completion_type;
      } break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_class_name.clear();
      m_funct_name.clear();
      m_short_help.clear();
      m_completion_type = eNoCompletion;
      m_overwrite_lazy = eLazyBoolCalculate;
      m_synchronicity = eScriptedCommandSynchronicitySynchronous;
      m_parsed_command = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_script_add_options);
    }

    // Instance variables to hold the values for command options.

    std::string m_class_name;
    std::string m_funct_name;
    std::string m_short_help;
    LazyBool m_overwrite_lazy = eLazyBoolCalculate;
    ScriptedCommandSynchronicity m_synchronicity =
        eScriptedCommandSynchronicitySynchronous;
    CompletionType m_completion_type = eNoCompletion;
    bool m_parsed_command = false;
  };

  void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
    if (interactive) {
      if (lldb::LockableStreamFileSP output_sp =
              io_handler.GetOutputStreamFileSP()) {
        LockedStreamFile locked_stream = output_sp->Lock();
        locked_stream.PutCString(g_python_command_instructions);
      }
    }
  }

  void IOHandlerInputComplete(IOHandler &io_handler,
                              std::string &data) override {
    LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP();

    ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
    if (interpreter) {
      StringList lines;
      lines.SplitIntoLines(data);
      if (lines.GetSize() > 0) {
        std::string funct_name_str;
        if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
          if (funct_name_str.empty()) {
            LockedStreamFile locked_stream = error_sp->Lock();
            locked_stream.Printf(
                "error: unable to obtain a function name, didn't "
                "add python command.\n");
          } else {
            // everything should be fine now, let's add this alias

            CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
                m_interpreter, m_cmd_name, funct_name_str, m_short_help,
                m_synchronicity, m_completion_type));
            if (!m_container) {
              Status error = m_interpreter.AddUserCommand(
                  m_cmd_name, command_obj_sp, m_overwrite);
              if (error.Fail()) {
                LockedStreamFile locked_stream = error_sp->Lock();
                locked_stream.Printf(
                    "error: unable to add selected command: '%s'",
                    error.AsCString());
              }
            } else {
              llvm::Error llvm_error = m_container->LoadUserSubcommand(
                  m_cmd_name, command_obj_sp, m_overwrite);
              if (llvm_error) {
                LockedStreamFile locked_stream = error_sp->Lock();
                locked_stream.Printf(
                    "error: unable to add selected command: '%s'",
                    llvm::toString(std::move(llvm_error)).c_str());
              }
            }
          }
        } else {
          LockedStreamFile locked_stream = error_sp->Lock();
          locked_stream.Printf(
              "error: unable to create function, didn't add python command\n");
        }
      } else {
        LockedStreamFile locked_stream = error_sp->Lock();
        locked_stream.Printf(
            "error: empty function, didn't add python command\n");
      }
    } else {
      LockedStreamFile locked_stream = error_sp->Lock();
      locked_stream.Printf(
          "error: script interpreter missing, didn't add python command\n");
    }

    io_handler.SetIsDone(true);
  }

  void DoExecute(Args &command, CommandReturnObject &result) override {
    if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
      result.AppendError("only scripting language supported for scripted "
                         "commands is currently Python");
      return;
    }

    if (command.GetArgumentCount() == 0) {
      result.AppendError("'command script add' requires at least one argument");
      return;
    }
    // Store the options in case we get multi-line input, also figure out the
    // default if not user supplied:
    switch (m_options.m_overwrite_lazy) {
      case eLazyBoolCalculate:
        m_overwrite = !GetDebugger().GetCommandInterpreter().GetRequireCommandOverwrite();
        break;
      case eLazyBoolYes:
        m_overwrite = true;
        break;
      case eLazyBoolNo:
        m_overwrite = false;
    }
    
    Status path_error;
    m_container = GetCommandInterpreter().VerifyUserMultiwordCmdPath(
        command, true, path_error);

    if (path_error.Fail()) {
      result.AppendErrorWithFormat("error in command path: %s",
                                   path_error.AsCString());
      return;
    }

    if (!m_container) {
      // This is getting inserted into the root of the interpreter.
      m_cmd_name = std::string(command[0].ref());
    } else {
      size_t num_args = command.GetArgumentCount();
      m_cmd_name = std::string(command[num_args - 1].ref());
    }

    m_short_help.assign(m_options.m_short_help);
    m_synchronicity = m_options.m_synchronicity;
    m_completion_type = m_options.m_completion_type;

    // Handle the case where we prompt for the script code first:
    if (m_options.m_class_name.empty() && m_options.m_funct_name.empty()) {
      m_interpreter.GetPythonCommandsFromIOHandler("     ", // Prompt
                                                   *this);  // IOHandlerDelegate
      return;
    }

    CommandObjectSP new_cmd_sp;
    if (m_options.m_class_name.empty()) {
      new_cmd_sp.reset(new CommandObjectPythonFunction(
          m_interpreter, m_cmd_name, m_options.m_funct_name,
          m_options.m_short_help, m_synchronicity, m_completion_type));
    } else {
      ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
      if (!interpreter) {
        result.AppendError("cannot find ScriptInterpreter");
        return;
      }

      auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
          m_options.m_class_name.c_str());
      if (!cmd_obj_sp) {
        result.AppendErrorWithFormatv("cannot create helper object for: "
                                      "'{0}'", m_options.m_class_name);
        return;
      }
      
      if (m_options.m_parsed_command) {
        new_cmd_sp = CommandObjectScriptingObjectParsed::Create(m_interpreter, 
            m_cmd_name, cmd_obj_sp, m_synchronicity, result);
        if (!result.Succeeded())
          return;
      } else
        new_cmd_sp.reset(new CommandObjectScriptingObjectRaw(
            m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity,
            m_completion_type));
    }
    
    // Assume we're going to succeed...
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
    if (!m_container) {
      Status add_error =
          m_interpreter.AddUserCommand(m_cmd_name, new_cmd_sp, m_overwrite);
      if (add_error.Fail())
        result.AppendErrorWithFormat("cannot add command: %s",
                                     add_error.AsCString());
    } else {
      llvm::Error llvm_error =
          m_container->LoadUserSubcommand(m_cmd_name, new_cmd_sp, m_overwrite);
      if (llvm_error)
        result.AppendErrorWithFormat(
            "cannot add command: %s",
            llvm::toString(std::move(llvm_error)).c_str());
    }
  }

  CommandOptions m_options;
  std::string m_cmd_name;
  CommandObjectMultiword *m_container = nullptr;
  std::string m_short_help;
  bool m_overwrite = false;
  ScriptedCommandSynchronicity m_synchronicity =
      eScriptedCommandSynchronicitySynchronous;
  CompletionType m_completion_type = eNoCompletion;
};

// CommandObjectCommandsScriptList

class CommandObjectCommandsScriptList : public CommandObjectParsed {
public:
  CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "command script list",
                            "List defined top-level scripted commands.",
                            nullptr) {}

  ~CommandObjectCommandsScriptList() override = default;

  void DoExecute(Args &command, CommandReturnObject &result) override {
    m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);

    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

// CommandObjectCommandsScriptClear

class CommandObjectCommandsScriptClear : public CommandObjectParsed {
public:
  CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "command script clear",
                            "Delete all scripted commands.", nullptr) {}

  ~CommandObjectCommandsScriptClear() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    m_interpreter.RemoveAllUser();

    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

// CommandObjectCommandsScriptDelete

class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
public:
  CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "command script delete",
            "Delete a scripted command by specifying the path to the command.",
            nullptr) {
    AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus);
  }

  ~CommandObjectCommandsScriptDelete() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
        m_interpreter, request, opt_element_vector);
  }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {

    llvm::StringRef root_cmd = command[0].ref();
    size_t num_args = command.GetArgumentCount();

    if (root_cmd.empty()) {
      result.AppendErrorWithFormat("empty root command name");
      return;
    }
    if (!m_interpreter.HasUserCommands() &&
        !m_interpreter.HasUserMultiwordCommands()) {
      result.AppendErrorWithFormat("can only delete user defined commands, "
                                   "but no user defined commands found");
      return;
    }

    CommandObjectSP cmd_sp = m_interpreter.GetCommandSPExact(root_cmd);
    if (!cmd_sp) {
      result.AppendErrorWithFormat("command '%s' not found.",
                                   command[0].c_str());
      return;
    }
    if (!cmd_sp->IsUserCommand()) {
      result.AppendErrorWithFormat("command '%s' is not a user command.",
                                   command[0].c_str());
      return;
    }
    if (cmd_sp->GetAsMultiwordCommand() && num_args == 1) {
      result.AppendErrorWithFormat("command '%s' is a multi-word command.\n "
                                   "Delete with \"command container delete\"",
                                   command[0].c_str());
      return;
    }

    if (command.GetArgumentCount() == 1) {
      m_interpreter.RemoveUser(root_cmd);
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return;
    }
    // We're deleting a command from a multiword command.  Verify the command
    // path:
    Status error;
    CommandObjectMultiword *container =
        GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
                                                           error);
    if (error.Fail()) {
      result.AppendErrorWithFormat("could not resolve command path: %s",
                                   error.AsCString());
      return;
    }
    if (!container) {
      // This means that command only had a leaf command, so the container is
      // the root.  That should have been handled above.
      result.AppendErrorWithFormat("could not find a container for '%s'",
                                   command[0].c_str());
      return;
    }
    const char *leaf_cmd = command[num_args - 1].c_str();
    llvm::Error llvm_error =
        container->RemoveUserSubcommand(leaf_cmd,
                                        /* multiword not okay */ false);
    if (llvm_error) {
      result.AppendErrorWithFormat(
          "could not delete command '%s': %s", leaf_cmd,
          llvm::toString(std::move(llvm_error)).c_str());
      return;
    }

    Stream &out_stream = result.GetOutputStream();

    out_stream << "Deleted command:";
    for (size_t idx = 0; idx < num_args; idx++) {
      out_stream << ' ';
      out_stream << command[idx].c_str();
    }
    out_stream << '\n';
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectMultiwordCommandsScript

// CommandObjectMultiwordCommandsScript

class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
public:
  CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "command script",
            "Commands for managing custom "
            "commands implemented by "
            "interpreter scripts.",
            "command script <subcommand> [<subcommand-options>]") {
    LoadSubCommand("add", CommandObjectSP(
                              new CommandObjectCommandsScriptAdd(interpreter)));
    LoadSubCommand(
        "delete",
        CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
    LoadSubCommand(
        "clear",
        CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
    LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
                               interpreter)));
    LoadSubCommand(
        "import",
        CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
  }

  ~CommandObjectMultiwordCommandsScript() override = default;
};

#pragma mark CommandObjectCommandContainer
#define LLDB_OPTIONS_container_add
#include "CommandOptions.inc"

class CommandObjectCommandsContainerAdd : public CommandObjectParsed {
public:
  CommandObjectCommandsContainerAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "command container add",
            "Add a container command to lldb.  Adding to built-"
            "in container commands is not allowed.",
            "command container add [[path1]...] container-name") {
    AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus);
  }

  ~CommandObjectCommandsContainerAdd() override = default;

  Options *GetOptions() override { return &m_options; }

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
        m_interpreter, request, opt_element_vector);
  }

protected:
  class CommandOptions : public Options {
  public:
    CommandOptions() = default;

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'h':
        if (!option_arg.empty())
          m_short_help = std::string(option_arg);
        break;
      case 'o':
        m_overwrite = true;
        break;
      case 'H':
        if (!option_arg.empty())
          m_long_help = std::string(option_arg);
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_short_help.clear();
      m_long_help.clear();
      m_overwrite = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_container_add_options);
    }

    // Instance variables to hold the values for command options.

    std::string m_short_help;
    std::string m_long_help;
    bool m_overwrite = false;
  };
  void DoExecute(Args &command, CommandReturnObject &result) override {
    size_t num_args = command.GetArgumentCount();

    if (num_args == 0) {
      result.AppendError("no command was specified");
      return;
    }

    if (num_args == 1) {
      // We're adding this as a root command, so use the interpreter.
      const char *cmd_name = command.GetArgumentAtIndex(0);
      auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
          GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
          m_options.m_long_help.c_str()));
      cmd_sp->GetAsMultiwordCommand()->SetRemovable(true);
      Status add_error = GetCommandInterpreter().AddUserCommand(
          cmd_name, cmd_sp, m_options.m_overwrite);
      if (add_error.Fail()) {
        result.AppendErrorWithFormat("error adding command: %s",
                                     add_error.AsCString());
        return;
      }
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return;
    }

    // We're adding this to a subcommand, first find the subcommand:
    Status path_error;
    CommandObjectMultiword *add_to_me =
        GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
                                                           path_error);

    if (!add_to_me) {
      result.AppendErrorWithFormat("error adding command: %s",
                                   path_error.AsCString());
      return;
    }

    const char *cmd_name = command.GetArgumentAtIndex(num_args - 1);
    auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
        GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
        m_options.m_long_help.c_str()));
    llvm::Error llvm_error =
        add_to_me->LoadUserSubcommand(cmd_name, cmd_sp, m_options.m_overwrite);
    if (llvm_error) {
      result.AppendErrorWithFormat("error adding subcommand: %s",
                                   llvm::toString(std::move(llvm_error)).c_str());
      return;
    }

    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }

private:
  CommandOptions m_options;
};

#define LLDB_OPTIONS_multiword_delete
#include "CommandOptions.inc"
class CommandObjectCommandsContainerDelete : public CommandObjectParsed {
public:
  CommandObjectCommandsContainerDelete(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "command container delete",
            "Delete a container command previously added to "
            "lldb.",
            "command container delete [[path1] ...] container-cmd") {
    AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus);
  }

  ~CommandObjectCommandsContainerDelete() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
        m_interpreter, request, opt_element_vector);
  }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    size_t num_args = command.GetArgumentCount();

    if (num_args == 0) {
      result.AppendError("No command was specified.");
      return;
    }

    if (num_args == 1) {
      // We're removing a root command, so we need to delete it from the
      // interpreter.
      const char *cmd_name = command.GetArgumentAtIndex(0);
      // Let's do a little more work here so we can do better error reporting.
      CommandInterpreter &interp = GetCommandInterpreter();
      CommandObjectSP cmd_sp = interp.GetCommandSPExact(cmd_name);
      if (!cmd_sp) {
        result.AppendErrorWithFormat("container command %s doesn't exist.",
                                     cmd_name);
        return;
      }
      if (!cmd_sp->IsUserCommand()) {
        result.AppendErrorWithFormat(
            "container command %s is not a user command", cmd_name);
        return;
      }
      if (!cmd_sp->GetAsMultiwordCommand()) {
        result.AppendErrorWithFormat("command %s is not a container command",
                                     cmd_name);
        return;
      }

      bool did_remove = GetCommandInterpreter().RemoveUserMultiword(cmd_name);
      if (!did_remove) {
        result.AppendErrorWithFormat("error removing command %s.", cmd_name);
        return;
      }

      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return;
    }

    // We're removing a subcommand, first find the subcommand's owner:
    Status path_error;
    CommandObjectMultiword *container =
        GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
                                                           path_error);

    if (!container) {
      result.AppendErrorWithFormat("error removing container command: %s",
                                   path_error.AsCString());
      return;
    }
    const char *leaf = command.GetArgumentAtIndex(num_args - 1);
    llvm::Error llvm_error =
        container->RemoveUserSubcommand(leaf, /* multiword okay */ true);
    if (llvm_error) {
      result.AppendErrorWithFormat("error removing container command: %s",
                                   llvm::toString(std::move(llvm_error)).c_str());
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }
};

class CommandObjectCommandContainer : public CommandObjectMultiword {
public:
  CommandObjectCommandContainer(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "command container",
            "Commands for adding container commands to lldb.  "
            "Container commands are containers for other commands.  You can "
            "add nested container commands by specifying a command path, "
            "but you can't add commands into the built-in command hierarchy.",
            "command container <subcommand> [<subcommand-options>]") {
    LoadSubCommand("add", CommandObjectSP(new CommandObjectCommandsContainerAdd(
                              interpreter)));
    LoadSubCommand(
        "delete",
        CommandObjectSP(new CommandObjectCommandsContainerDelete(interpreter)));
  }

  ~CommandObjectCommandContainer() override = default;
};

#pragma mark CommandObjectMultiwordCommands

// CommandObjectMultiwordCommands

CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "command",
                             "Commands for managing custom LLDB commands.",
                             "command <subcommand> [<subcommand-options>]") {
  LoadSubCommand("source",
                 CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
  LoadSubCommand("alias",
                 CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
  LoadSubCommand("unalias", CommandObjectSP(
                                new CommandObjectCommandsUnalias(interpreter)));
  LoadSubCommand("delete",
                 CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
  LoadSubCommand("container", CommandObjectSP(new CommandObjectCommandContainer(
                                  interpreter)));
  LoadSubCommand(
      "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
  LoadSubCommand(
      "script",
      CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
}

CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
