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

// C Includes
// C++ Includes
#include <mutex>
// Other libraries and framework includes
// Project includes
#include "CommandObjectPlatform.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionValidators.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFile.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Utils.h"

#include "llvm/ADT/SmallString.h"

using namespace lldb;
using namespace lldb_private;

static mode_t ParsePermissionString(const char *) = delete;

static mode_t ParsePermissionString(llvm::StringRef permissions) {
  if (permissions.size() != 9)
    return (mode_t)(-1);
  bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w,
      world_x;

  user_r = (permissions[0] == 'r');
  user_w = (permissions[1] == 'w');
  user_x = (permissions[2] == 'x');

  group_r = (permissions[3] == 'r');
  group_w = (permissions[4] == 'w');
  group_x = (permissions[5] == 'x');

  world_r = (permissions[6] == 'r');
  world_w = (permissions[7] == 'w');
  world_x = (permissions[8] == 'x');

  mode_t user, group, world;
  user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
  group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
  world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);

  return user | group | world;
}

static OptionDefinition g_permissions_options[] = {
    // clang-format off
  {LLDB_OPT_SET_ALL, false, "permissions-value",   'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"},
  {LLDB_OPT_SET_ALL, false, "permissions-string",  's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."},
  {LLDB_OPT_SET_ALL, false, "user-read",           'r', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Allow user to read."},
  {LLDB_OPT_SET_ALL, false, "user-write",          'w', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Allow user to write."},
  {LLDB_OPT_SET_ALL, false, "user-exec",           'x', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Allow user to execute."},
  {LLDB_OPT_SET_ALL, false, "group-read",          'R', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Allow group to read."},
  {LLDB_OPT_SET_ALL, false, "group-write",         'W', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Allow group to write."},
  {LLDB_OPT_SET_ALL, false, "group-exec",          'X', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Allow group to execute."},
  {LLDB_OPT_SET_ALL, false, "world-read",          'd', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Allow world to read."},
  {LLDB_OPT_SET_ALL, false, "world-write",         't', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Allow world to write."},
  {LLDB_OPT_SET_ALL, false, "world-exec",          'e', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Allow world to execute."},
    // clang-format on
};

class OptionPermissions : public OptionGroup {
public:
  OptionPermissions() {}

  ~OptionPermissions() override = default;

  lldb_private::Error
  SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                 ExecutionContext *execution_context) override {
    Error error;
    char short_option = (char)GetDefinitions()[option_idx].short_option;
    switch (short_option) {
    case 'v': {
      if (option_arg.getAsInteger(8, m_permissions)) {
        m_permissions = 0777;
        error.SetErrorStringWithFormat("invalid value for permissions: %s",
                                       option_arg.str().c_str());
      }

    } break;
    case 's': {
      mode_t perms = ParsePermissionString(option_arg);
      if (perms == (mode_t)-1)
        error.SetErrorStringWithFormat("invalid value for permissions: %s",
                                       option_arg.str().c_str());
      else
        m_permissions = perms;
    } break;
    case 'r':
      m_permissions |= lldb::eFilePermissionsUserRead;
      break;
    case 'w':
      m_permissions |= lldb::eFilePermissionsUserWrite;
      break;
    case 'x':
      m_permissions |= lldb::eFilePermissionsUserExecute;
      break;
    case 'R':
      m_permissions |= lldb::eFilePermissionsGroupRead;
      break;
    case 'W':
      m_permissions |= lldb::eFilePermissionsGroupWrite;
      break;
    case 'X':
      m_permissions |= lldb::eFilePermissionsGroupExecute;
      break;
    case 'd':
      m_permissions |= lldb::eFilePermissionsWorldRead;
      break;
    case 't':
      m_permissions |= lldb::eFilePermissionsWorldWrite;
      break;
    case 'e':
      m_permissions |= lldb::eFilePermissionsWorldExecute;
      break;
    default:
      error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
      break;
    }

    return error;
  }

  void OptionParsingStarting(ExecutionContext *execution_context) override {
    m_permissions = 0;
  }

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

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

  uint32_t m_permissions;

private:
  DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
};

//----------------------------------------------------------------------
// "platform select <platform-name>"
//----------------------------------------------------------------------
class CommandObjectPlatformSelect : public CommandObjectParsed {
public:
  CommandObjectPlatformSelect(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform select",
                            "Create a platform if needed and select it as the "
                            "current platform.",
                            "platform select <platform-name>", 0),
        m_option_group(),
        m_platform_options(
            false) // Don't include the "--platform" option by passing false
  {
    m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
    m_option_group.Finalize();
  }

  ~CommandObjectPlatformSelect() override = default;

  int HandleCompletion(Args &input, int &cursor_index,
                       int &cursor_char_position, int match_start_point,
                       int max_return_elements, bool &word_complete,
                       StringList &matches) override {
    std::string completion_str(input.GetArgumentAtIndex(cursor_index));
    completion_str.erase(cursor_char_position);

    CommandCompletions::PlatformPluginNames(
        GetCommandInterpreter(), completion_str.c_str(), match_start_point,
        max_return_elements, nullptr, word_complete, matches);
    return matches.GetSize();
  }

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

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    if (args.GetArgumentCount() == 1) {
      const char *platform_name = args.GetArgumentAtIndex(0);
      if (platform_name && platform_name[0]) {
        const bool select = true;
        m_platform_options.SetPlatformName(platform_name);
        Error error;
        ArchSpec platform_arch;
        PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions(
            m_interpreter, ArchSpec(), select, error, platform_arch));
        if (platform_sp) {
          m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(
              platform_sp);

          platform_sp->GetStatus(result.GetOutputStream());
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          result.AppendError(error.AsCString());
          result.SetStatus(eReturnStatusFailed);
        }
      } else {
        result.AppendError("invalid platform name");
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError(
          "platform create takes a platform name as an argument\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

  OptionGroupOptions m_option_group;
  OptionGroupPlatform m_platform_options;
};

//----------------------------------------------------------------------
// "platform list"
//----------------------------------------------------------------------
class CommandObjectPlatformList : public CommandObjectParsed {
public:
  CommandObjectPlatformList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform list",
                            "List all platforms that are available.", nullptr,
                            0) {}

  ~CommandObjectPlatformList() override = default;

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    Stream &ostrm = result.GetOutputStream();
    ostrm.Printf("Available platforms:\n");

    PlatformSP host_platform_sp(Platform::GetHostPlatform());
    ostrm.Printf("%s: %s\n", host_platform_sp->GetPluginName().GetCString(),
                 host_platform_sp->GetDescription());

    uint32_t idx;
    for (idx = 0; 1; ++idx) {
      const char *plugin_name =
          PluginManager::GetPlatformPluginNameAtIndex(idx);
      if (plugin_name == nullptr)
        break;
      const char *plugin_desc =
          PluginManager::GetPlatformPluginDescriptionAtIndex(idx);
      if (plugin_desc == nullptr)
        break;
      ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
    }

    if (idx == 0) {
      result.AppendError("no platforms are available\n");
      result.SetStatus(eReturnStatusFailed);
    } else
      result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

//----------------------------------------------------------------------
// "platform status"
//----------------------------------------------------------------------
class CommandObjectPlatformStatus : public CommandObjectParsed {
public:
  CommandObjectPlatformStatus(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform status",
                            "Display status for the current platform.", nullptr,
                            0) {}

  ~CommandObjectPlatformStatus() override = default;

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    Stream &ostrm = result.GetOutputStream();

    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    PlatformSP platform_sp;
    if (target) {
      platform_sp = target->GetPlatform();
    }
    if (!platform_sp) {
      platform_sp =
          m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
    }
    if (platform_sp) {
      platform_sp->GetStatus(ostrm);
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendError("no platform us currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

//----------------------------------------------------------------------
// "platform connect <connect-url>"
//----------------------------------------------------------------------
class CommandObjectPlatformConnect : public CommandObjectParsed {
public:
  CommandObjectPlatformConnect(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "platform connect",
            "Select the current platform by providing a connection URL.",
            "platform connect <connect-url>", 0) {}

  ~CommandObjectPlatformConnect() override = default;

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    Stream &ostrm = result.GetOutputStream();

    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      Error error(platform_sp->ConnectRemote(args));
      if (error.Success()) {
        platform_sp->GetStatus(ostrm);
        result.SetStatus(eReturnStatusSuccessFinishResult);

        platform_sp->ConnectToWaitingProcesses(m_interpreter.GetDebugger(),
                                               error);
        if (error.Fail()) {
          result.AppendError(error.AsCString());
          result.SetStatus(eReturnStatusFailed);
        }
      } else {
        result.AppendErrorWithFormat("%s\n", error.AsCString());
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform is currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

  Options *GetOptions() override {
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    OptionGroupOptions *m_platform_options = nullptr;
    if (platform_sp) {
      m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
      if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
        m_platform_options->Finalize();
    }
    return m_platform_options;
  }
};

//----------------------------------------------------------------------
// "platform disconnect"
//----------------------------------------------------------------------
class CommandObjectPlatformDisconnect : public CommandObjectParsed {
public:
  CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform disconnect",
                            "Disconnect from the current platform.",
                            "platform disconnect", 0) {}

  ~CommandObjectPlatformDisconnect() override = default;

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      if (args.GetArgumentCount() == 0) {
        Error error;

        if (platform_sp->IsConnected()) {
          // Cache the instance name if there is one since we are
          // about to disconnect and the name might go with it.
          const char *hostname_cstr = platform_sp->GetHostname();
          std::string hostname;
          if (hostname_cstr)
            hostname.assign(hostname_cstr);

          error = platform_sp->DisconnectRemote();
          if (error.Success()) {
            Stream &ostrm = result.GetOutputStream();
            if (hostname.empty())
              ostrm.Printf("Disconnected from \"%s\"\n",
                           platform_sp->GetPluginName().GetCString());
            else
              ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
            result.SetStatus(eReturnStatusSuccessFinishResult);
          } else {
            result.AppendErrorWithFormat("%s", error.AsCString());
            result.SetStatus(eReturnStatusFailed);
          }
        } else {
          // Not connected...
          result.AppendErrorWithFormat(
              "not connected to '%s'",
              platform_sp->GetPluginName().GetCString());
          result.SetStatus(eReturnStatusFailed);
        }
      } else {
        // Bad args
        result.AppendError(
            "\"platform disconnect\" doesn't take any arguments");
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform is currently selected");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

//----------------------------------------------------------------------
// "platform settings"
//----------------------------------------------------------------------
class CommandObjectPlatformSettings : public CommandObjectParsed {
public:
  CommandObjectPlatformSettings(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform settings",
                            "Set settings for the current target's platform, "
                            "or for a platform by name.",
                            "platform settings", 0),
        m_options(),
        m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', 0,
                             eArgTypePath,
                             "The working directory for the platform.") {
    m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
  }

  ~CommandObjectPlatformSettings() override = default;

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      if (m_option_working_dir.GetOptionValue().OptionWasSet())
        platform_sp->SetWorkingDirectory(
            m_option_working_dir.GetOptionValue().GetCurrentValue());
    } else {
      result.AppendError("no platform is currently selected");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

  Options *GetOptions() override {
    if (!m_options.DidFinalize())
      m_options.Finalize();
    return &m_options;
  }

protected:
  OptionGroupOptions m_options;
  OptionGroupFile m_option_working_dir;
};

//----------------------------------------------------------------------
// "platform mkdir"
//----------------------------------------------------------------------
class CommandObjectPlatformMkDir : public CommandObjectParsed {
public:
  CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform mkdir",
                            "Make a new directory on the remote end.", nullptr,
                            0),
        m_options() {}

  ~CommandObjectPlatformMkDir() override = default;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      std::string cmd_line;
      args.GetCommandString(cmd_line);
      uint32_t mode;
      const OptionPermissions *options_permissions =
          (const OptionPermissions *)m_options.GetGroupWithOption('r');
      if (options_permissions)
        mode = options_permissions->m_permissions;
      else
        mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
               lldb::eFilePermissionsWorldRX;
      Error error = platform_sp->MakeDirectory(FileSpec{cmd_line, false}, mode);
      if (error.Success()) {
        result.SetStatus(eReturnStatusSuccessFinishResult);
      } else {
        result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

  Options *GetOptions() override {
    if (!m_options.DidFinalize()) {
      m_options.Append(new OptionPermissions());
      m_options.Finalize();
    }
    return &m_options;
  }

  OptionGroupOptions m_options;
};

//----------------------------------------------------------------------
// "platform fopen"
//----------------------------------------------------------------------
class CommandObjectPlatformFOpen : public CommandObjectParsed {
public:
  CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform file open",
                            "Open a file on the remote end.", nullptr, 0),
        m_options() {}

  ~CommandObjectPlatformFOpen() override = default;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      Error error;
      std::string cmd_line;
      args.GetCommandString(cmd_line);
      mode_t perms;
      const OptionPermissions *options_permissions =
          (const OptionPermissions *)m_options.GetGroupWithOption('r');
      if (options_permissions)
        perms = options_permissions->m_permissions;
      else
        perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
                lldb::eFilePermissionsWorldRead;
      lldb::user_id_t fd = platform_sp->OpenFile(
          FileSpec(cmd_line, false),
          File::eOpenOptionRead | File::eOpenOptionWrite |
              File::eOpenOptionAppend | File::eOpenOptionCanCreate,
          perms, error);
      if (error.Success()) {
        result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd);
        result.SetStatus(eReturnStatusSuccessFinishResult);
      } else {
        result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

  Options *GetOptions() override {
    if (!m_options.DidFinalize()) {
      m_options.Append(new OptionPermissions());
      m_options.Finalize();
    }
    return &m_options;
  }

  OptionGroupOptions m_options;
};

//----------------------------------------------------------------------
// "platform fclose"
//----------------------------------------------------------------------
class CommandObjectPlatformFClose : public CommandObjectParsed {
public:
  CommandObjectPlatformFClose(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform file close",
                            "Close a file on the remote end.", nullptr, 0) {}

  ~CommandObjectPlatformFClose() override = default;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      std::string cmd_line;
      args.GetCommandString(cmd_line);
      const lldb::user_id_t fd =
          StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
      Error error;
      bool success = platform_sp->CloseFile(fd, error);
      if (success) {
        result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
        result.SetStatus(eReturnStatusSuccessFinishResult);
      } else {
        result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

//----------------------------------------------------------------------
// "platform fread"
//----------------------------------------------------------------------

static OptionDefinition g_platform_fread_options[] = {
    // clang-format off
  { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
  { LLDB_OPT_SET_1, false, "count",  'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Number of bytes to read from the file." },
    // clang-format on
};

class CommandObjectPlatformFRead : public CommandObjectParsed {
public:
  CommandObjectPlatformFRead(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform file read",
                            "Read data from a file on the remote end.", nullptr,
                            0),
        m_options() {}

  ~CommandObjectPlatformFRead() override = default;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      std::string cmd_line;
      args.GetCommandString(cmd_line);
      const lldb::user_id_t fd =
          StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
      std::string buffer(m_options.m_count, 0);
      Error error;
      uint32_t retcode = platform_sp->ReadFile(
          fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
      result.AppendMessageWithFormat("Return = %d\n", retcode);
      result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendError("no platform currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

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

protected:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

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

      switch (short_option) {
      case 'o':
        if (option_arg.getAsInteger(0, m_offset))
          error.SetErrorStringWithFormat("invalid offset: '%s'",
                                         option_arg.str().c_str());
        break;
      case 'c':
        if (option_arg.getAsInteger(0, m_count))
          error.SetErrorStringWithFormat("invalid offset: '%s'",
                                         option_arg.str().c_str());
        break;
      default:
        error.SetErrorStringWithFormat("unrecognized option '%c'",
                                       short_option);
        break;
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_offset = 0;
      m_count = 1;
    }

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

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

    uint32_t m_offset;
    uint32_t m_count;
  };

  CommandOptions m_options;
};

//----------------------------------------------------------------------
// "platform fwrite"
//----------------------------------------------------------------------

static OptionDefinition g_platform_fwrite_options[] = {
    // clang-format off
  { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
  { LLDB_OPT_SET_1, false, "data",   'd', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Text to write to the file." },
    // clang-format on
};

class CommandObjectPlatformFWrite : public CommandObjectParsed {
public:
  CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform file write",
                            "Write data to a file on the remote end.", nullptr,
                            0),
        m_options() {}

  ~CommandObjectPlatformFWrite() override = default;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      std::string cmd_line;
      args.GetCommandString(cmd_line);
      Error error;
      const lldb::user_id_t fd =
          StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
      uint32_t retcode =
          platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
                                 m_options.m_data.size(), error);
      result.AppendMessageWithFormat("Return = %d\n", retcode);
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendError("no platform currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

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

protected:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

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

      switch (short_option) {
      case 'o':
        if (option_arg.getAsInteger(0, m_offset))
          error.SetErrorStringWithFormat("invalid offset: '%s'",
                                         option_arg.str().c_str());
        break;
      case 'd':
        m_data.assign(option_arg);
        break;
      default:
        error.SetErrorStringWithFormat("unrecognized option '%c'",
                                       short_option);
        break;
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_offset = 0;
      m_data.clear();
    }

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

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

    uint32_t m_offset;
    std::string m_data;
  };

  CommandOptions m_options;
};

class CommandObjectPlatformFile : public CommandObjectMultiword {
public:
  //------------------------------------------------------------------
  // Constructors and Destructors
  //------------------------------------------------------------------
  CommandObjectPlatformFile(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "platform file",
            "Commands to access files on the current platform.",
            "platform file [open|close|read|write] ...") {
    LoadSubCommand(
        "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
    LoadSubCommand(
        "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
    LoadSubCommand(
        "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
    LoadSubCommand(
        "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
  }

  ~CommandObjectPlatformFile() override = default;

private:
  //------------------------------------------------------------------
  // For CommandObjectPlatform only
  //------------------------------------------------------------------
  DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformFile);
};

//----------------------------------------------------------------------
// "platform get-file remote-file-path host-file-path"
//----------------------------------------------------------------------
class CommandObjectPlatformGetFile : public CommandObjectParsed {
public:
  CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "platform get-file",
            "Transfer a file from the remote end to the local host.",
            "platform get-file <remote-file-spec> <local-file-spec>", 0) {
    SetHelpLong(
        R"(Examples:

(lldb) platform get-file /the/remote/file/path /the/local/file/path

    Transfer a file from the remote end with file path /the/remote/file/path to the local host.)");

    CommandArgumentEntry arg1, arg2;
    CommandArgumentData file_arg_remote, file_arg_host;

    // Define the first (and only) variant of this arg.
    file_arg_remote.arg_type = eArgTypeFilename;
    file_arg_remote.arg_repetition = eArgRepeatPlain;
    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg1.push_back(file_arg_remote);

    // Define the second (and only) variant of this arg.
    file_arg_host.arg_type = eArgTypeFilename;
    file_arg_host.arg_repetition = eArgRepeatPlain;
    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg2.push_back(file_arg_host);

    // Push the data for the first and the second arguments into the m_arguments
    // vector.
    m_arguments.push_back(arg1);
    m_arguments.push_back(arg2);
  }

  ~CommandObjectPlatformGetFile() override = default;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    // If the number of arguments is incorrect, issue an error message.
    if (args.GetArgumentCount() != 2) {
      result.GetErrorStream().Printf("error: required arguments missing; "
                                     "specify both the source and destination "
                                     "file paths\n");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      const char *remote_file_path = args.GetArgumentAtIndex(0);
      const char *local_file_path = args.GetArgumentAtIndex(1);
      Error error = platform_sp->GetFile(FileSpec(remote_file_path, false),
                                         FileSpec(local_file_path, false));
      if (error.Success()) {
        result.AppendMessageWithFormat(
            "successfully get-file from %s (remote) to %s (host)\n",
            remote_file_path, local_file_path);
        result.SetStatus(eReturnStatusSuccessFinishResult);
      } else {
        result.AppendMessageWithFormat("get-file failed: %s\n",
                                       error.AsCString());
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

//----------------------------------------------------------------------
// "platform get-size remote-file-path"
//----------------------------------------------------------------------
class CommandObjectPlatformGetSize : public CommandObjectParsed {
public:
  CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform get-size",
                            "Get the file size from the remote end.",
                            "platform get-size <remote-file-spec>", 0) {
    SetHelpLong(
        R"(Examples:

(lldb) platform get-size /the/remote/file/path

    Get the file size from the remote end with path /the/remote/file/path.)");

    CommandArgumentEntry arg1;
    CommandArgumentData file_arg_remote;

    // Define the first (and only) variant of this arg.
    file_arg_remote.arg_type = eArgTypeFilename;
    file_arg_remote.arg_repetition = eArgRepeatPlain;
    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg1.push_back(file_arg_remote);

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

  ~CommandObjectPlatformGetSize() override = default;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    // If the number of arguments is incorrect, issue an error message.
    if (args.GetArgumentCount() != 1) {
      result.GetErrorStream().Printf("error: required argument missing; "
                                     "specify the source file path as the only "
                                     "argument\n");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      std::string remote_file_path(args.GetArgumentAtIndex(0));
      user_id_t size =
          platform_sp->GetFileSize(FileSpec(remote_file_path, false));
      if (size != UINT64_MAX) {
        result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
                                       "\n",
                                       remote_file_path.c_str(), size);
        result.SetStatus(eReturnStatusSuccessFinishResult);
      } else {
        result.AppendMessageWithFormat(
            "Error getting file size of %s (remote)\n",
            remote_file_path.c_str());
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

//----------------------------------------------------------------------
// "platform put-file"
//----------------------------------------------------------------------
class CommandObjectPlatformPutFile : public CommandObjectParsed {
public:
  CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "platform put-file",
            "Transfer a file from this system to the remote end.", nullptr, 0) {
  }

  ~CommandObjectPlatformPutFile() override = default;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    const char *src = args.GetArgumentAtIndex(0);
    const char *dst = args.GetArgumentAtIndex(1);

    FileSpec src_fs(src, true);
    FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString(), false);

    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      Error error(platform_sp->PutFile(src_fs, dst_fs));
      if (error.Success()) {
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
      } else {
        result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform currently selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

//----------------------------------------------------------------------
// "platform process launch"
//----------------------------------------------------------------------
class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
public:
  CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform process launch",
                            "Launch a new process on a remote platform.",
                            "platform process launch program",
                            eCommandRequiresTarget | eCommandTryTargetAPILock),
        m_options() {}

  ~CommandObjectPlatformProcessLaunch() override = default;

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

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    PlatformSP platform_sp;
    if (target) {
      platform_sp = target->GetPlatform();
    }
    if (!platform_sp) {
      platform_sp =
          m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
    }

    if (platform_sp) {
      Error error;
      const size_t argc = args.GetArgumentCount();
      Target *target = m_exe_ctx.GetTargetPtr();
      Module *exe_module = target->GetExecutableModulePointer();
      if (exe_module) {
        m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
        llvm::SmallString<PATH_MAX> exe_path;
        m_options.launch_info.GetExecutableFile().GetPath(exe_path);
        if (!exe_path.empty())
          m_options.launch_info.GetArguments().AppendArgument(exe_path);
        m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
      }

      if (argc > 0) {
        if (m_options.launch_info.GetExecutableFile()) {
          // We already have an executable file, so we will use this
          // and all arguments to this function are extra arguments
          m_options.launch_info.GetArguments().AppendArguments(args);
        } else {
          // We don't have any file yet, so the first argument is our
          // executable, and the rest are program arguments
          const bool first_arg_is_executable = true;
          m_options.launch_info.SetArguments(args, first_arg_is_executable);
        }
      }

      if (m_options.launch_info.GetExecutableFile()) {
        Debugger &debugger = m_interpreter.GetDebugger();

        if (argc == 0)
          target->GetRunArguments(m_options.launch_info.GetArguments());

        ProcessSP process_sp(platform_sp->DebugProcess(
            m_options.launch_info, debugger, target, error));
        if (process_sp && process_sp->IsAlive()) {
          result.SetStatus(eReturnStatusSuccessFinishNoResult);
          return true;
        }

        if (error.Success())
          result.AppendError("process launch failed");
        else
          result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
      } else {
        result.AppendError("'platform process launch' uses the current target "
                           "file and arguments, or the executable and its "
                           "arguments can be specified in this command");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    } else {
      result.AppendError("no platform is selected\n");
    }
    return result.Succeeded();
  }

protected:
  ProcessLaunchCommandOptions m_options;
};

//----------------------------------------------------------------------
// "platform process list"
//----------------------------------------------------------------------

OptionDefinition g_platform_process_list_options[] = {
    // clang-format off
  { LLDB_OPT_SET_1,             false, "pid",         'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid,               "List the process info for a specific process ID." },
  { LLDB_OPT_SET_2,             true,  "name",        'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName,       "Find processes with executable basenames that match a string." },
  { LLDB_OPT_SET_3,             true,  "ends-with",   'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName,       "Find processes with executable basenames that end with a string." },
  { LLDB_OPT_SET_4,             true,  "starts-with", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName,       "Find processes with executable basenames that start with a string." },
  { LLDB_OPT_SET_5,             true,  "contains",    'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName,       "Find processes with executable basenames that contain a string." },
  { LLDB_OPT_SET_6,             true,  "regex",       'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
  { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent",      'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid,               "Find processes that have a matching parent process ID." },
  { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid",         'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger,   "Find processes that have a matching user ID." },
  { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid",        'U', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger,   "Find processes that have a matching effective user ID." },
  { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid",         'g', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger,   "Find processes that have a matching group ID." },
  { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid",        'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger,   "Find processes that have a matching effective group ID." },
  { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch",        'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture,      "Find processes that have a matching architecture." },
  { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args",   'A', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Show process arguments instead of the process executable basename." },
  { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose",     'v', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,              "Enable verbose output." },
    // clang-format on
};

class CommandObjectPlatformProcessList : public CommandObjectParsed {
public:
  CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform process list",
                            "List processes on a remote platform by name, pid, "
                            "or many other matching attributes.",
                            "platform process list", 0),
        m_options() {}

  ~CommandObjectPlatformProcessList() override = default;

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

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    PlatformSP platform_sp;
    if (target) {
      platform_sp = target->GetPlatform();
    }
    if (!platform_sp) {
      platform_sp =
          m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
    }

    if (platform_sp) {
      Error error;
      if (args.GetArgumentCount() == 0) {
        if (platform_sp) {
          Stream &ostrm = result.GetOutputStream();

          lldb::pid_t pid =
              m_options.match_info.GetProcessInfo().GetProcessID();
          if (pid != LLDB_INVALID_PROCESS_ID) {
            ProcessInstanceInfo proc_info;
            if (platform_sp->GetProcessInfo(pid, proc_info)) {
              ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(),
                                                   m_options.show_args,
                                                   m_options.verbose);
              proc_info.DumpAsTableRow(ostrm, platform_sp.get(),
                                       m_options.show_args, m_options.verbose);
              result.SetStatus(eReturnStatusSuccessFinishResult);
            } else {
              result.AppendErrorWithFormat(
                  "no process found with pid = %" PRIu64 "\n", pid);
              result.SetStatus(eReturnStatusFailed);
            }
          } else {
            ProcessInstanceInfoList proc_infos;
            const uint32_t matches =
                platform_sp->FindProcesses(m_options.match_info, proc_infos);
            const char *match_desc = nullptr;
            const char *match_name =
                m_options.match_info.GetProcessInfo().GetName();
            if (match_name && match_name[0]) {
              switch (m_options.match_info.GetNameMatchType()) {
              case eNameMatchIgnore:
                break;
              case eNameMatchEquals:
                match_desc = "matched";
                break;
              case eNameMatchContains:
                match_desc = "contained";
                break;
              case eNameMatchStartsWith:
                match_desc = "started with";
                break;
              case eNameMatchEndsWith:
                match_desc = "ended with";
                break;
              case eNameMatchRegularExpression:
                match_desc = "matched the regular expression";
                break;
              }
            }

            if (matches == 0) {
              if (match_desc)
                result.AppendErrorWithFormat(
                    "no processes were found that %s \"%s\" on the \"%s\" "
                    "platform\n",
                    match_desc, match_name,
                    platform_sp->GetPluginName().GetCString());
              else
                result.AppendErrorWithFormat(
                    "no processes were found on the \"%s\" platform\n",
                    platform_sp->GetPluginName().GetCString());
              result.SetStatus(eReturnStatusFailed);
            } else {
              result.AppendMessageWithFormat(
                  "%u matching process%s found on \"%s\"", matches,
                  matches > 1 ? "es were" : " was",
                  platform_sp->GetName().GetCString());
              if (match_desc)
                result.AppendMessageWithFormat(" whose name %s \"%s\"",
                                               match_desc, match_name);
              result.AppendMessageWithFormat("\n");
              ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(),
                                                   m_options.show_args,
                                                   m_options.verbose);
              for (uint32_t i = 0; i < matches; ++i) {
                proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(
                    ostrm, platform_sp.get(), m_options.show_args,
                    m_options.verbose);
              }
            }
          }
        }
      } else {
        result.AppendError("invalid args: process list takes only options\n");
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform is selected\n");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

  class CommandOptions : public Options {
  public:
    CommandOptions()
        : Options(), match_info(), show_args(false), verbose(false) {
      static std::once_flag g_once_flag;
      std::call_once(g_once_flag, []() {
        PosixPlatformCommandOptionValidator *posix_validator =
            new PosixPlatformCommandOptionValidator();
        for (auto &Option : g_platform_process_list_options) {
          switch (Option.short_option) {
          case 'u':
          case 'U':
          case 'g':
          case 'G':
            Option.validator = posix_validator;
            break;
          default:
            break;
          }
        }
      });
    }

    ~CommandOptions() override = default;

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

      uint32_t id = LLDB_INVALID_PROCESS_ID;
      success = !option_arg.getAsInteger(0, id);
      switch (short_option) {
      case 'p': {
        match_info.GetProcessInfo().SetProcessID(id);
        if (!success)
          error.SetErrorStringWithFormat("invalid process ID string: '%s'",
                                         option_arg.str().c_str());
        break;
      }
      case 'P':
        match_info.GetProcessInfo().SetParentProcessID(id);
        if (!success)
          error.SetErrorStringWithFormat(
              "invalid parent process ID string: '%s'",
              option_arg.str().c_str());
        break;

      case 'u':
        match_info.GetProcessInfo().SetUserID(success ? id : UINT32_MAX);
        if (!success)
          error.SetErrorStringWithFormat("invalid user ID string: '%s'",
                                         option_arg.str().c_str());
        break;

      case 'U':
        match_info.GetProcessInfo().SetEffectiveUserID(success ? id
                                                               : UINT32_MAX);
        if (!success)
          error.SetErrorStringWithFormat(
              "invalid effective user ID string: '%s'",
              option_arg.str().c_str());
        break;

      case 'g':
        match_info.GetProcessInfo().SetGroupID(success ? id : UINT32_MAX);
        if (!success)
          error.SetErrorStringWithFormat("invalid group ID string: '%s'",
                                         option_arg.str().c_str());
        break;

      case 'G':
        match_info.GetProcessInfo().SetEffectiveGroupID(success ? id
                                                                : UINT32_MAX);
        if (!success)
          error.SetErrorStringWithFormat(
              "invalid effective group ID string: '%s'",
              option_arg.str().c_str());
        break;

      case 'a': {
        TargetSP target_sp =
            execution_context ? execution_context->GetTargetSP() : TargetSP();
        DebuggerSP debugger_sp =
            target_sp ? target_sp->GetDebugger().shared_from_this()
                      : DebuggerSP();
        PlatformSP platform_sp =
            debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
                        : PlatformSP();
        match_info.GetProcessInfo().GetArchitecture().SetTriple(
            option_arg, platform_sp.get());
      } break;

      case 'n':
        match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
                                                                false);
        match_info.SetNameMatchType(eNameMatchEquals);
        break;

      case 'e':
        match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
                                                                false);
        match_info.SetNameMatchType(eNameMatchEndsWith);
        break;

      case 's':
        match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
                                                                false);
        match_info.SetNameMatchType(eNameMatchStartsWith);
        break;

      case 'c':
        match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
                                                                false);
        match_info.SetNameMatchType(eNameMatchContains);
        break;

      case 'r':
        match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
                                                                false);
        match_info.SetNameMatchType(eNameMatchRegularExpression);
        break;

      case 'A':
        show_args = true;
        break;

      case 'v':
        verbose = true;
        break;

      default:
        error.SetErrorStringWithFormat("unrecognized option '%c'",
                                       short_option);
        break;
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      match_info.Clear();
      show_args = false;
      verbose = false;
    }

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

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

    ProcessInstanceInfoMatch match_info;
    bool show_args;
    bool verbose;
  };

  CommandOptions m_options;
};

//----------------------------------------------------------------------
// "platform process info"
//----------------------------------------------------------------------
class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
public:
  CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "platform process info",
            "Get detailed information for one or more process by process ID.",
            "platform process info <pid> [<pid> <pid> ...]", 0) {
    CommandArgumentEntry arg;
    CommandArgumentData pid_args;

    // Define the first (and only) variant of this arg.
    pid_args.arg_type = eArgTypePid;
    pid_args.arg_repetition = eArgRepeatStar;

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

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

  ~CommandObjectPlatformProcessInfo() override = default;

protected:
  bool DoExecute(Args &args, CommandReturnObject &result) override {
    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    PlatformSP platform_sp;
    if (target) {
      platform_sp = target->GetPlatform();
    }
    if (!platform_sp) {
      platform_sp =
          m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
    }

    if (platform_sp) {
      const size_t argc = args.GetArgumentCount();
      if (argc > 0) {
        Error error;

        if (platform_sp->IsConnected()) {
          Stream &ostrm = result.GetOutputStream();
          for (auto &entry : args.entries()) {
            lldb::pid_t pid;
            if (entry.ref.getAsInteger(0, pid)) {
              result.AppendErrorWithFormat("invalid process ID argument '%s'",
                                           entry.ref.str().c_str());
              result.SetStatus(eReturnStatusFailed);
              break;
            } else {
              ProcessInstanceInfo proc_info;
              if (platform_sp->GetProcessInfo(pid, proc_info)) {
                ostrm.Printf("Process information for process %" PRIu64 ":\n",
                             pid);
                proc_info.Dump(ostrm, platform_sp.get());
              } else {
                ostrm.Printf("error: no process information is available for "
                             "process %" PRIu64 "\n",
                             pid);
              }
              ostrm.EOL();
            }
          }
        } else {
          // Not connected...
          result.AppendErrorWithFormat(
              "not connected to '%s'",
              platform_sp->GetPluginName().GetCString());
          result.SetStatus(eReturnStatusFailed);
        }
      } else {
        // No args
        result.AppendError("one or more process id(s) must be specified");
        result.SetStatus(eReturnStatusFailed);
      }
    } else {
      result.AppendError("no platform is currently selected");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

static OptionDefinition g_platform_process_attach_options[] = {
    // clang-format off
  { LLDB_OPT_SET_ALL, false, "plugin",  'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin,      "Name of the process plugin you want to use." },
  { LLDB_OPT_SET_1,   false, "pid",     'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid,         "The process ID of an existing process to attach to." },
  { LLDB_OPT_SET_2,   false, "name",    'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to." },
  { LLDB_OPT_SET_2,   false, "waitfor", 'w', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,        "Wait for the process with <process-name> to launch." },
    // clang-format on
};

class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {
      // Keep default values of all options in one place: OptionParsingStarting
      // ()
      OptionParsingStarting(nullptr);
    }

    ~CommandOptions() override = default;

    Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                         ExecutionContext *execution_context) override {
      Error error;
      char short_option = (char)m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'p': {
        lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
        if (option_arg.getAsInteger(0, pid)) {
          error.SetErrorStringWithFormat("invalid process ID '%s'",
                                         option_arg.str().c_str());
        } else {
          attach_info.SetProcessID(pid);
        }
      } break;

      case 'P':
        attach_info.SetProcessPluginName(option_arg);
        break;

      case 'n':
        attach_info.GetExecutableFile().SetFile(option_arg, false);
        break;

      case 'w':
        attach_info.SetWaitForLaunch(true);
        break;

      default:
        error.SetErrorStringWithFormat("invalid short option character '%c'",
                                       short_option);
        break;
      }
      return error;
    }

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

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

    bool HandleOptionArgumentCompletion(
        Args &input, int cursor_index, int char_pos,
        OptionElementVector &opt_element_vector, int opt_element_index,
        int match_start_point, int max_return_elements,
        CommandInterpreter &interpreter, bool &word_complete,
        StringList &matches) override {
      int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
      int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;

      // We are only completing the name option for now...

      if (GetDefinitions()[opt_defs_index].short_option == 'n') {
        // Are we in the name?

        // Look to see if there is a -P argument provided, and if so use that
        // plugin, otherwise
        // use the default plugin.

        const char *partial_name = nullptr;
        partial_name = input.GetArgumentAtIndex(opt_arg_pos);

        PlatformSP platform_sp(interpreter.GetPlatform(true));
        if (platform_sp) {
          ProcessInstanceInfoList process_infos;
          ProcessInstanceInfoMatch match_info;
          if (partial_name) {
            match_info.GetProcessInfo().GetExecutableFile().SetFile(
                partial_name, false);
            match_info.SetNameMatchType(eNameMatchStartsWith);
          }
          platform_sp->FindProcesses(match_info, process_infos);
          const uint32_t num_matches = process_infos.GetSize();
          if (num_matches > 0) {
            for (uint32_t i = 0; i < num_matches; ++i) {
              matches.AppendString(
                  process_infos.GetProcessNameAtIndex(i),
                  process_infos.GetProcessNameLengthAtIndex(i));
            }
          }
        }
      }

      return false;
    }

    // Options table: Required for subclasses of Options.

    static OptionDefinition g_option_table[];

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

    ProcessAttachInfo attach_info;
  };

  CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "platform process attach",
                            "Attach to a process.",
                            "platform process attach <cmd-options>"),
        m_options() {}

  ~CommandObjectPlatformProcessAttach() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (platform_sp) {
      Error err;
      ProcessSP remote_process_sp = platform_sp->Attach(
          m_options.attach_info, m_interpreter.GetDebugger(), nullptr, err);
      if (err.Fail()) {
        result.AppendError(err.AsCString());
        result.SetStatus(eReturnStatusFailed);
      } else if (!remote_process_sp) {
        result.AppendError("could not attach: unknown reason");
        result.SetStatus(eReturnStatusFailed);
      } else
        result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendError("no platform is currently selected");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

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

protected:
  CommandOptions m_options;
};

class CommandObjectPlatformProcess : public CommandObjectMultiword {
public:
  //------------------------------------------------------------------
  // Constructors and Destructors
  //------------------------------------------------------------------
  CommandObjectPlatformProcess(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "platform process",
                               "Commands to query, launch and attach to "
                               "processes on the current platform.",
                               "platform process [attach|launch|list] ...") {
    LoadSubCommand(
        "attach",
        CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter)));
    LoadSubCommand(
        "launch",
        CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter)));
    LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
                               interpreter)));
    LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
                               interpreter)));
  }

  ~CommandObjectPlatformProcess() override = default;

private:
  //------------------------------------------------------------------
  // For CommandObjectPlatform only
  //------------------------------------------------------------------
  DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformProcess);
};

//----------------------------------------------------------------------
// "platform shell"
//----------------------------------------------------------------------
static OptionDefinition g_platform_shell_options[] = {
    // clang-format off
  { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command." },
    // clang-format on
};

class CommandObjectPlatformShell : public CommandObjectRaw {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options(), timeout(10) {}

    ~CommandOptions() override = default;

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

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

      const char short_option = (char)GetDefinitions()[option_idx].short_option;

      switch (short_option) {
      case 't':
        timeout = 10;
        if (option_arg.getAsInteger(10, timeout))
          error.SetErrorStringWithFormat(
              "could not convert \"%s\" to a numeric value.",
              option_arg.str().c_str());
        break;
      default:
        error.SetErrorStringWithFormat("invalid short option character '%c'",
                                       short_option);
        break;
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {}

    uint32_t timeout;
  };

  CommandObjectPlatformShell(CommandInterpreter &interpreter)
      : CommandObjectRaw(interpreter, "platform shell",
                         "Run a shell command on the current platform.",
                         "platform shell <shell-command>", 0),
        m_options() {}

  ~CommandObjectPlatformShell() override = default;

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

  bool DoExecute(const char *raw_command_line,
                 CommandReturnObject &result) override {
    ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
    m_options.NotifyOptionParsingStarting(&exe_ctx);

    const char *expr = nullptr;

    // Print out an usage syntax on an empty command line.
    if (raw_command_line[0] == '\0') {
      result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
      return true;
    }

    if (raw_command_line[0] == '-') {
      // We have some options and these options MUST end with --.
      const char *end_options = nullptr;
      const char *s = raw_command_line;
      while (s && s[0]) {
        end_options = ::strstr(s, "--");
        if (end_options) {
          end_options += 2; // Get past the "--"
          if (::isspace(end_options[0])) {
            expr = end_options;
            while (::isspace(*expr))
              ++expr;
            break;
          }
        }
        s = end_options;
      }

      if (end_options) {
        Args args(
            llvm::StringRef(raw_command_line, end_options - raw_command_line));
        if (!ParseOptions(args, result))
          return false;
      }
    }

    if (expr == nullptr)
      expr = raw_command_line;

    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    Error error;
    if (platform_sp) {
      FileSpec working_dir{};
      std::string output;
      int status = -1;
      int signo = -1;
      error = (platform_sp->RunShellCommand(expr, working_dir, &status, &signo,
                                            &output, m_options.timeout));
      if (!output.empty())
        result.GetOutputStream().PutCString(output);
      if (status > 0) {
        if (signo > 0) {
          const char *signo_cstr = Host::GetSignalAsCString(signo);
          if (signo_cstr)
            result.GetOutputStream().Printf(
                "error: command returned with status %i and signal %s\n",
                status, signo_cstr);
          else
            result.GetOutputStream().Printf(
                "error: command returned with status %i and signal %i\n",
                status, signo);
        } else
          result.GetOutputStream().Printf(
              "error: command returned with status %i\n", status);
      }
    } else {
      result.GetOutputStream().Printf(
          "error: cannot run remote shell commands without a platform\n");
      error.SetErrorString(
          "error: cannot run remote shell commands without a platform");
    }

    if (error.Fail()) {
      result.AppendError(error.AsCString());
      result.SetStatus(eReturnStatusFailed);
    } else {
      result.SetStatus(eReturnStatusSuccessFinishResult);
    }
    return true;
  }

  CommandOptions m_options;
};

//----------------------------------------------------------------------
// "platform install" - install a target to a remote end
//----------------------------------------------------------------------
class CommandObjectPlatformInstall : public CommandObjectParsed {
public:
  CommandObjectPlatformInstall(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "platform target-install",
            "Install a target (bundle or executable file) to the remote end.",
            "platform target-install <local-thing> <remote-sandbox>", 0) {}

  ~CommandObjectPlatformInstall() override = default;

  bool DoExecute(Args &args, CommandReturnObject &result) override {
    if (args.GetArgumentCount() != 2) {
      result.AppendError("platform target-install takes two arguments");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
    // TODO: move the bulk of this code over to the platform itself
    FileSpec src(args.GetArgumentAtIndex(0), true);
    FileSpec dst(args.GetArgumentAtIndex(1), false);
    if (!src.Exists()) {
      result.AppendError("source location does not exist or is not accessible");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
    PlatformSP platform_sp(
        m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
    if (!platform_sp) {
      result.AppendError("no platform currently selected");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    Error error = platform_sp->Install(src, dst);
    if (error.Success()) {
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else {
      result.AppendErrorWithFormat("install failed: %s", error.AsCString());
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }
};

CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
    : CommandObjectMultiword(
          interpreter, "platform", "Commands to manage and create platforms.",
          "platform [connect|disconnect|info|list|status|select] ...") {
  LoadSubCommand("select",
                 CommandObjectSP(new CommandObjectPlatformSelect(interpreter)));
  LoadSubCommand("list",
                 CommandObjectSP(new CommandObjectPlatformList(interpreter)));
  LoadSubCommand("status",
                 CommandObjectSP(new CommandObjectPlatformStatus(interpreter)));
  LoadSubCommand("connect", CommandObjectSP(
                                new CommandObjectPlatformConnect(interpreter)));
  LoadSubCommand(
      "disconnect",
      CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter)));
  LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
                                 interpreter)));
  LoadSubCommand("mkdir",
                 CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
  LoadSubCommand("file",
                 CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
  LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
                                 interpreter)));
  LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
                                 interpreter)));
  LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
                                 interpreter)));
  LoadSubCommand("process", CommandObjectSP(
                                new CommandObjectPlatformProcess(interpreter)));
  LoadSubCommand("shell",
                 CommandObjectSP(new CommandObjectPlatformShell(interpreter)));
  LoadSubCommand(
      "target-install",
      CommandObjectSP(new CommandObjectPlatformInstall(interpreter)));
}

CommandObjectPlatform::~CommandObjectPlatform() = default;
