//===-- Options.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 "lldb/Interpreter/Options.h"

#include <algorithm>
#include <bitset>
#include <map>
#include <set>

#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DiagnosticsRendering.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/STLExtras.h"

using namespace lldb;
using namespace lldb_private;

namespace lldb_private {

/// An llvm::Error that represents an option parsing diagnostic.
class OptionParseError
    : public llvm::ErrorInfo<OptionParseError, DiagnosticError> {
  std::vector<DiagnosticDetail> m_details;

public:
  using llvm::ErrorInfo<OptionParseError, DiagnosticError>::ErrorInfo;
  OptionParseError(DiagnosticDetail detail)
      : ErrorInfo(std::error_code(EINVAL, std::generic_category())),
        m_details({detail}) {}
  OptionParseError(const Args::ArgEntry &arg, std::string msg)
      : ErrorInfo(std::error_code(EINVAL, std::generic_category())) {
    DiagnosticDetail::SourceLocation sloc;
    if (auto pos = arg.GetPos()) {
      uint16_t len = arg.GetLength();
      sloc = {FileSpec{}, 1, *pos, len, false, true};
    }
    m_details.push_back(DiagnosticDetail{sloc, lldb::eSeverityError, msg, msg});
  }
  std::unique_ptr<CloneableError> Clone() const override {
    return std::make_unique<OptionParseError>(m_details[0]);
  }
  llvm::ArrayRef<DiagnosticDetail> GetDetails() const override {
    return m_details;
  }
  static char ID;
};

char OptionParseError::ID;

} // namespace lldb_private

// Options
Options::Options() { BuildValidOptionSets(); }

Options::~Options() = default;

void Options::NotifyOptionParsingStarting(ExecutionContext *execution_context) {
  m_seen_options.clear();
  // Let the subclass reset its option values
  OptionParsingStarting(execution_context);
}

Status
Options::NotifyOptionParsingFinished(ExecutionContext *execution_context) {
  return OptionParsingFinished(execution_context);
}

void Options::OptionSeen(int option_idx) { m_seen_options.insert(option_idx); }

// Returns true is set_a is a subset of set_b;  Otherwise returns false.

bool Options::IsASubset(const OptionSet &set_a, const OptionSet &set_b) {
  bool is_a_subset = true;
  OptionSet::const_iterator pos_a;
  OptionSet::const_iterator pos_b;

  // set_a is a subset of set_b if every member of set_a is also a member of
  // set_b

  for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a) {
    pos_b = set_b.find(*pos_a);
    if (pos_b == set_b.end())
      is_a_subset = false;
  }

  return is_a_subset;
}

// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) &&
// !ElementOf (x, set_b) }

size_t Options::OptionsSetDiff(const OptionSet &set_a, const OptionSet &set_b,
                               OptionSet &diffs) {
  size_t num_diffs = 0;
  OptionSet::const_iterator pos_a;
  OptionSet::const_iterator pos_b;

  for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a) {
    pos_b = set_b.find(*pos_a);
    if (pos_b == set_b.end()) {
      ++num_diffs;
      diffs.insert(*pos_a);
    }
  }

  return num_diffs;
}

// Returns the union of set_a and set_b.  Does not put duplicate members into
// the union.

void Options::OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b,
                              OptionSet &union_set) {
  OptionSet::const_iterator pos;
  OptionSet::iterator pos_union;

  // Put all the elements of set_a into the union.

  for (pos = set_a.begin(); pos != set_a.end(); ++pos)
    union_set.insert(*pos);

  // Put all the elements of set_b that are not already there into the union.
  for (pos = set_b.begin(); pos != set_b.end(); ++pos) {
    pos_union = union_set.find(*pos);
    if (pos_union == union_set.end())
      union_set.insert(*pos);
  }
}

// This is called in the Options constructor, though we could call it lazily if
// that ends up being a performance problem.

void Options::BuildValidOptionSets() {
  // Check to see if we already did this.
  if (m_required_options.size() != 0)
    return;

  // Check to see if there are any options.
  int num_options = NumCommandOptions();
  if (num_options == 0)
    return;

  auto opt_defs = GetDefinitions();
  m_required_options.resize(1);
  m_optional_options.resize(1);

  // First count the number of option sets we've got.  Ignore
  // LLDB_ALL_OPTION_SETS...

  uint32_t num_option_sets = 0;

  for (const auto &def : opt_defs) {
    uint32_t this_usage_mask = def.usage_mask;
    if (this_usage_mask == LLDB_OPT_SET_ALL) {
      if (num_option_sets == 0)
        num_option_sets = 1;
    } else {
      for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) {
        if (this_usage_mask & (1 << j)) {
          if (num_option_sets <= j)
            num_option_sets = j + 1;
        }
      }
    }
  }

  if (num_option_sets > 0) {
    m_required_options.resize(num_option_sets);
    m_optional_options.resize(num_option_sets);

    for (const auto &def : opt_defs) {
      for (uint32_t j = 0; j < num_option_sets; j++) {
        if (def.usage_mask & 1 << j) {
          if (def.required)
            m_required_options[j].insert(def.short_option);
          else
            m_optional_options[j].insert(def.short_option);
        }
      }
    }
  }
}

uint32_t Options::NumCommandOptions() { return GetDefinitions().size(); }

