brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.8 KiB · 22eeceb Raw
856 lines · cpp
1//===-- CommandObject.cpp -------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Interpreter/CommandObject.h"10 11#include <map>12#include <sstream>13#include <string>14 15#include <cctype>16#include <cstdlib>17 18#include "lldb/Core/Address.h"19#include "lldb/Interpreter/CommandOptionArgumentTable.h"20#include "lldb/Interpreter/Options.h"21#include "lldb/Utility/ArchSpec.h"22#include "llvm/ADT/ScopeExit.h"23 24// These are for the Sourcename completers.25// FIXME: Make a separate file for the completers.26#include "lldb/DataFormatters/FormatManager.h"27#include "lldb/Target/Process.h"28#include "lldb/Target/Target.h"29#include "lldb/Utility/FileSpec.h"30#include "lldb/Utility/FileSpecList.h"31 32#include "lldb/Target/Language.h"33 34#include "lldb/Interpreter/CommandInterpreter.h"35#include "lldb/Interpreter/CommandReturnObject.h"36 37using namespace lldb;38using namespace lldb_private;39 40// CommandObject41 42CommandObject::CommandObject(CommandInterpreter &interpreter,43                             llvm::StringRef name, llvm::StringRef help,44                             llvm::StringRef syntax, uint32_t flags)45    : m_interpreter(interpreter), m_cmd_name(std::string(name)),46      m_flags(flags), m_deprecated_command_override_callback(nullptr),47      m_command_override_callback(nullptr), m_command_override_baton(nullptr) {48  m_cmd_help_short = std::string(help);49  m_cmd_syntax = std::string(syntax);50}51 52Debugger &CommandObject::GetDebugger() { return m_interpreter.GetDebugger(); }53 54llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; }55 56llvm::StringRef CommandObject::GetHelpLong() { return m_cmd_help_long; }57 58llvm::StringRef CommandObject::GetSyntax() {59  if (!m_cmd_syntax.empty())60    return m_cmd_syntax;61 62  StreamString syntax_str;63  syntax_str.PutCString(GetCommandName());64 65  if (!IsDashDashCommand() && GetOptions() != nullptr)66    syntax_str.PutCString(" <cmd-options>");67 68  if (!m_arguments.empty()) {69    syntax_str.PutCString(" ");70 71    if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() &&72        GetOptions()->NumCommandOptions())73      syntax_str.PutCString("-- ");74    GetFormattedCommandArguments(syntax_str);75  }76  m_cmd_syntax = std::string(syntax_str.GetString());77 78  return m_cmd_syntax;79}80 81llvm::StringRef CommandObject::GetCommandName() const { return m_cmd_name; }82 83void CommandObject::SetCommandName(llvm::StringRef name) {84  m_cmd_name = std::string(name);85}86 87void CommandObject::SetHelp(llvm::StringRef str) {88  m_cmd_help_short = std::string(str);89}90 91void CommandObject::SetHelpLong(llvm::StringRef str) {92  m_cmd_help_long = std::string(str);93}94 95void CommandObject::SetSyntax(llvm::StringRef str) {96  m_cmd_syntax = std::string(str);97}98 99Options *CommandObject::GetOptions() {100  // By default commands don't have options unless this virtual function is101  // overridden by base classes.102  return nullptr;103}104 105bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {106  // See if the subclass has options?107  Options *options = GetOptions();108  if (options != nullptr) {109    Status error;110 111    auto exe_ctx = GetCommandInterpreter().GetExecutionContext();112    options->NotifyOptionParsingStarting(&exe_ctx);113 114    const bool require_validation = true;115    llvm::Expected<Args> args_or = options->Parse(116        args, &exe_ctx, GetCommandInterpreter().GetPlatform(true),117        require_validation);118 119    if (args_or) {120      args = std::move(*args_or);121      error = options->NotifyOptionParsingFinished(&exe_ctx);122    } else {123      error = Status::FromError(args_or.takeError());124    }125 126    if (error.Fail()) {127      result.SetError(error.takeError());128      result.SetStatus(eReturnStatusFailed);129      return false;130    }131 132    if (llvm::Error error = options->VerifyOptions()) {133      result.SetError(std::move(error));134      result.SetStatus(eReturnStatusFailed);135      return false;136    }137 138    result.SetStatus(eReturnStatusSuccessFinishNoResult);139    return true;140  }141  return true;142}143 144bool CommandObject::CheckRequirements(CommandReturnObject &result) {145  // Nothing should be stored in m_exe_ctx between running commands as146  // m_exe_ctx has shared pointers to the target, process, thread and frame and147  // we don't want any CommandObject instances to keep any of these objects148  // around longer than for a single command. Every command should call149  // CommandObject::Cleanup() after it has completed.150  assert(!m_exe_ctx.GetTargetPtr());151  assert(!m_exe_ctx.GetProcessPtr());152  assert(!m_exe_ctx.GetThreadPtr());153  assert(!m_exe_ctx.GetFramePtr());154 155  // Lock down the interpreter's execution context prior to running the command156  // so we guarantee the selected target, process, thread and frame can't go157  // away during the execution158  m_exe_ctx = m_interpreter.GetExecutionContext();159 160  const uint32_t flags = GetFlags().Get();161  if (flags & (eCommandRequiresTarget | eCommandRequiresProcess |162               eCommandRequiresThread | eCommandRequiresFrame |163               eCommandTryTargetAPILock)) {164 165    if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) {166      result.AppendError(GetInvalidTargetDescription());167      return false;168    }169 170    if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) {171      if (!m_exe_ctx.HasTargetScope())172        result.AppendError(GetInvalidTargetDescription());173      else174        result.AppendError(GetInvalidProcessDescription());175      return false;176    }177 178    if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) {179      if (!m_exe_ctx.HasTargetScope())180        result.AppendError(GetInvalidTargetDescription());181      else if (!m_exe_ctx.HasProcessScope())182        result.AppendError(GetInvalidProcessDescription());183      else184        result.AppendError(GetInvalidThreadDescription());185      return false;186    }187 188    if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) {189      if (!m_exe_ctx.HasTargetScope())190        result.AppendError(GetInvalidTargetDescription());191      else if (!m_exe_ctx.HasProcessScope())192        result.AppendError(GetInvalidProcessDescription());193      else if (!m_exe_ctx.HasThreadScope())194        result.AppendError(GetInvalidThreadDescription());195      else196        result.AppendError(GetInvalidFrameDescription());197      return false;198    }199 200    if ((flags & eCommandRequiresRegContext) &&201        (m_exe_ctx.GetRegisterContext() == nullptr)) {202      result.AppendError(GetInvalidRegContextDescription());203      return false;204    }205 206    if (flags & eCommandTryTargetAPILock) {207      Target *target = m_exe_ctx.GetTargetPtr();208      if (target)209        m_api_locker =210            std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());211    }212  }213 214  if (GetFlags().AnySet(eCommandProcessMustBeLaunched |215                        eCommandProcessMustBePaused)) {216    Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();217    if (process == nullptr) {218      // A process that is not running is considered paused.219      if (GetFlags().Test(eCommandProcessMustBeLaunched)) {220        result.AppendError("process must exist");221        return false;222      }223    } else {224      StateType state = process->GetState();225      switch (state) {226      case eStateInvalid:227      case eStateSuspended:228      case eStateCrashed:229      case eStateStopped:230        break;231 232      case eStateConnected:233      case eStateAttaching:234      case eStateLaunching:235      case eStateDetached:236      case eStateExited:237      case eStateUnloaded:238        if (GetFlags().Test(eCommandProcessMustBeLaunched)) {239          result.AppendError("process must be launched");240          return false;241        }242        break;243 244      case eStateRunning:245      case eStateStepping:246        if (GetFlags().Test(eCommandProcessMustBePaused)) {247          result.AppendError("Process is running.  Use 'process interrupt' to "248                             "pause execution.");249          return false;250        }251      }252    }253  }254 255  if (GetFlags().Test(eCommandProcessMustBeTraced)) {256    Target *target = m_exe_ctx.GetTargetPtr();257    if (target && !target->GetTrace()) {258      result.AppendError("process is not being traced");259      return false;260    }261  }262 263  return true;264}265 266void CommandObject::Cleanup() {267  m_exe_ctx.Clear();268  if (m_api_locker.owns_lock())269    m_api_locker.unlock();270}271 272void CommandObject::HandleCompletion(CompletionRequest &request) {273 274  m_exe_ctx = m_interpreter.GetExecutionContext();275  auto reset_ctx = llvm::make_scope_exit([this]() { Cleanup(); });276 277  // Default implementation of WantsCompletion() is !WantsRawCommandString().278  // Subclasses who want raw command string but desire, for example, argument279  // completion should override WantsCompletion() to return true, instead.280  if (WantsRawCommandString() && !WantsCompletion()) {281    // FIXME: Abstract telling the completion to insert the completion282    // character.283    return;284  } else {285    // Can we do anything generic with the options?286    Options *cur_options = GetOptions();287    OptionElementVector opt_element_vector;288 289    if (cur_options != nullptr) {290      opt_element_vector = cur_options->ParseForCompletion(291          request.GetParsedLine(), request.GetCursorIndex());292 293      bool handled_by_options = cur_options->HandleOptionCompletion(294          request, opt_element_vector, GetCommandInterpreter());295      if (handled_by_options)296        return;297    }298 299    // If we got here, the last word is not an option or an option argument.300    HandleArgumentCompletion(request, opt_element_vector);301  }302}303 304void CommandObject::HandleArgumentCompletion(305    CompletionRequest &request, OptionElementVector &opt_element_vector) {306  size_t num_arg_entries = GetNumArgumentEntries();307  if (num_arg_entries != 1)308    return;309 310  CommandArgumentEntry *entry_ptr = GetArgumentEntryAtIndex(0);311  if (!entry_ptr) {312    assert(entry_ptr && "We said there was one entry, but there wasn't.");313    return; // Not worth crashing if asserts are off...314  }315  316  CommandArgumentEntry &entry = *entry_ptr;317  // For now, we only handle the simple case of one homogenous argument type.318  if (entry.size() != 1)319    return;320 321  // Look up the completion type, and if it has one, invoke it:322  const CommandObject::ArgumentTableEntry *arg_entry =323      FindArgumentDataByType(entry[0].arg_type);324  const ArgumentRepetitionType repeat = entry[0].arg_repetition;325 326  if (arg_entry == nullptr || arg_entry->completion_type == lldb::eNoCompletion)327    return;328 329  // FIXME: This should be handled higher in the Command Parser.330  // Check the case where this command only takes one argument, and don't do331  // the completion if we aren't on the first entry:332  if (repeat == eArgRepeatPlain && request.GetCursorIndex() != 0)333    return;334 335  lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(336      GetCommandInterpreter(), arg_entry->completion_type, request, nullptr);337 338}339 340bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,341                                         bool search_short_help,342                                         bool search_long_help,343                                         bool search_syntax,344                                         bool search_options) {345  bool found_word = false;346 347  llvm::StringRef short_help = GetHelp();348  llvm::StringRef long_help = GetHelpLong();349  llvm::StringRef syntax_help = GetSyntax();350 351  if (search_short_help && short_help.contains_insensitive(search_word))352    found_word = true;353  else if (search_long_help && long_help.contains_insensitive(search_word))354    found_word = true;355  else if (search_syntax && syntax_help.contains_insensitive(search_word))356    found_word = true;357 358  if (!found_word && search_options && GetOptions() != nullptr) {359    StreamString usage_help;360    GetOptions()->GenerateOptionUsage(361        usage_help, *this,362        GetCommandInterpreter().GetDebugger().GetTerminalWidth(),363        GetCommandInterpreter().GetDebugger().GetUseColor());364    if (!usage_help.Empty()) {365      llvm::StringRef usage_text = usage_help.GetString();366      if (usage_text.contains_insensitive(search_word))367        found_word = true;368    }369  }370 371  return found_word;372}373 374bool CommandObject::ParseOptionsAndNotify(Args &args,375                                          CommandReturnObject &result,376                                          OptionGroupOptions &group_options,377                                          ExecutionContext &exe_ctx) {378  if (!ParseOptions(args, result))379    return false;380 381  Status error(group_options.NotifyOptionParsingFinished(&exe_ctx));382  if (error.Fail()) {383    result.AppendError(error.AsCString());384    return false;385  }386  return true;387}388 389void CommandObject::AddSimpleArgumentList(390    CommandArgumentType arg_type, ArgumentRepetitionType repetition_type) {391 392  CommandArgumentEntry arg_entry;393  CommandArgumentData simple_arg;394 395  // Define the first (and only) variant of this arg.396  simple_arg.arg_type = arg_type;397  simple_arg.arg_repetition = repetition_type;398 399  // There is only one variant this argument could be; put it into the argument400  // entry.401  arg_entry.push_back(simple_arg);402 403  // Push the data for the first argument into the m_arguments vector.404  m_arguments.push_back(arg_entry);405}406 407int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); }408 409CommandObject::CommandArgumentEntry *410CommandObject::GetArgumentEntryAtIndex(int idx) {411  if (static_cast<size_t>(idx) < m_arguments.size())412    return &(m_arguments[idx]);413 414  return nullptr;415}416 417const CommandObject::ArgumentTableEntry *418CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) {419  for (int i = 0; i < eArgTypeLastArg; ++i)420    if (g_argument_table[i].arg_type == arg_type)421      return &(g_argument_table[i]);422 423  return nullptr;424}425 426void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type,427                                    CommandInterpreter &interpreter) {428  const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);429 430  // The table is *supposed* to be kept in arg_type order, but someone *could*431  // have messed it up...432 433  if (entry->arg_type != arg_type)434    entry = CommandObject::FindArgumentDataByType(arg_type);435 436  if (!entry)437    return;438 439  StreamString name_str;440  name_str.Printf("<%s>", entry->arg_name);441 442  if (entry->help_function) {443    llvm::StringRef help_text = entry->help_function();444    if (!entry->help_function.self_formatting) {445      interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",446                                          help_text, name_str.GetSize());447    } else {448      interpreter.OutputHelpText(str, name_str.GetString(), "--", help_text,449                                 name_str.GetSize());450    }451  } else {452    interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",453                                        entry->help_text, name_str.GetSize());454 455    // Print enum values and their description if any.456    OptionEnumValues enum_values = g_argument_table[arg_type].enum_values;457    if (!enum_values.empty()) {458      str.EOL();459      size_t longest = 0;460      for (const OptionEnumValueElement &element : enum_values)461        longest =462            std::max(longest, llvm::StringRef(element.string_value).size());463      str.IndentMore(5);464      for (const OptionEnumValueElement &element : enum_values) {465        str.Indent();466        interpreter.OutputHelpText(str, element.string_value, ":",467                                   element.usage, longest);468      }469      str.IndentLess(5);470      str.EOL();471    }472  }473}474 475const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) {476  const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);477 478  // The table is *supposed* to be kept in arg_type order, but someone *could*479  // have messed it up...480 481  if (entry->arg_type != arg_type)482    entry = CommandObject::FindArgumentDataByType(arg_type);483 484  if (entry)485    return entry->arg_name;486 487  return nullptr;488}489 490bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) {491  return (arg_repeat_type == eArgRepeatPairPlain) ||492         (arg_repeat_type == eArgRepeatPairOptional) ||493         (arg_repeat_type == eArgRepeatPairPlus) ||494         (arg_repeat_type == eArgRepeatPairStar) ||495         (arg_repeat_type == eArgRepeatPairRange) ||496         (arg_repeat_type == eArgRepeatPairRangeOptional);497}498 499std::optional<ArgumentRepetitionType> 500CommandObject::ArgRepetitionFromString(llvm::StringRef string) {501  return llvm::StringSwitch<ArgumentRepetitionType>(string)502  .Case("plain", eArgRepeatPlain)  503  .Case("optional", eArgRepeatOptional)504  .Case("plus", eArgRepeatPlus)505  .Case("star", eArgRepeatStar) 506  .Case("range", eArgRepeatRange)507  .Case("pair-plain", eArgRepeatPairPlain)508  .Case("pair-optional", eArgRepeatPairOptional)509  .Case("pair-plus", eArgRepeatPairPlus)510  .Case("pair-star", eArgRepeatPairStar)511  .Case("pair-range", eArgRepeatPairRange)512  .Case("pair-range-optional", eArgRepeatPairRangeOptional)513  .Default({});514}515 516static CommandObject::CommandArgumentEntry517OptSetFiltered(uint32_t opt_set_mask,518               CommandObject::CommandArgumentEntry &cmd_arg_entry) {519  CommandObject::CommandArgumentEntry ret_val;520  for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)521    if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)522      ret_val.push_back(cmd_arg_entry[i]);523  return ret_val;524}525 526// Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means527// take all the argument data into account.  On rare cases where some argument528// sticks with certain option sets, this function returns the option set529// filtered args.530void CommandObject::GetFormattedCommandArguments(Stream &str,531                                                 uint32_t opt_set_mask) {532  int num_args = m_arguments.size();533  for (int i = 0; i < num_args; ++i) {534    if (i > 0)535      str.Printf(" ");536    CommandArgumentEntry arg_entry =537        opt_set_mask == LLDB_OPT_SET_ALL538            ? m_arguments[i]539            : OptSetFiltered(opt_set_mask, m_arguments[i]);540    // This argument is not associated with the current option set, so skip it.541    if (arg_entry.empty())542      continue;543    int num_alternatives = arg_entry.size();544 545    if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) {546      const char *first_name = GetArgumentName(arg_entry[0].arg_type);547      const char *second_name = GetArgumentName(arg_entry[1].arg_type);548      switch (arg_entry[0].arg_repetition) {549      case eArgRepeatPairPlain:550        str.Printf("<%s> <%s>", first_name, second_name);551        break;552      case eArgRepeatPairOptional:553        str.Printf("[<%s> <%s>]", first_name, second_name);554        break;555      case eArgRepeatPairPlus:556        str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name,557                   first_name, second_name);558        break;559      case eArgRepeatPairStar:560        str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name,561                   first_name, second_name);562        break;563      case eArgRepeatPairRange:564        str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name,565                   first_name, second_name);566        break;567      case eArgRepeatPairRangeOptional:568        str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name,569                   first_name, second_name);570        break;571      // Explicitly test for all the rest of the cases, so if new types get572      // added we will notice the missing case statement(s).573      case eArgRepeatPlain:574      case eArgRepeatOptional:575      case eArgRepeatPlus:576      case eArgRepeatStar:577      case eArgRepeatRange:578        // These should not be reached, as they should fail the IsPairType test579        // above.580        break;581      }582    } else {583      StreamString names;584      for (int j = 0; j < num_alternatives; ++j) {585        if (j > 0)586          names.Printf(" | ");587        names.Printf("%s", GetArgumentName(arg_entry[j].arg_type));588      }589 590      std::string name_str = std::string(names.GetString());591      switch (arg_entry[0].arg_repetition) {592      case eArgRepeatPlain:593        str.Printf("<%s>", name_str.c_str());594        break;595      case eArgRepeatPlus:596        str.Printf("<%s> [<%s> [...]]", name_str.c_str(), name_str.c_str());597        break;598      case eArgRepeatStar:599        str.Printf("[<%s> [<%s> [...]]]", name_str.c_str(), name_str.c_str());600        break;601      case eArgRepeatOptional:602        str.Printf("[<%s>]", name_str.c_str());603        break;604      case eArgRepeatRange:605        str.Printf("<%s_1> .. <%s_n>", name_str.c_str(), name_str.c_str());606        break;607      // Explicitly test for all the rest of the cases, so if new types get608      // added we will notice the missing case statement(s).609      case eArgRepeatPairPlain:610      case eArgRepeatPairOptional:611      case eArgRepeatPairPlus:612      case eArgRepeatPairStar:613      case eArgRepeatPairRange:614      case eArgRepeatPairRangeOptional:615        // These should not be hit, as they should pass the IsPairType test616        // above, and control should have gone into the other branch of the if617        // statement.618        break;619      }620    }621  }622}623 624CommandArgumentType625CommandObject::LookupArgumentName(llvm::StringRef arg_name) {626  CommandArgumentType return_type = eArgTypeLastArg;627 628  arg_name = arg_name.ltrim('<').rtrim('>');629 630  for (int i = 0; i < eArgTypeLastArg; ++i)631    if (arg_name == g_argument_table[i].arg_name)632      return_type = g_argument_table[i].arg_type;633 634  return return_type;635}636 637void CommandObject::FormatLongHelpText(Stream &output_strm,638                                       llvm::StringRef long_help) {639  CommandInterpreter &interpreter = GetCommandInterpreter();640  std::stringstream lineStream{std::string(long_help)};641  std::string line;642  while (std::getline(lineStream, line)) {643    if (line.empty()) {644      output_strm << "\n";645      continue;646    }647    size_t result = line.find_first_not_of(" \t");648    if (result == std::string::npos) {649      result = 0;650    }651    std::string whitespace_prefix = line.substr(0, result);652    std::string remainder = line.substr(result);653    interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix,654                                        remainder);655  }656}657 658void CommandObject::GenerateHelpText(CommandReturnObject &result) {659  GenerateHelpText(result.GetOutputStream());660 661  result.SetStatus(eReturnStatusSuccessFinishNoResult);662}663 664void CommandObject::GenerateHelpText(Stream &output_strm) {665  CommandInterpreter &interpreter = GetCommandInterpreter();666  std::string help_text(GetHelp());667  if (WantsRawCommandString()) {668    help_text.append("  Expects 'raw' input (see 'help raw-input'.)");669  }670  interpreter.OutputFormattedHelpText(output_strm, "", help_text);671  output_strm << "\nSyntax: " << GetSyntax() << "\n";672  Options *options = GetOptions();673  if (options != nullptr) {674    options->GenerateOptionUsage(675        output_strm, *this,676        GetCommandInterpreter().GetDebugger().GetTerminalWidth(),677        GetCommandInterpreter().GetDebugger().GetUseColor());678  }679  llvm::StringRef long_help = GetHelpLong();680  if (!long_help.empty()) {681    FormatLongHelpText(output_strm, long_help);682  }683  if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) {684    if (WantsRawCommandString() && !WantsCompletion()) {685      // Emit the message about using ' -- ' between the end of the command686      // options and the raw input conditionally, i.e., only if the command687      // object does not want completion.688      interpreter.OutputFormattedHelpText(689          output_strm, "", "",690          "\nImportant Note: Because this command takes 'raw' input, if you "691          "use any command options"692          " you must use ' -- ' between the end of the command options and the "693          "beginning of the raw input.",694          1);695    } else if (GetNumArgumentEntries() > 0) {696      // Also emit a warning about using "--" in case you are using a command697      // that takes options and arguments.698      interpreter.OutputFormattedHelpText(699          output_strm, "", "",700          "\nThis command takes options and free-form arguments.  If your "701          "arguments resemble"702          " option specifiers (i.e., they start with a - or --), you must use "703          "' -- ' between"704          " the end of the command options and the beginning of the arguments.",705          1);706    }707  }708}709 710void CommandObject::AddIDsArgumentData(CommandObject::IDType type) {711  CommandArgumentEntry arg;712  CommandArgumentData id_arg;713  CommandArgumentData id_range_arg;714 715  // Create the first variant for the first (and only) argument for this716  // command.717  switch (type) {718  case eBreakpointArgs:719    id_arg.arg_type = eArgTypeBreakpointID;720    id_range_arg.arg_type = eArgTypeBreakpointIDRange;721    break;722  case eWatchpointArgs:723    id_arg.arg_type = eArgTypeWatchpointID;724    id_range_arg.arg_type = eArgTypeWatchpointIDRange;725    break;726  }727  id_arg.arg_repetition = eArgRepeatOptional;728  id_range_arg.arg_repetition = eArgRepeatOptional;729 730  // The first (and only) argument for this command could be either an id or an731  // id_range. Push both variants into the entry for the first argument for732  // this command.733  arg.push_back(id_arg);734  arg.push_back(id_range_arg);735  m_arguments.push_back(arg);736}737 738const char *CommandObject::GetArgumentTypeAsCString(739    const lldb::CommandArgumentType arg_type) {740  assert(arg_type < eArgTypeLastArg &&741         "Invalid argument type passed to GetArgumentTypeAsCString");742  return g_argument_table[arg_type].arg_name;743}744 745const char *CommandObject::GetArgumentDescriptionAsCString(746    const lldb::CommandArgumentType arg_type) {747  assert(arg_type < eArgTypeLastArg &&748         "Invalid argument type passed to GetArgumentDescriptionAsCString");749  return g_argument_table[arg_type].help_text;750}751 752Target &CommandObject::GetDummyTarget() {753  return m_interpreter.GetDebugger().GetDummyTarget();754}755 756Target &CommandObject::GetTarget() {757  // Prefer the frozen execution context in the command object.758  if (Target *target = m_exe_ctx.GetTargetPtr())759    return *target;760 761  // Fallback to the command interpreter's execution context in case we get762  // called after DoExecute has finished. For example, when doing multi-line763  // expression that uses an input reader or breakpoint callbacks.764  if (Target *target = m_interpreter.GetExecutionContext().GetTargetPtr())765    return *target;766 767  // Finally, if we have no other target, get the selected target.768  if (TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget())769    return *target_sp;770 771  // We only have the dummy target.772  return GetDummyTarget();773}774 775Thread *CommandObject::GetDefaultThread() {776  Thread *thread_to_use = m_exe_ctx.GetThreadPtr();777  if (thread_to_use)778    return thread_to_use;779 780  Process *process = m_exe_ctx.GetProcessPtr();781  if (!process) {782    Target *target = m_exe_ctx.GetTargetPtr();783    if (!target) {784      target = m_interpreter.GetDebugger().GetSelectedTarget().get();785    }786    if (target)787      process = target->GetProcessSP().get();788  }789 790  if (process)791    return process->GetThreadList().GetSelectedThread().get();792  else793    return nullptr;794}795 796void CommandObjectParsed::Execute(const char *args_string,797                                  CommandReturnObject &result) {798  bool handled = false;799  Args cmd_args(args_string);800  if (HasOverrideCallback()) {801    Args full_args(GetCommandName());802    full_args.AppendArguments(cmd_args);803    handled =804        InvokeOverrideCallback(full_args.GetConstArgumentVector(), result);805  }806  if (!handled) {807    for (auto entry : llvm::enumerate(cmd_args.entries())) {808      const Args::ArgEntry &value = entry.value();809      if (!value.ref().empty() && value.GetQuoteChar() == '`') {810        // We have to put the backtick back in place for PreprocessCommand.811        std::string opt_string = value.c_str();812        Status error;813        error = m_interpreter.PreprocessToken(opt_string);814        if (error.Success())815          cmd_args.ReplaceArgumentAtIndex(entry.index(), opt_string);816      }817    }818 819    if (CheckRequirements(result)) {820      if (ParseOptions(cmd_args, result)) {821        // Call the command-specific version of 'Execute', passing it the822        // already processed arguments.823        if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) {824          result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.",825                                        GetCommandName());826          Cleanup();827          return;828        }829        m_interpreter.IncreaseCommandUsage(*this);830        DoExecute(cmd_args, result);831      }832    }833 834    Cleanup();835  }836}837 838void CommandObjectRaw::Execute(const char *args_string,839                               CommandReturnObject &result) {840  bool handled = false;841  if (HasOverrideCallback()) {842    std::string full_command(GetCommandName());843    full_command += ' ';844    full_command += args_string;845    const char *argv[2] = {nullptr, nullptr};846    argv[0] = full_command.c_str();847    handled = InvokeOverrideCallback(argv, result);848  }849  if (!handled) {850    if (CheckRequirements(result))851      DoExecute(args_string, result);852 853    Cleanup();854  }855}856