Option *Options::GetLongOptions() {
  // Check to see if this has already been done.
  if (m_getopt_table.empty()) {
    auto defs = GetDefinitions();
    if (defs.empty())
      return nullptr;

    std::map<int, uint32_t> option_seen;

    m_getopt_table.resize(defs.size() + 1);
    for (size_t i = 0; i < defs.size(); ++i) {
      const int short_opt = defs[i].short_option;

      m_getopt_table[i].definition = &defs[i];
      m_getopt_table[i].flag = nullptr;
      m_getopt_table[i].val = short_opt;

      auto [pos, inserted] = option_seen.try_emplace(short_opt, i);
      if (!inserted && short_opt) {
        m_getopt_table[i].val = 0;
        StreamString strm;
        if (defs[i].HasShortOption())
          Debugger::ReportError(
              llvm::formatv(
                  "option[{0}] --{1} has a short option -{2} that "
                  "conflicts with option[{3}] --{4}, short option won't "
                  "be used for --{5}",
                  i, defs[i].long_option, short_opt, pos->second,
                  m_getopt_table[pos->second].definition->long_option,
                  defs[i].long_option)
                  .str());
        else
          Debugger::ReportError(
              llvm::formatv(
                  "option[{0}] --{1} has a short option {2:x} that "
                  "conflicts with option[{3}] --{4}, short option won't "
                  "be used for --{5}",
                  (int)i, defs[i].long_option, short_opt, pos->second,
                  m_getopt_table[pos->second].definition->long_option,
                  defs[i].long_option)
                  .str());
      }
    }

    // getopt_long_only requires a NULL final entry in the table:

    m_getopt_table.back().definition = nullptr;
    m_getopt_table.back().flag = nullptr;
    m_getopt_table.back().val = 0;
  }

  if (m_getopt_table.empty())
    return nullptr;

  return &m_getopt_table.front();
}

// This function takes INDENT, which tells how many spaces to output at the
// front of each line; SPACES, which is a string containing 80 spaces; and
// TEXT, which is the text that is to be output.   It outputs the text, on
// multiple lines if necessary, to RESULT, with INDENT spaces at the front of
// each line.  It breaks lines on spaces, tabs or newlines, shortening the line
// if necessary to not break in the middle of a word.  It assumes that each
// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.

void Options::OutputFormattedUsageText(Stream &strm,
                                       const OptionDefinition &option_def,
                                       uint32_t output_max_columns) {
  std::string actual_text;
  if (option_def.validator) {
    const char *condition = option_def.validator->ShortConditionString();
    if (condition) {
      actual_text = "[";
      actual_text.append(condition);
      actual_text.append("] ");
    }
  }
  actual_text.append(option_def.usage_text);

  // Will it all fit on one line?

  if (static_cast<uint32_t>(actual_text.length() + strm.GetIndentLevel()) <
      output_max_columns) {
    // Output it as a single line.
    strm.Indent(actual_text);
    strm.EOL();
  } else {
    // We need to break it up into multiple lines.

    int text_width = output_max_columns - strm.GetIndentLevel() - 1;
    int start = 0;
    int end = start;
    int final_end = actual_text.length();
    int sub_len;

    while (end < final_end) {
      // Don't start the 'text' on a space, since we're already outputting the
      // indentation.
      while ((start < final_end) && (actual_text[start] == ' '))
        start++;

      end = start + text_width;
      if (end > final_end)
        end = final_end;
      else {
        // If we're not at the end of the text, make sure we break the line on
        // white space.
        while (end > start && actual_text[end] != ' ' &&
               actual_text[end] != '\t' && actual_text[end] != '\n')
          end--;
      }

      sub_len = end - start;
      if (start != 0)
        strm.EOL();
      strm.Indent();
      assert(start < final_end);
      assert(start + sub_len <= final_end);
      strm.Write(actual_text.c_str() + start, sub_len);
      start = end + 1;
    }
    strm.EOL();
  }
}

bool Options::SupportsLongOption(const char *long_option) {
  if (!long_option || !long_option[0])
    return false;

  auto opt_defs = GetDefinitions();
  if (opt_defs.empty())
    return false;

  const char *long_option_name = long_option;
  if (long_option[0] == '-' && long_option[1] == '-')
    long_option_name += 2;

  for (auto &def : opt_defs) {
    if (!def.long_option)
      continue;

    if (strcmp(def.long_option, long_option_name) == 0)
      return true;
  }

  return false;
}

enum OptionDisplayType {
  eDisplayBestOption,
  eDisplayShortOption,
  eDisplayLongOption
};

static bool PrintOption(const OptionDefinition &opt_def,
                        OptionDisplayType display_type, const char *header,
                        const char *footer, bool show_optional, Stream &strm) {
  if (display_type == eDisplayShortOption && !opt_def.HasShortOption())
    return false;

  if (header && header[0])
    strm.PutCString(header);

  if (show_optional && !opt_def.required)
    strm.PutChar('[');
  const bool show_short_option =
      opt_def.HasShortOption() && display_type != eDisplayLongOption;
  if (show_short_option)
    strm.Printf("-%c", opt_def.short_option);
  else
    strm.Printf("--%s", opt_def.long_option);
  switch (opt_def.option_has_arg) {
  case OptionParser::eNoArgument:
    break;
  case OptionParser::eRequiredArgument:
    strm.Printf(" <%s>", CommandObject::GetArgumentName(opt_def.argument_type));
    break;

  case OptionParser::eOptionalArgument:
    strm.Printf("%s[<%s>]", show_short_option ? "" : "=",
                CommandObject::GetArgumentName(opt_def.argument_type));
    break;
  }
  if (show_optional && !opt_def.required)
    strm.PutChar(']');
  if (footer && footer[0])
    strm.PutCString(footer);
  return true;
}

void Options::GenerateOptionUsage(Stream &strm, CommandObject &cmd,
                                  uint32_t screen_width) {
  auto opt_defs = GetDefinitions();
  const uint32_t save_indent_level = strm.GetIndentLevel();
  llvm::StringRef name = cmd.GetCommandName();
  StreamString arguments_str;
  cmd.GetFormattedCommandArguments(arguments_str);

  const uint32_t num_options = NumCommandOptions();
  if (num_options == 0)
    return;

  const bool only_print_args = cmd.IsDashDashCommand();
  if (!only_print_args)
    strm.PutCString("\nCommand Options Usage:\n");

  strm.IndentMore(2);

  // First, show each usage level set of options, e.g. <cmd> [options-for-
  // level-0]
  //                                                   <cmd>
  //                                                   [options-for-level-1]
  //                                                   etc.

  if (!only_print_args) {
    uint32_t num_option_sets = GetRequiredOptions().size();
    for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) {
      if (opt_set > 0)
        strm.Printf("\n");
      strm.Indent(name);

      // Different option sets may require different args.
      StreamString args_str;
      uint32_t opt_set_mask = 1 << opt_set;
      cmd.GetFormattedCommandArguments(args_str, opt_set_mask);

      // First go through and print all options that take no arguments as a
      // single string. If a command has "-a" "-b" and "-c", this will show up
      // as [-abc]

      // We use a set here so that they will be sorted.
      std::set<int> required_options;
      std::set<int> optional_options;

      for (auto &def : opt_defs) {
        if (def.usage_mask & opt_set_mask && def.HasShortOption() &&
            def.option_has_arg == OptionParser::eNoArgument) {
          if (def.required) {
            required_options.insert(def.short_option);
          } else {
            optional_options.insert(def.short_option);
          }
        }
      }

      if (!required_options.empty()) {
        strm.PutCString(" -");
        for (int short_option : required_options)
          strm.PutChar(short_option);
      }

      if (!optional_options.empty()) {
        strm.PutCString(" [-");
        for (int short_option : optional_options)
          strm.PutChar(short_option);
        strm.PutChar(']');
      }

      // First go through and print the required options (list them up front).
      for (auto &def : opt_defs) {
        if (def.usage_mask & opt_set_mask && def.HasShortOption() &&
            def.required && def.option_has_arg != OptionParser::eNoArgument)
          PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
      }

      // Now go through again, and this time only print the optional options.
      for (auto &def : opt_defs) {
        if (def.usage_mask & opt_set_mask && !def.required &&
            def.option_has_arg != OptionParser::eNoArgument)
          PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
      }

      if (args_str.GetSize() > 0) {
        if (cmd.WantsRawCommandString())
          strm.Printf(" --");
        strm << " " << args_str.GetString();
      }
    }
  }

  if ((only_print_args || cmd.WantsRawCommandString()) &&
      arguments_str.GetSize() > 0) {
    if (!only_print_args)
      strm.PutChar('\n');
    strm.Indent(name);
    strm << " " << arguments_str.GetString();
  }

  if (!only_print_args) {
    strm.Printf("\n\n");

    // Now print out all the detailed information about the various options:
    // long form, short form and help text:
    //   -short <argument> ( --long_name <argument> )
    //   help text

    strm.IndentMore(5);

    // Put the command options in a sorted container, so we can output
    // them alphabetically by short_option.
    std::multimap<int, uint32_t> options_ordered;
    for (auto def : llvm::enumerate(opt_defs))
      options_ordered.insert(
          std::make_pair(def.value().short_option, def.index()));

    // Go through each option, find the table entry and write out the detailed
    // help information for that option.

    bool first_option_printed = false;

    for (auto pos : options_ordered) {
      // Put a newline separation between arguments
      if (first_option_printed)
        strm.EOL();
      else
        first_option_printed = true;

      OptionDefinition opt_def = opt_defs[pos.second];

      strm.Indent();
      if (opt_def.short_option && opt_def.HasShortOption()) {
        PrintOption(opt_def, eDisplayShortOption, nullptr, nullptr, false,
                    strm);
        PrintOption(opt_def, eDisplayLongOption, " ( ", " )", false, strm);
      } else {
        // Short option is not printable, just print long option
        PrintOption(opt_def, eDisplayLongOption, nullptr, nullptr, false, strm);
      }
      strm.EOL();

      strm.IndentMore(5);

      if (opt_def.usage_text)
        OutputFormattedUsageText(strm, opt_def, screen_width);
      if (!opt_def.enum_values.empty()) {
        strm.Indent();
        strm.Printf("Values: ");
        bool is_first = true;
        for (const auto &enum_value : opt_def.enum_values) {
          if (is_first) {
            strm.Printf("%s", enum_value.string_value);
            is_first = false;
          }
          else
            strm.Printf(" | %s", enum_value.string_value);
        }
        strm.EOL();
      }
      strm.IndentLess(5);
    }
  }

  // Restore the indent level
  strm.SetIndentLevel(save_indent_level);
}

llvm::Error Options::VerifyOptions() {
  bool options_are_valid = false;

  int num_levels = GetRequiredOptions().size();
  if (num_levels) {
    for (int i = 0; i < num_levels && !options_are_valid; ++i) {
      // This is the correct set of options if:  1). m_seen_options contains
      // all of m_required_options[i] (i.e. all the required options at this
      // level are a subset of m_seen_options); AND 2). { m_seen_options -
      // m_required_options[i] is a subset of m_options_options[i] (i.e. all
      // the rest of m_seen_options are in the set of optional options at this
      // level.

      // Check to see if all of m_required_options[i] are a subset of
      // m_seen_options
      if (IsASubset(GetRequiredOptions()[i], m_seen_options)) {
        // Construct the set difference: remaining_options = {m_seen_options} -
        // {m_required_options[i]}
        OptionSet remaining_options;
        OptionsSetDiff(m_seen_options, GetRequiredOptions()[i],
                       remaining_options);
        // Check to see if remaining_options is a subset of
        // m_optional_options[i]
        if (IsASubset(remaining_options, GetOptionalOptions()[i]))
          options_are_valid = true;
      }
    }
  } else {
    options_are_valid = true;
  }

  if (!options_are_valid)
    return llvm::createStringError(
        "invalid combination of options for the given command");

  return llvm::Error::success();
}

// This function is called when we have been given a potentially incomplete set
// of options, such as when an alias has been defined (more options might be
// added at at the time the alias is invoked).  We need to verify that the
// options in the set m_seen_options are all part of a set that may be used
// together, but m_seen_options may be missing some of the "required" options.
llvm::Error Options::VerifyPartialOptions() {
  bool options_are_valid = false;

  int num_levels = GetRequiredOptions().size();
  if (num_levels) {
    for (int i = 0; i < num_levels && !options_are_valid; ++i) {
      // In this case we are treating all options as optional rather than
      // required. Therefore a set of options is correct if m_seen_options is a
      // subset of the union of m_required_options and m_optional_options.
      OptionSet union_set;
      OptionsSetUnion(GetRequiredOptions()[i], GetOptionalOptions()[i],
                      union_set);
      if (IsASubset(m_seen_options, union_set))
        options_are_valid = true;
    }
  }

  if (!options_are_valid)
    return llvm::createStringError(
        "invalid combination of options for the given command");

  return llvm::Error::success();
}

bool Options::HandleOptionCompletion(CompletionRequest &request,
                                     OptionElementVector &opt_element_vector,
                                     CommandInterpreter &interpreter) {
  // For now we just scan the completions to see if the cursor position is in
  // an option or its argument.  Otherwise we'll call HandleArgumentCompletion.
  // In the future we can use completion to validate options as well if we
  // want.

  auto opt_defs = GetDefinitions();

  llvm::StringRef cur_opt_str = request.GetCursorArgumentPrefix();

  for (size_t i = 0; i < opt_element_vector.size(); i++) {
    size_t opt_pos = static_cast<size_t>(opt_element_vector[i].opt_pos);
    size_t opt_arg_pos = static_cast<size_t>(opt_element_vector[i].opt_arg_pos);
    int opt_defs_index = opt_element_vector[i].opt_defs_index;
    if (opt_pos == request.GetCursorIndex()) {
      // We're completing the option itself.

      if (opt_defs_index == OptionArgElement::eBareDash) {
        // We're completing a bare dash.  That means all options are open.
        // FIXME: We should scan the other options provided and only complete
        // options
        // within the option group they belong to.
        std::string opt_str = "-a";

        for (auto &def : opt_defs) {
          if (!def.short_option)
            continue;
          opt_str[1] = def.short_option;
          request.AddCompletion(opt_str, def.usage_text);
        }

        return true;
      } else if (opt_defs_index == OptionArgElement::eBareDoubleDash) {
        std::string full_name("--");
        for (auto &def : opt_defs) {
          if (!def.short_option)
            continue;

          full_name.erase(full_name.begin() + 2, full_name.end());
          full_name.append(def.long_option);
          request.AddCompletion(full_name, def.usage_text);
        }
        return true;
      } else if (opt_defs_index != OptionArgElement::eUnrecognizedArg) {
        // We recognized it, if it an incomplete long option, complete it
        // anyway (getopt_long_only is happy with shortest unique string, but
        // it's still a nice thing to do.)  Otherwise return The string so the
        // upper level code will know this is a full match and add the " ".
        const OptionDefinition &opt = opt_defs[opt_defs_index];
        llvm::StringRef long_option = opt.long_option;
        if (cur_opt_str.starts_with("--") && cur_opt_str != long_option) {
          request.AddCompletion("--" + long_option.str(), opt.usage_text);
          return true;
        } else
          request.AddCompletion(request.GetCursorArgumentPrefix());
        return true;
      } else {
        // FIXME - not handling wrong options yet:
        // Check to see if they are writing a long option & complete it.
        // I think we will only get in here if the long option table has two
        // elements
        // that are not unique up to this point.  getopt_long_only does
        // shortest unique match for long options already.
        if (cur_opt_str.consume_front("--")) {
          for (auto &def : opt_defs) {
            llvm::StringRef long_option(def.long_option);
            if (long_option.starts_with(cur_opt_str))
              request.AddCompletion("--" + long_option.str(), def.usage_text);
          }
        }
        return true;
      }

    } else if (opt_arg_pos == request.GetCursorIndex()) {
      // Okay the cursor is on the completion of an argument. See if it has a
      // completion, otherwise return no matches.  Note, opt_defs_index == -1
      // means we're after an option, but that option doesn't exist.  We'll
      // end up treating that as an argument.  Not sure we can do much better.
      if (opt_defs_index != -1) {
        HandleOptionArgumentCompletion(request, opt_element_vector, i,
                                       interpreter);
        return true;
      } else {
        // No completion callback means no completions...
        return true;
      }

    } else {
      // Not the last element, keep going.
      continue;
    }
  }
  return false;
}

void Options::HandleOptionArgumentCompletion(
    CompletionRequest &request, OptionElementVector &opt_element_vector,
    int opt_element_index, CommandInterpreter &interpreter) {
  auto opt_defs = GetDefinitions();
  std::unique_ptr<SearchFilter> filter_up;

  int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;

  // See if this is an enumeration type option, and if so complete it here:
  const auto &enum_values = opt_defs[opt_defs_index].enum_values;
  if (!enum_values.empty())
    for (const auto &enum_value : enum_values)
      request.TryCompleteCurrentArg(enum_value.string_value);

  // If this is a source file or symbol type completion, and  there is a -shlib
  // option somewhere in the supplied arguments, then make a search filter for
  // that shared library.
  // FIXME: Do we want to also have an "OptionType" so we don't have to match
  // string names?

  uint32_t completion_mask = opt_defs[opt_defs_index].completion_type;

  if (completion_mask == 0) {
    lldb::CommandArgumentType option_arg_type =
        opt_defs[opt_defs_index].argument_type;
    if (option_arg_type != eArgTypeNone) {
      const CommandObject::ArgumentTableEntry *arg_entry =
          CommandObject::FindArgumentDataByType(
              opt_defs[opt_defs_index].argument_type);
      if (arg_entry)
        completion_mask = arg_entry->completion_type;
    }
  }

  if (completion_mask & lldb::eSourceFileCompletion ||
      completion_mask & lldb::eSymbolCompletion) {
    for (size_t i = 0; i < opt_element_vector.size(); i++) {
      int cur_defs_index = opt_element_vector[i].opt_defs_index;

      // trying to use <0 indices will definitely cause problems
      if (cur_defs_index == OptionArgElement::eUnrecognizedArg ||
          cur_defs_index == OptionArgElement::eBareDash ||
          cur_defs_index == OptionArgElement::eBareDoubleDash)
        continue;

      int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
      const char *cur_opt_name = opt_defs[cur_defs_index].long_option;

      // If this is the "shlib" option and there was an argument provided,
      // restrict it to that shared library.
      if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 &&
          cur_arg_pos != -1) {
        const char *module_name =
            request.GetParsedLine().GetArgumentAtIndex(cur_arg_pos);
        if (module_name) {
          FileSpec module_spec(module_name);
          lldb::TargetSP target_sp =
              interpreter.GetDebugger().GetSelectedTarget();
          // Search filters require a target...
          if (target_sp)
            filter_up =
                std::make_unique<SearchFilterByModule>(target_sp, module_spec);
        }
        break;
      }
    }
  }

  lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
      interpreter, completion_mask, request, filter_up.get());
}

void OptionGroupOptions::Append(OptionGroup *group) {
  auto group_option_defs = group->GetDefinitions();
  for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
    m_option_infos.push_back(OptionInfo(group, i));
    m_option_defs.push_back(group_option_defs[i]);
  }
}

const OptionGroup *OptionGroupOptions::GetGroupWithOption(char short_opt) {
  for (uint32_t i = 0; i < m_option_defs.size(); i++) {
    OptionDefinition opt_def = m_option_defs[i];
    if (opt_def.short_option == short_opt)
      return m_option_infos[i].option_group;
  }
  return nullptr;
}

void OptionGroupOptions::Append(OptionGroup *group, uint32_t src_mask,
                                uint32_t dst_mask) {
  auto group_option_defs = group->GetDefinitions();
  for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
    if (group_option_defs[i].usage_mask & src_mask) {
      m_option_infos.push_back(OptionInfo(group, i));
      m_option_defs.push_back(group_option_defs[i]);
      m_option_defs.back().usage_mask = dst_mask;
    }
  }
}

void OptionGroupOptions::Append(
    OptionGroup *group, llvm::ArrayRef<llvm::StringRef> exclude_long_options) {
  auto group_option_defs = group->GetDefinitions();
  for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
    const auto &definition = group_option_defs[i];
    if (llvm::is_contained(exclude_long_options, definition.long_option))
      continue;

    m_option_infos.push_back(OptionInfo(group, i));
    m_option_defs.push_back(definition);
  }
}

void OptionGroupOptions::Finalize() {
  m_did_finalize = true;
}

Status OptionGroupOptions::SetOptionValue(uint32_t option_idx,
                                          llvm::StringRef option_value,
                                          ExecutionContext *execution_context) {
  // After calling OptionGroupOptions::Append(...), you must finalize the
  // groups by calling OptionGroupOptions::Finlize()
  assert(m_did_finalize);
  Status error;
  if (option_idx < m_option_infos.size()) {
    error = m_option_infos[option_idx].option_group->SetOptionValue(
        m_option_infos[option_idx].option_index, option_value,
        execution_context);

  } else {
    error =
        Status::FromErrorString("invalid option index"); // Shouldn't happen...
  }
  return error;
}

void OptionGroupOptions::OptionParsingStarting(
    ExecutionContext *execution_context) {
  std::set<OptionGroup *> group_set;
  OptionInfos::iterator pos, end = m_option_infos.end();
  for (pos = m_option_infos.begin(); pos != end; ++pos) {
    OptionGroup *group = pos->option_group;
    if (group_set.find(group) == group_set.end()) {
      group->OptionParsingStarting(execution_context);
      group_set.insert(group);
    }
  }
}
Status
OptionGroupOptions::OptionParsingFinished(ExecutionContext *execution_context) {
  std::set<OptionGroup *> group_set;
  Status error;
  OptionInfos::iterator pos, end = m_option_infos.end();
  for (pos = m_option_infos.begin(); pos != end; ++pos) {
    OptionGroup *group = pos->option_group;
    if (group_set.find(group) == group_set.end()) {
      error = group->OptionParsingFinished(execution_context);
      group_set.insert(group);
      if (error.Fail())
        return error;
    }
  }
  return error;
}

// OptionParser permutes the arguments while processing them, so we create a
// temporary array holding to avoid modification of the input arguments. The
// options themselves are never modified, but the API expects a char * anyway,
// hence the const_cast.
static std::vector<char *> GetArgvForParsing(const Args &args) {
  std::vector<char *> result;
  // OptionParser always skips the first argument as it is based on getopt().
  result.push_back(const_cast<char *>("<FAKE-ARG0>"));
  for (const Args::ArgEntry &entry : args)
    result.push_back(const_cast<char *>(entry.c_str()));
  result.push_back(nullptr);
  return result;
}

// Given a permuted argument, find it's position in the original Args vector.
static Args::const_iterator FindOriginalIter(const char *arg,
                                             const Args &original) {
  return llvm::find_if(
      original, [arg](const Args::ArgEntry &D) { return D.c_str() == arg; });
}

// Given a permuted argument, find it's index in the original Args vector.
static size_t FindOriginalIndex(const char *arg, const Args &original) {
  return std::distance(original.begin(), FindOriginalIter(arg, original));
}

// Construct a new Args object, consisting of the entries from the original
// arguments, but in the permuted order.
static Args ReconstituteArgsAfterParsing(llvm::ArrayRef<char *> parsed,
                                         const Args &original) {
  Args result;
  for (const char *arg : parsed) {
    auto pos = FindOriginalIter(arg, original);
    assert(pos != original.end());
    result.AppendArgument(pos->ref(), pos->GetQuoteChar());
  }
  return result;
}

static size_t FindArgumentIndexForOption(const Args &args,
                                         const Option &long_option) {
  std::string short_opt = llvm::formatv("-{0}", char(long_option.val)).str();
  std::string long_opt =
      std::string(llvm::formatv("--{0}", long_option.definition->long_option));
  for (const auto &entry : llvm::enumerate(args)) {
    if (entry.value().ref().starts_with(short_opt) ||
        entry.value().ref().starts_with(long_opt))
      return entry.index();
  }

  return size_t(-1);
}

static std::string BuildShortOptions(const Option *long_options) {
  std::string storage;
  llvm::raw_string_ostream sstr(storage);

  // Leading : tells getopt to return a : for a missing option argument AND to
  // suppress error messages.
  sstr << ":";

  for (size_t i = 0; long_options[i].definition != nullptr; ++i) {
    if (long_options[i].flag == nullptr) {
      sstr << (char)long_options[i].val;
      switch (long_options[i].definition->option_has_arg) {
      default:
      case OptionParser::eNoArgument:
        break;
      case OptionParser::eRequiredArgument:
        sstr << ":";
        break;
      case OptionParser::eOptionalArgument:
        sstr << "::";
        break;
      }
    }
  }
  return storage;
}

llvm::Expected<Args> Options::ParseAlias(const Args &args,
                                         OptionArgVector *option_arg_vector,
                                         std::string &input_line) {
  Option *long_options = GetLongOptions();

  if (long_options == nullptr) {
    return llvm::createStringError("Invalid long options");
  }

  std::string short_options = BuildShortOptions(long_options);

  Args args_copy = args;
  std::vector<char *> argv = GetArgvForParsing(args);

  std::unique_lock<std::mutex> lock;
  OptionParser::Prepare(lock);
  int val;
  while (true) {
    int long_options_index = -1;
    val = OptionParser::Parse(argv, short_options, long_options,
                              &long_options_index);

    if (val == ':') {
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "last option requires an argument");
    }

    if (val == -1)
      break;

    if (val == '?') {
      return llvm::createStringError("Unknown or ambiguous option");
    }

    if (val == 0)
      continue;

    OptionSeen(val);

    // Look up the long option index
    if (long_options_index == -1) {
      for (int j = 0; long_options[j].definition || long_options[j].flag ||
                      long_options[j].val;
           ++j) {
        if (long_options[j].val == val) {
          long_options_index = j;
          break;
        }
      }
    }

    // See if the option takes an argument, and see if one was supplied.
    if (long_options_index == -1) {
      return llvm::createStringError(
          llvm::formatv("Invalid option with value '{0}'.", char(val)).str());
    }

    StreamString option_str;
    option_str.Printf("-%c", val);
    const OptionDefinition *def = long_options[long_options_index].definition;
    int has_arg =
        (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;

    const char *option_arg = nullptr;
    switch (has_arg) {
    case OptionParser::eRequiredArgument:
      if (OptionParser::GetOptionArgument() == nullptr) {
        return llvm::createStringError(
            llvm::formatv("Option '{0}' is missing argument specifier.",
                          option_str.GetString())
                .str());
      }
      [[fallthrough]];
    case OptionParser::eOptionalArgument:
      option_arg = OptionParser::GetOptionArgument();
      [[fallthrough]];
    case OptionParser::eNoArgument:
      break;
    default:
      return llvm::createStringError(
          llvm::formatv("error with options table; invalid value in has_arg "
                        "field for option '{0}'.",
                        char(val))
              .str());
    }
    // Find option in the argument list; also see if it was supposed to take an
    // argument and if one was supplied.  Remove option (and argument, if
    // given) from the argument list.  Also remove them from the
    // raw_input_string, if one was passed in.
    // Note: We also need to preserve any option argument values that were
    // surrounded by backticks, as we lose track of them in the
    // option_args_vector.
    size_t idx =
        FindArgumentIndexForOption(args_copy, long_options[long_options_index]);
    std::string option_to_insert;
    if (option_arg) {
      if (idx != size_t(-1) && has_arg) {
        bool arg_has_backtick = args_copy[idx + 1].GetQuoteChar() == '`';
        if (arg_has_backtick)
          option_to_insert = "`";
        option_to_insert += option_arg;
        if (arg_has_backtick)
          option_to_insert += "`";
      } else
        option_to_insert = option_arg;
    } else
      option_to_insert = CommandInterpreter::g_no_argument;

    option_arg_vector->emplace_back(std::string(option_str.GetString()),
                                    has_arg, option_to_insert);

    if (idx == size_t(-1))
      continue;

    if (!input_line.empty()) {
      llvm::StringRef tmp_arg = args_copy[idx].ref();
      size_t pos = input_line.find(tmp_arg);
      if (pos != std::string::npos)
        input_line.erase(pos, tmp_arg.size());
    }
    args_copy.DeleteArgumentAtIndex(idx);
    if ((option_to_insert != CommandInterpreter::g_no_argument) &&
        (OptionParser::GetOptionArgument() != nullptr) &&
        (idx < args_copy.GetArgumentCount()) &&
        (args_copy[idx].ref() == OptionParser::GetOptionArgument())) {
      if (input_line.size() > 0) {
        size_t pos = input_line.find(option_to_insert);
        if (pos != std::string::npos)
          input_line.erase(pos, option_to_insert.size());
      }
      args_copy.DeleteArgumentAtIndex(idx);
    }
  }

  return std::move(args_copy);
}

OptionElementVector Options::ParseForCompletion(const Args &args,
                                                uint32_t cursor_index) {
  OptionElementVector option_element_vector;
  Option *long_options = GetLongOptions();
  option_element_vector.clear();

  if (long_options == nullptr)
    return option_element_vector;

  std::string short_options = BuildShortOptions(long_options);

  std::unique_lock<std::mutex> lock;
  OptionParser::Prepare(lock);
  OptionParser::EnableError(false);

  int val;
  auto opt_defs = GetDefinitions();

  std::vector<char *> dummy_vec = GetArgvForParsing(args);

  bool failed_once = false;
  uint32_t dash_dash_pos = -1;

  while (true) {
    bool missing_argument = false;
    int long_options_index = -1;

    val = OptionParser::Parse(dummy_vec, short_options, long_options,
                              &long_options_index);

    if (val == -1) {
      // When we're completing a "--" which is the last option on line,
      if (failed_once)
        break;

      failed_once = true;

      // If this is a bare  "--" we mark it as such so we can complete it
      // successfully later.  Handling the "--" is a little tricky, since that
      // may mean end of options or arguments, or the user might want to
      // complete options by long name.  I make this work by checking whether
      // the cursor is in the "--" argument, and if so I assume we're
      // completing the long option, otherwise I let it pass to
      // OptionParser::Parse which will terminate the option parsing.  Note, in
      // either case we continue parsing the line so we can figure out what
      // other options were passed.  This will be useful when we come to
      // restricting completions based on what other options we've seen on the
      // line.

      if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
              dummy_vec.size() &&
          (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
        dash_dash_pos = FindOriginalIndex(
            dummy_vec[OptionParser::GetOptionIndex() - 1], args);
        if (dash_dash_pos == cursor_index) {
          option_element_vector.push_back(
              OptionArgElement(OptionArgElement::eBareDoubleDash, dash_dash_pos,
                               OptionArgElement::eBareDoubleDash));
          continue;
        } else
          break;
      } else
        break;
    } else if (val == '?') {
      option_element_vector.push_back(OptionArgElement(
          OptionArgElement::eUnrecognizedArg,
          FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
                            args),
          OptionArgElement::eUnrecognizedArg));
      continue;
    } else if (val == 0) {
      continue;
    } else if (val == ':') {
      // This is a missing argument.
      val = OptionParser::GetOptionErrorCause();
      missing_argument = true;
    }

    OptionSeen(val);

    // Look up the long option index
    if (long_options_index == -1) {
      for (int j = 0; long_options[j].definition || long_options[j].flag ||
                      long_options[j].val;
           ++j) {
        if (long_options[j].val == val) {
          long_options_index = j;
          break;
        }
      }
    }

    // See if the option takes an argument, and see if one was supplied.
    if (long_options_index >= 0) {
      int opt_defs_index = -1;
      for (size_t i = 0; i < opt_defs.size(); i++) {
        if (opt_defs[i].short_option != val)
          continue;
        opt_defs_index = i;
        break;
      }

      const OptionDefinition *def = long_options[long_options_index].definition;
      int has_arg =
          (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
      switch (has_arg) {
      case OptionParser::eNoArgument:
        option_element_vector.push_back(OptionArgElement(
            opt_defs_index,
            FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
                              args),
            0));
        break;
      case OptionParser::eRequiredArgument:
        if (OptionParser::GetOptionArgument() != nullptr) {
          int arg_index;
          if (missing_argument)
            arg_index = -1;
          else
            arg_index = OptionParser::GetOptionIndex() - 2;

          option_element_vector.push_back(OptionArgElement(
              opt_defs_index,
              FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 2],
                                args),
              arg_index));
        } else {
          option_element_vector.push_back(OptionArgElement(
              opt_defs_index,
              FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
                                args),
              -1));
        }
        break;
      case OptionParser::eOptionalArgument:
        option_element_vector.push_back(OptionArgElement(
            opt_defs_index,
            FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 2],
                              args),
            FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
                              args)));
        break;
      default:
        // The options table is messed up.  Here we'll just continue
        option_element_vector.push_back(OptionArgElement(
            OptionArgElement::eUnrecognizedArg,
            FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
                              args),
            OptionArgElement::eUnrecognizedArg));
        break;
      }
    } else {
      option_element_vector.push_back(OptionArgElement(
          OptionArgElement::eUnrecognizedArg,
          FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
                            args),
          OptionArgElement::eUnrecognizedArg));
    }
  }

  // Finally we have to handle the case where the cursor index points at a
  // single "-".  We want to mark that in the option_element_vector, but only
  // if it is not after the "--".  But it turns out that OptionParser::Parse
  // just ignores an isolated "-".  So we have to look it up by hand here.  We
  // only care if it is AT the cursor position. Note, a single quoted dash is
  // not the same as a single dash...

  const Args::ArgEntry &cursor = args[cursor_index];
  if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
       cursor_index < dash_dash_pos) &&
      !cursor.IsQuoted() && cursor.ref() == "-") {
    option_element_vector.push_back(
        OptionArgElement(OptionArgElement::eBareDash, cursor_index,
                         OptionArgElement::eBareDash));
  }
  return option_element_vector;
}

llvm::Expected<Args> Options::Parse(const Args &args,
                                    ExecutionContext *execution_context,
                                    lldb::PlatformSP platform_sp,
                                    bool require_validation) {
  Status error;
  Option *long_options = GetLongOptions();
  if (long_options == nullptr) {
    return llvm::createStringError("Invalid long options.");
  }

  std::string short_options = BuildShortOptions(long_options);
  std::vector<char *> argv = GetArgvForParsing(args);

  std::unique_lock<std::mutex> lock;
  OptionParser::Prepare(lock);
  while (true) {
    int long_options_index = -1;
    int val = OptionParser::Parse(argv, short_options, long_options,
                                  &long_options_index);

    if (val == ':') {
      error = Status::FromErrorString("last option requires an argument");
      break;
    }

    if (val == -1)
      break;

    // Did we get an error?
    if (val == '?') {
      // Account for "argv[0]" and that it points to the next option.
      int idx = OptionParser::GetOptionIndex() - 2;
      if (idx >= 0 && (size_t)idx < args.GetArgumentCount())
        error = Status::FromError(llvm::make_error<OptionParseError>(
            args[idx], "unknown or ambiguous option"));
      else
        error = Status("unknown or ambiguous option");

      break;
    }
    // The option auto-set itself
    if (val == 0)
      continue;

    OptionSeen(val);

    // Lookup the long option index
    if (long_options_index == -1) {
      for (int i = 0; long_options[i].definition || long_options[i].flag ||
                      long_options[i].val;
           ++i) {
        if (long_options[i].val == val) {
          long_options_index = i;
          break;
        }
      }
    }
    // Call the callback with the option
    if (long_options_index >= 0 &&
        long_options[long_options_index].definition) {
      const OptionDefinition *def = long_options[long_options_index].definition;

      if (!platform_sp) {
        // User did not pass in an explicit platform.  Try to grab from the
        // execution context.
        TargetSP target_sp =
            execution_context ? execution_context->GetTargetSP() : TargetSP();
        platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
      }
      OptionValidator *validator = def->validator;

      if (!platform_sp && require_validation) {
        // Caller requires validation but we cannot validate as we don't have
        // the mandatory platform against which to validate.
        return llvm::createStringError(
            "cannot validate options: no platform available");
      }

      bool validation_failed = false;
      if (platform_sp) {
        // Ensure we have an execution context, empty or not.
        ExecutionContext dummy_context;
        ExecutionContext *exe_ctx_p =
            execution_context ? execution_context : &dummy_context;
        if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
          validation_failed = true;
          error = Status::FromErrorStringWithFormat(
              "Option \"%s\" invalid.  %s", def->long_option,
              def->validator->LongConditionString());
        }
      }

      // As long as validation didn't fail, we set the option value.
      if (!validation_failed)
        error =
            SetOptionValue(long_options_index,
                           (def->option_has_arg == OptionParser::eNoArgument)
                               ? nullptr
                               : OptionParser::GetOptionArgument(),
                           execution_context);
      // If the Option setting returned an error, we should stop parsing
      // and return the error.
      if (error.Fail())
        break;
    } else {
      error = Status::FromErrorStringWithFormat(
          "invalid option with value '%i'", val);
    }
  }

  if (error.Fail())
    return error.ToError();

  argv.pop_back();
  argv.erase(argv.begin(), argv.begin() + OptionParser::GetOptionIndex());
  return ReconstituteArgsAfterParsing(argv, args);
}

llvm::Error lldb_private::CreateOptionParsingError(
    llvm::StringRef option_arg, const char short_option,
    llvm::StringRef long_option, llvm::StringRef additional_context) {
  std::string buffer;
  llvm::raw_string_ostream stream(buffer);
  stream << "Invalid value ('" << option_arg << "') for -" << short_option;
  if (!long_option.empty())
    stream << " (" << long_option << ")";
  if (!additional_context.empty())
    stream << ": " << additional_context;
  return llvm::createStringError(llvm::inconvertibleErrorCode(), buffer);
}
