15ffd83dbSDimitry Andric //===-- CommandObject.cpp -------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Interpreter/CommandObject.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include <map>
120b57cec5SDimitry Andric #include <sstream>
130b57cec5SDimitry Andric #include <string>
140b57cec5SDimitry Andric 
15fe6060f1SDimitry Andric #include <cctype>
16fe6060f1SDimitry Andric #include <cstdlib>
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "lldb/Core/Address.h"
19fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
200b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h"
210b57cec5SDimitry Andric #include "lldb/Utility/ArchSpec.h"
225ffd83dbSDimitry Andric #include "llvm/ADT/ScopeExit.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric // These are for the Sourcename completers.
250b57cec5SDimitry Andric // FIXME: Make a separate file for the completers.
260b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatManager.h"
270b57cec5SDimitry Andric #include "lldb/Target/Process.h"
280b57cec5SDimitry Andric #include "lldb/Target/Target.h"
290b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h"
30fe013be4SDimitry Andric #include "lldb/Utility/FileSpecList.h"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric #include "lldb/Target/Language.h"
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
35fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
360b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric using namespace lldb;
390b57cec5SDimitry Andric using namespace lldb_private;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric // CommandObject
420b57cec5SDimitry Andric 
CommandObject(CommandInterpreter & interpreter,llvm::StringRef name,llvm::StringRef help,llvm::StringRef syntax,uint32_t flags)435ffd83dbSDimitry Andric CommandObject::CommandObject(CommandInterpreter &interpreter,
445ffd83dbSDimitry Andric                              llvm::StringRef name, llvm::StringRef help,
455ffd83dbSDimitry Andric                              llvm::StringRef syntax, uint32_t flags)
465ffd83dbSDimitry Andric     : m_interpreter(interpreter), m_cmd_name(std::string(name)),
47fe6060f1SDimitry Andric       m_flags(flags), m_deprecated_command_override_callback(nullptr),
480b57cec5SDimitry Andric       m_command_override_callback(nullptr), m_command_override_baton(nullptr) {
495ffd83dbSDimitry Andric   m_cmd_help_short = std::string(help);
505ffd83dbSDimitry Andric   m_cmd_syntax = std::string(syntax);
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
GetDebugger()530b57cec5SDimitry Andric Debugger &CommandObject::GetDebugger() { return m_interpreter.GetDebugger(); }
540b57cec5SDimitry Andric 
GetHelp()550b57cec5SDimitry Andric llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; }
560b57cec5SDimitry Andric 
GetHelpLong()570b57cec5SDimitry Andric llvm::StringRef CommandObject::GetHelpLong() { return m_cmd_help_long; }
580b57cec5SDimitry Andric 
GetSyntax()590b57cec5SDimitry Andric llvm::StringRef CommandObject::GetSyntax() {
600b57cec5SDimitry Andric   if (!m_cmd_syntax.empty())
610b57cec5SDimitry Andric     return m_cmd_syntax;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   StreamString syntax_str;
640b57cec5SDimitry Andric   syntax_str.PutCString(GetCommandName());
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   if (!IsDashDashCommand() && GetOptions() != nullptr)
670b57cec5SDimitry Andric     syntax_str.PutCString(" <cmd-options>");
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   if (!m_arguments.empty()) {
700b57cec5SDimitry Andric     syntax_str.PutCString(" ");
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric     if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() &&
730b57cec5SDimitry Andric         GetOptions()->NumCommandOptions())
740b57cec5SDimitry Andric       syntax_str.PutCString("-- ");
750b57cec5SDimitry Andric     GetFormattedCommandArguments(syntax_str);
760b57cec5SDimitry Andric   }
775ffd83dbSDimitry Andric   m_cmd_syntax = std::string(syntax_str.GetString());
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   return m_cmd_syntax;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
GetCommandName() const820b57cec5SDimitry Andric llvm::StringRef CommandObject::GetCommandName() const { return m_cmd_name; }
830b57cec5SDimitry Andric 
SetCommandName(llvm::StringRef name)845ffd83dbSDimitry Andric void CommandObject::SetCommandName(llvm::StringRef name) {
855ffd83dbSDimitry Andric   m_cmd_name = std::string(name);
865ffd83dbSDimitry Andric }
870b57cec5SDimitry Andric 
SetHelp(llvm::StringRef str)885ffd83dbSDimitry Andric void CommandObject::SetHelp(llvm::StringRef str) {
895ffd83dbSDimitry Andric   m_cmd_help_short = std::string(str);
905ffd83dbSDimitry Andric }
910b57cec5SDimitry Andric 
SetHelpLong(llvm::StringRef str)925ffd83dbSDimitry Andric void CommandObject::SetHelpLong(llvm::StringRef str) {
935ffd83dbSDimitry Andric   m_cmd_help_long = std::string(str);
945ffd83dbSDimitry Andric }
950b57cec5SDimitry Andric 
SetSyntax(llvm::StringRef str)965ffd83dbSDimitry Andric void CommandObject::SetSyntax(llvm::StringRef str) {
975ffd83dbSDimitry Andric   m_cmd_syntax = std::string(str);
985ffd83dbSDimitry Andric }
990b57cec5SDimitry Andric 
GetOptions()1000b57cec5SDimitry Andric Options *CommandObject::GetOptions() {
1010b57cec5SDimitry Andric   // By default commands don't have options unless this virtual function is
1020b57cec5SDimitry Andric   // overridden by base classes.
1030b57cec5SDimitry Andric   return nullptr;
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
ParseOptions(Args & args,CommandReturnObject & result)1060b57cec5SDimitry Andric bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
1070b57cec5SDimitry Andric   // See if the subclass has options?
1080b57cec5SDimitry Andric   Options *options = GetOptions();
1090b57cec5SDimitry Andric   if (options != nullptr) {
1100b57cec5SDimitry Andric     Status error;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
1130b57cec5SDimitry Andric     options->NotifyOptionParsingStarting(&exe_ctx);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     const bool require_validation = true;
1160b57cec5SDimitry Andric     llvm::Expected<Args> args_or = options->Parse(
1170b57cec5SDimitry Andric         args, &exe_ctx, GetCommandInterpreter().GetPlatform(true),
1180b57cec5SDimitry Andric         require_validation);
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric     if (args_or) {
1210b57cec5SDimitry Andric       args = std::move(*args_or);
1220b57cec5SDimitry Andric       error = options->NotifyOptionParsingFinished(&exe_ctx);
1230b57cec5SDimitry Andric     } else
1240b57cec5SDimitry Andric       error = args_or.takeError();
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric     if (error.Success()) {
1270b57cec5SDimitry Andric       if (options->VerifyOptions(result))
1280b57cec5SDimitry Andric         return true;
1290b57cec5SDimitry Andric     } else {
1300b57cec5SDimitry Andric       const char *error_cstr = error.AsCString();
1310b57cec5SDimitry Andric       if (error_cstr) {
1320b57cec5SDimitry Andric         // We got an error string, lets use that
1330b57cec5SDimitry Andric         result.AppendError(error_cstr);
1340b57cec5SDimitry Andric       } else {
1350b57cec5SDimitry Andric         // No error string, output the usage information into result
1360b57cec5SDimitry Andric         options->GenerateOptionUsage(
13781ad6265SDimitry Andric             result.GetErrorStream(), *this,
1380b57cec5SDimitry Andric             GetCommandInterpreter().GetDebugger().GetTerminalWidth());
1390b57cec5SDimitry Andric       }
1400b57cec5SDimitry Andric     }
1410b57cec5SDimitry Andric     result.SetStatus(eReturnStatusFailed);
1420b57cec5SDimitry Andric     return false;
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric   return true;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
CheckRequirements(CommandReturnObject & result)1470b57cec5SDimitry Andric bool CommandObject::CheckRequirements(CommandReturnObject &result) {
1480b57cec5SDimitry Andric   // Nothing should be stored in m_exe_ctx between running commands as
1490b57cec5SDimitry Andric   // m_exe_ctx has shared pointers to the target, process, thread and frame and
1500b57cec5SDimitry Andric   // we don't want any CommandObject instances to keep any of these objects
1510b57cec5SDimitry Andric   // around longer than for a single command. Every command should call
1520b57cec5SDimitry Andric   // CommandObject::Cleanup() after it has completed.
1530b57cec5SDimitry Andric   assert(!m_exe_ctx.GetTargetPtr());
1540b57cec5SDimitry Andric   assert(!m_exe_ctx.GetProcessPtr());
1550b57cec5SDimitry Andric   assert(!m_exe_ctx.GetThreadPtr());
1560b57cec5SDimitry Andric   assert(!m_exe_ctx.GetFramePtr());
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   // Lock down the interpreter's execution context prior to running the command
1590b57cec5SDimitry Andric   // so we guarantee the selected target, process, thread and frame can't go
1600b57cec5SDimitry Andric   // away during the execution
1610b57cec5SDimitry Andric   m_exe_ctx = m_interpreter.GetExecutionContext();
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   const uint32_t flags = GetFlags().Get();
1640b57cec5SDimitry Andric   if (flags & (eCommandRequiresTarget | eCommandRequiresProcess |
1650b57cec5SDimitry Andric                eCommandRequiresThread | eCommandRequiresFrame |
1660b57cec5SDimitry Andric                eCommandTryTargetAPILock)) {
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric     if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) {
1690b57cec5SDimitry Andric       result.AppendError(GetInvalidTargetDescription());
1700b57cec5SDimitry Andric       return false;
1710b57cec5SDimitry Andric     }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) {
1740b57cec5SDimitry Andric       if (!m_exe_ctx.HasTargetScope())
1750b57cec5SDimitry Andric         result.AppendError(GetInvalidTargetDescription());
1760b57cec5SDimitry Andric       else
1770b57cec5SDimitry Andric         result.AppendError(GetInvalidProcessDescription());
1780b57cec5SDimitry Andric       return false;
1790b57cec5SDimitry Andric     }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric     if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) {
1820b57cec5SDimitry Andric       if (!m_exe_ctx.HasTargetScope())
1830b57cec5SDimitry Andric         result.AppendError(GetInvalidTargetDescription());
1840b57cec5SDimitry Andric       else if (!m_exe_ctx.HasProcessScope())
1850b57cec5SDimitry Andric         result.AppendError(GetInvalidProcessDescription());
1860b57cec5SDimitry Andric       else
1870b57cec5SDimitry Andric         result.AppendError(GetInvalidThreadDescription());
1880b57cec5SDimitry Andric       return false;
1890b57cec5SDimitry Andric     }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric     if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) {
1920b57cec5SDimitry Andric       if (!m_exe_ctx.HasTargetScope())
1930b57cec5SDimitry Andric         result.AppendError(GetInvalidTargetDescription());
1940b57cec5SDimitry Andric       else if (!m_exe_ctx.HasProcessScope())
1950b57cec5SDimitry Andric         result.AppendError(GetInvalidProcessDescription());
1960b57cec5SDimitry Andric       else if (!m_exe_ctx.HasThreadScope())
1970b57cec5SDimitry Andric         result.AppendError(GetInvalidThreadDescription());
1980b57cec5SDimitry Andric       else
1990b57cec5SDimitry Andric         result.AppendError(GetInvalidFrameDescription());
2000b57cec5SDimitry Andric       return false;
2010b57cec5SDimitry Andric     }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric     if ((flags & eCommandRequiresRegContext) &&
2040b57cec5SDimitry Andric         (m_exe_ctx.GetRegisterContext() == nullptr)) {
2050b57cec5SDimitry Andric       result.AppendError(GetInvalidRegContextDescription());
2060b57cec5SDimitry Andric       return false;
2070b57cec5SDimitry Andric     }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     if (flags & eCommandTryTargetAPILock) {
2100b57cec5SDimitry Andric       Target *target = m_exe_ctx.GetTargetPtr();
2110b57cec5SDimitry Andric       if (target)
2120b57cec5SDimitry Andric         m_api_locker =
2130b57cec5SDimitry Andric             std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());
2140b57cec5SDimitry Andric     }
2150b57cec5SDimitry Andric   }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric   if (GetFlags().AnySet(eCommandProcessMustBeLaunched |
2180b57cec5SDimitry Andric                         eCommandProcessMustBePaused)) {
2190b57cec5SDimitry Andric     Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
2200b57cec5SDimitry Andric     if (process == nullptr) {
2210b57cec5SDimitry Andric       // A process that is not running is considered paused.
2220b57cec5SDimitry Andric       if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
2230b57cec5SDimitry Andric         result.AppendError("Process must exist.");
2240b57cec5SDimitry Andric         return false;
2250b57cec5SDimitry Andric       }
2260b57cec5SDimitry Andric     } else {
2270b57cec5SDimitry Andric       StateType state = process->GetState();
2280b57cec5SDimitry Andric       switch (state) {
2290b57cec5SDimitry Andric       case eStateInvalid:
2300b57cec5SDimitry Andric       case eStateSuspended:
2310b57cec5SDimitry Andric       case eStateCrashed:
2320b57cec5SDimitry Andric       case eStateStopped:
2330b57cec5SDimitry Andric         break;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric       case eStateConnected:
2360b57cec5SDimitry Andric       case eStateAttaching:
2370b57cec5SDimitry Andric       case eStateLaunching:
2380b57cec5SDimitry Andric       case eStateDetached:
2390b57cec5SDimitry Andric       case eStateExited:
2400b57cec5SDimitry Andric       case eStateUnloaded:
2410b57cec5SDimitry Andric         if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
2420b57cec5SDimitry Andric           result.AppendError("Process must be launched.");
2430b57cec5SDimitry Andric           return false;
2440b57cec5SDimitry Andric         }
2450b57cec5SDimitry Andric         break;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric       case eStateRunning:
2480b57cec5SDimitry Andric       case eStateStepping:
2490b57cec5SDimitry Andric         if (GetFlags().Test(eCommandProcessMustBePaused)) {
2500b57cec5SDimitry Andric           result.AppendError("Process is running.  Use 'process interrupt' to "
2510b57cec5SDimitry Andric                              "pause execution.");
2520b57cec5SDimitry Andric           return false;
2530b57cec5SDimitry Andric         }
2540b57cec5SDimitry Andric       }
2550b57cec5SDimitry Andric     }
2560b57cec5SDimitry Andric   }
257e8d8bef9SDimitry Andric 
258e8d8bef9SDimitry Andric   if (GetFlags().Test(eCommandProcessMustBeTraced)) {
259e8d8bef9SDimitry Andric     Target *target = m_exe_ctx.GetTargetPtr();
260e8d8bef9SDimitry Andric     if (target && !target->GetTrace()) {
261fe6060f1SDimitry Andric       result.AppendError("Process is not being traced.");
262e8d8bef9SDimitry Andric       return false;
263e8d8bef9SDimitry Andric     }
264e8d8bef9SDimitry Andric   }
265e8d8bef9SDimitry Andric 
2660b57cec5SDimitry Andric   return true;
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric 
Cleanup()2690b57cec5SDimitry Andric void CommandObject::Cleanup() {
2700b57cec5SDimitry Andric   m_exe_ctx.Clear();
2710b57cec5SDimitry Andric   if (m_api_locker.owns_lock())
2720b57cec5SDimitry Andric     m_api_locker.unlock();
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric 
HandleCompletion(CompletionRequest & request)2759dba64beSDimitry Andric void CommandObject::HandleCompletion(CompletionRequest &request) {
2765ffd83dbSDimitry Andric 
2775ffd83dbSDimitry Andric   m_exe_ctx = m_interpreter.GetExecutionContext();
2785ffd83dbSDimitry Andric   auto reset_ctx = llvm::make_scope_exit([this]() { Cleanup(); });
2795ffd83dbSDimitry Andric 
2800b57cec5SDimitry Andric   // Default implementation of WantsCompletion() is !WantsRawCommandString().
2810b57cec5SDimitry Andric   // Subclasses who want raw command string but desire, for example, argument
2820b57cec5SDimitry Andric   // completion should override WantsCompletion() to return true, instead.
2830b57cec5SDimitry Andric   if (WantsRawCommandString() && !WantsCompletion()) {
2840b57cec5SDimitry Andric     // FIXME: Abstract telling the completion to insert the completion
2850b57cec5SDimitry Andric     // character.
2869dba64beSDimitry Andric     return;
2870b57cec5SDimitry Andric   } else {
2880b57cec5SDimitry Andric     // Can we do anything generic with the options?
2890b57cec5SDimitry Andric     Options *cur_options = GetOptions();
2905ffd83dbSDimitry Andric     CommandReturnObject result(m_interpreter.GetDebugger().GetUseColor());
2910b57cec5SDimitry Andric     OptionElementVector opt_element_vector;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric     if (cur_options != nullptr) {
2940b57cec5SDimitry Andric       opt_element_vector = cur_options->ParseForCompletion(
2950b57cec5SDimitry Andric           request.GetParsedLine(), request.GetCursorIndex());
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric       bool handled_by_options = cur_options->HandleOptionCompletion(
2980b57cec5SDimitry Andric           request, opt_element_vector, GetCommandInterpreter());
2990b57cec5SDimitry Andric       if (handled_by_options)
3009dba64beSDimitry Andric         return;
3010b57cec5SDimitry Andric     }
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric     // If we got here, the last word is not an option or an option argument.
3049dba64beSDimitry Andric     HandleArgumentCompletion(request, opt_element_vector);
3050b57cec5SDimitry Andric   }
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric 
HelpTextContainsWord(llvm::StringRef search_word,bool search_short_help,bool search_long_help,bool search_syntax,bool search_options)3080b57cec5SDimitry Andric bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
3090b57cec5SDimitry Andric                                          bool search_short_help,
3100b57cec5SDimitry Andric                                          bool search_long_help,
3110b57cec5SDimitry Andric                                          bool search_syntax,
3120b57cec5SDimitry Andric                                          bool search_options) {
3130b57cec5SDimitry Andric   std::string options_usage_help;
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   bool found_word = false;
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   llvm::StringRef short_help = GetHelp();
3180b57cec5SDimitry Andric   llvm::StringRef long_help = GetHelpLong();
3190b57cec5SDimitry Andric   llvm::StringRef syntax_help = GetSyntax();
3200b57cec5SDimitry Andric 
321fe6060f1SDimitry Andric   if (search_short_help && short_help.contains_insensitive(search_word))
3220b57cec5SDimitry Andric     found_word = true;
323fe6060f1SDimitry Andric   else if (search_long_help && long_help.contains_insensitive(search_word))
3240b57cec5SDimitry Andric     found_word = true;
325fe6060f1SDimitry Andric   else if (search_syntax && syntax_help.contains_insensitive(search_word))
3260b57cec5SDimitry Andric     found_word = true;
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   if (!found_word && search_options && GetOptions() != nullptr) {
3290b57cec5SDimitry Andric     StreamString usage_help;
3300b57cec5SDimitry Andric     GetOptions()->GenerateOptionUsage(
33181ad6265SDimitry Andric         usage_help, *this,
3320b57cec5SDimitry Andric         GetCommandInterpreter().GetDebugger().GetTerminalWidth());
3330b57cec5SDimitry Andric     if (!usage_help.Empty()) {
3340b57cec5SDimitry Andric       llvm::StringRef usage_text = usage_help.GetString();
335fe6060f1SDimitry Andric       if (usage_text.contains_insensitive(search_word))
3360b57cec5SDimitry Andric         found_word = true;
3370b57cec5SDimitry Andric     }
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   return found_word;
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric 
ParseOptionsAndNotify(Args & args,CommandReturnObject & result,OptionGroupOptions & group_options,ExecutionContext & exe_ctx)3430b57cec5SDimitry Andric bool CommandObject::ParseOptionsAndNotify(Args &args,
3440b57cec5SDimitry Andric                                           CommandReturnObject &result,
3450b57cec5SDimitry Andric                                           OptionGroupOptions &group_options,
3460b57cec5SDimitry Andric                                           ExecutionContext &exe_ctx) {
3470b57cec5SDimitry Andric   if (!ParseOptions(args, result))
3480b57cec5SDimitry Andric     return false;
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   Status error(group_options.NotifyOptionParsingFinished(&exe_ctx));
3510b57cec5SDimitry Andric   if (error.Fail()) {
3520b57cec5SDimitry Andric     result.AppendError(error.AsCString());
3530b57cec5SDimitry Andric     return false;
3540b57cec5SDimitry Andric   }
3550b57cec5SDimitry Andric   return true;
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric 
GetNumArgumentEntries()3580b57cec5SDimitry Andric int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric CommandObject::CommandArgumentEntry *
GetArgumentEntryAtIndex(int idx)3610b57cec5SDimitry Andric CommandObject::GetArgumentEntryAtIndex(int idx) {
3620b57cec5SDimitry Andric   if (static_cast<size_t>(idx) < m_arguments.size())
3630b57cec5SDimitry Andric     return &(m_arguments[idx]);
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   return nullptr;
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric const CommandObject::ArgumentTableEntry *
FindArgumentDataByType(CommandArgumentType arg_type)3690b57cec5SDimitry Andric CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) {
3700b57cec5SDimitry Andric   for (int i = 0; i < eArgTypeLastArg; ++i)
371fcaf7f86SDimitry Andric     if (g_argument_table[i].arg_type == arg_type)
372fcaf7f86SDimitry Andric       return &(g_argument_table[i]);
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   return nullptr;
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
GetArgumentHelp(Stream & str,CommandArgumentType arg_type,CommandInterpreter & interpreter)3770b57cec5SDimitry Andric void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type,
3780b57cec5SDimitry Andric                                     CommandInterpreter &interpreter) {
379fcaf7f86SDimitry Andric   const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   // The table is *supposed* to be kept in arg_type order, but someone *could*
3820b57cec5SDimitry Andric   // have messed it up...
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   if (entry->arg_type != arg_type)
3850b57cec5SDimitry Andric     entry = CommandObject::FindArgumentDataByType(arg_type);
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   if (!entry)
3880b57cec5SDimitry Andric     return;
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric   StreamString name_str;
3910b57cec5SDimitry Andric   name_str.Printf("<%s>", entry->arg_name);
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   if (entry->help_function) {
3940b57cec5SDimitry Andric     llvm::StringRef help_text = entry->help_function();
3950b57cec5SDimitry Andric     if (!entry->help_function.self_formatting) {
3960b57cec5SDimitry Andric       interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
3970b57cec5SDimitry Andric                                           help_text, name_str.GetSize());
3980b57cec5SDimitry Andric     } else {
3990b57cec5SDimitry Andric       interpreter.OutputHelpText(str, name_str.GetString(), "--", help_text,
4000b57cec5SDimitry Andric                                  name_str.GetSize());
4010b57cec5SDimitry Andric     }
402fcaf7f86SDimitry Andric   } else {
4030b57cec5SDimitry Andric     interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
4040b57cec5SDimitry Andric                                         entry->help_text, name_str.GetSize());
405fcaf7f86SDimitry Andric 
406fcaf7f86SDimitry Andric     // Print enum values and their description if any.
407fcaf7f86SDimitry Andric     OptionEnumValues enum_values = g_argument_table[arg_type].enum_values;
408fcaf7f86SDimitry Andric     if (!enum_values.empty()) {
409fcaf7f86SDimitry Andric       str.EOL();
410fcaf7f86SDimitry Andric       size_t longest = 0;
411fcaf7f86SDimitry Andric       for (const OptionEnumValueElement &element : enum_values)
412fcaf7f86SDimitry Andric         longest =
413fcaf7f86SDimitry Andric             std::max(longest, llvm::StringRef(element.string_value).size());
414fcaf7f86SDimitry Andric       str.IndentMore(5);
415fcaf7f86SDimitry Andric       for (const OptionEnumValueElement &element : enum_values) {
416fcaf7f86SDimitry Andric         str.Indent();
417fcaf7f86SDimitry Andric         interpreter.OutputHelpText(str, element.string_value, ":",
418fcaf7f86SDimitry Andric                                    element.usage, longest);
419fcaf7f86SDimitry Andric       }
420fcaf7f86SDimitry Andric       str.IndentLess(5);
421fcaf7f86SDimitry Andric       str.EOL();
422fcaf7f86SDimitry Andric     }
423fcaf7f86SDimitry Andric   }
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric 
GetArgumentName(CommandArgumentType arg_type)4260b57cec5SDimitry Andric const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) {
427fcaf7f86SDimitry Andric   const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   // The table is *supposed* to be kept in arg_type order, but someone *could*
4300b57cec5SDimitry Andric   // have messed it up...
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   if (entry->arg_type != arg_type)
4330b57cec5SDimitry Andric     entry = CommandObject::FindArgumentDataByType(arg_type);
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   if (entry)
4360b57cec5SDimitry Andric     return entry->arg_name;
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   return nullptr;
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric 
IsPairType(ArgumentRepetitionType arg_repeat_type)4410b57cec5SDimitry Andric bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) {
4420b57cec5SDimitry Andric   return (arg_repeat_type == eArgRepeatPairPlain) ||
4430b57cec5SDimitry Andric          (arg_repeat_type == eArgRepeatPairOptional) ||
4440b57cec5SDimitry Andric          (arg_repeat_type == eArgRepeatPairPlus) ||
4450b57cec5SDimitry Andric          (arg_repeat_type == eArgRepeatPairStar) ||
4460b57cec5SDimitry Andric          (arg_repeat_type == eArgRepeatPairRange) ||
4470b57cec5SDimitry Andric          (arg_repeat_type == eArgRepeatPairRangeOptional);
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric static CommandObject::CommandArgumentEntry
OptSetFiltered(uint32_t opt_set_mask,CommandObject::CommandArgumentEntry & cmd_arg_entry)4510b57cec5SDimitry Andric OptSetFiltered(uint32_t opt_set_mask,
4520b57cec5SDimitry Andric                CommandObject::CommandArgumentEntry &cmd_arg_entry) {
4530b57cec5SDimitry Andric   CommandObject::CommandArgumentEntry ret_val;
4540b57cec5SDimitry Andric   for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
4550b57cec5SDimitry Andric     if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
4560b57cec5SDimitry Andric       ret_val.push_back(cmd_arg_entry[i]);
4570b57cec5SDimitry Andric   return ret_val;
4580b57cec5SDimitry Andric }
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric // Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means
4610b57cec5SDimitry Andric // take all the argument data into account.  On rare cases where some argument
4620b57cec5SDimitry Andric // sticks with certain option sets, this function returns the option set
4630b57cec5SDimitry Andric // filtered args.
GetFormattedCommandArguments(Stream & str,uint32_t opt_set_mask)4640b57cec5SDimitry Andric void CommandObject::GetFormattedCommandArguments(Stream &str,
4650b57cec5SDimitry Andric                                                  uint32_t opt_set_mask) {
4660b57cec5SDimitry Andric   int num_args = m_arguments.size();
4670b57cec5SDimitry Andric   for (int i = 0; i < num_args; ++i) {
4680b57cec5SDimitry Andric     if (i > 0)
4690b57cec5SDimitry Andric       str.Printf(" ");
4700b57cec5SDimitry Andric     CommandArgumentEntry arg_entry =
4710b57cec5SDimitry Andric         opt_set_mask == LLDB_OPT_SET_ALL
4720b57cec5SDimitry Andric             ? m_arguments[i]
4730b57cec5SDimitry Andric             : OptSetFiltered(opt_set_mask, m_arguments[i]);
4744824e7fdSDimitry Andric     // This argument is not associated with the current option set, so skip it.
4754824e7fdSDimitry Andric     if (arg_entry.empty())
4764824e7fdSDimitry Andric       continue;
4770b57cec5SDimitry Andric     int num_alternatives = arg_entry.size();
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric     if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) {
4800b57cec5SDimitry Andric       const char *first_name = GetArgumentName(arg_entry[0].arg_type);
4810b57cec5SDimitry Andric       const char *second_name = GetArgumentName(arg_entry[1].arg_type);
4820b57cec5SDimitry Andric       switch (arg_entry[0].arg_repetition) {
4830b57cec5SDimitry Andric       case eArgRepeatPairPlain:
4840b57cec5SDimitry Andric         str.Printf("<%s> <%s>", first_name, second_name);
4850b57cec5SDimitry Andric         break;
4860b57cec5SDimitry Andric       case eArgRepeatPairOptional:
4870b57cec5SDimitry Andric         str.Printf("[<%s> <%s>]", first_name, second_name);
4880b57cec5SDimitry Andric         break;
4890b57cec5SDimitry Andric       case eArgRepeatPairPlus:
4900b57cec5SDimitry Andric         str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name,
4910b57cec5SDimitry Andric                    first_name, second_name);
4920b57cec5SDimitry Andric         break;
4930b57cec5SDimitry Andric       case eArgRepeatPairStar:
4940b57cec5SDimitry Andric         str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name,
4950b57cec5SDimitry Andric                    first_name, second_name);
4960b57cec5SDimitry Andric         break;
4970b57cec5SDimitry Andric       case eArgRepeatPairRange:
4980b57cec5SDimitry Andric         str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name,
4990b57cec5SDimitry Andric                    first_name, second_name);
5000b57cec5SDimitry Andric         break;
5010b57cec5SDimitry Andric       case eArgRepeatPairRangeOptional:
5020b57cec5SDimitry Andric         str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name,
5030b57cec5SDimitry Andric                    first_name, second_name);
5040b57cec5SDimitry Andric         break;
5050b57cec5SDimitry Andric       // Explicitly test for all the rest of the cases, so if new types get
5060b57cec5SDimitry Andric       // added we will notice the missing case statement(s).
5070b57cec5SDimitry Andric       case eArgRepeatPlain:
5080b57cec5SDimitry Andric       case eArgRepeatOptional:
5090b57cec5SDimitry Andric       case eArgRepeatPlus:
5100b57cec5SDimitry Andric       case eArgRepeatStar:
5110b57cec5SDimitry Andric       case eArgRepeatRange:
5120b57cec5SDimitry Andric         // These should not be reached, as they should fail the IsPairType test
5130b57cec5SDimitry Andric         // above.
5140b57cec5SDimitry Andric         break;
5150b57cec5SDimitry Andric       }
5160b57cec5SDimitry Andric     } else {
5170b57cec5SDimitry Andric       StreamString names;
5180b57cec5SDimitry Andric       for (int j = 0; j < num_alternatives; ++j) {
5190b57cec5SDimitry Andric         if (j > 0)
5200b57cec5SDimitry Andric           names.Printf(" | ");
5210b57cec5SDimitry Andric         names.Printf("%s", GetArgumentName(arg_entry[j].arg_type));
5220b57cec5SDimitry Andric       }
5230b57cec5SDimitry Andric 
5245ffd83dbSDimitry Andric       std::string name_str = std::string(names.GetString());
5250b57cec5SDimitry Andric       switch (arg_entry[0].arg_repetition) {
5260b57cec5SDimitry Andric       case eArgRepeatPlain:
5270b57cec5SDimitry Andric         str.Printf("<%s>", name_str.c_str());
5280b57cec5SDimitry Andric         break;
5290b57cec5SDimitry Andric       case eArgRepeatPlus:
5300b57cec5SDimitry Andric         str.Printf("<%s> [<%s> [...]]", name_str.c_str(), name_str.c_str());
5310b57cec5SDimitry Andric         break;
5320b57cec5SDimitry Andric       case eArgRepeatStar:
5330b57cec5SDimitry Andric         str.Printf("[<%s> [<%s> [...]]]", name_str.c_str(), name_str.c_str());
5340b57cec5SDimitry Andric         break;
5350b57cec5SDimitry Andric       case eArgRepeatOptional:
5360b57cec5SDimitry Andric         str.Printf("[<%s>]", name_str.c_str());
5370b57cec5SDimitry Andric         break;
5380b57cec5SDimitry Andric       case eArgRepeatRange:
5390b57cec5SDimitry Andric         str.Printf("<%s_1> .. <%s_n>", name_str.c_str(), name_str.c_str());
5400b57cec5SDimitry Andric         break;
5410b57cec5SDimitry Andric       // Explicitly test for all the rest of the cases, so if new types get
5420b57cec5SDimitry Andric       // added we will notice the missing case statement(s).
5430b57cec5SDimitry Andric       case eArgRepeatPairPlain:
5440b57cec5SDimitry Andric       case eArgRepeatPairOptional:
5450b57cec5SDimitry Andric       case eArgRepeatPairPlus:
5460b57cec5SDimitry Andric       case eArgRepeatPairStar:
5470b57cec5SDimitry Andric       case eArgRepeatPairRange:
5480b57cec5SDimitry Andric       case eArgRepeatPairRangeOptional:
5490b57cec5SDimitry Andric         // These should not be hit, as they should pass the IsPairType test
5500b57cec5SDimitry Andric         // above, and control should have gone into the other branch of the if
5510b57cec5SDimitry Andric         // statement.
5520b57cec5SDimitry Andric         break;
5530b57cec5SDimitry Andric       }
5540b57cec5SDimitry Andric     }
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric CommandArgumentType
LookupArgumentName(llvm::StringRef arg_name)5590b57cec5SDimitry Andric CommandObject::LookupArgumentName(llvm::StringRef arg_name) {
5600b57cec5SDimitry Andric   CommandArgumentType return_type = eArgTypeLastArg;
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   arg_name = arg_name.ltrim('<').rtrim('>');
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   for (int i = 0; i < eArgTypeLastArg; ++i)
565fcaf7f86SDimitry Andric     if (arg_name == g_argument_table[i].arg_name)
566fcaf7f86SDimitry Andric       return_type = g_argument_table[i].arg_type;
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   return return_type;
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
FormatLongHelpText(Stream & output_strm,llvm::StringRef long_help)5710b57cec5SDimitry Andric void CommandObject::FormatLongHelpText(Stream &output_strm,
5720b57cec5SDimitry Andric                                        llvm::StringRef long_help) {
5730b57cec5SDimitry Andric   CommandInterpreter &interpreter = GetCommandInterpreter();
5745ffd83dbSDimitry Andric   std::stringstream lineStream{std::string(long_help)};
5750b57cec5SDimitry Andric   std::string line;
5760b57cec5SDimitry Andric   while (std::getline(lineStream, line)) {
5770b57cec5SDimitry Andric     if (line.empty()) {
5780b57cec5SDimitry Andric       output_strm << "\n";
5790b57cec5SDimitry Andric       continue;
5800b57cec5SDimitry Andric     }
5810b57cec5SDimitry Andric     size_t result = line.find_first_not_of(" \t");
5820b57cec5SDimitry Andric     if (result == std::string::npos) {
5830b57cec5SDimitry Andric       result = 0;
5840b57cec5SDimitry Andric     }
5850b57cec5SDimitry Andric     std::string whitespace_prefix = line.substr(0, result);
5860b57cec5SDimitry Andric     std::string remainder = line.substr(result);
5875ffd83dbSDimitry Andric     interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix,
5885ffd83dbSDimitry Andric                                         remainder);
5890b57cec5SDimitry Andric   }
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric 
GenerateHelpText(CommandReturnObject & result)5920b57cec5SDimitry Andric void CommandObject::GenerateHelpText(CommandReturnObject &result) {
5930b57cec5SDimitry Andric   GenerateHelpText(result.GetOutputStream());
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   result.SetStatus(eReturnStatusSuccessFinishNoResult);
5960b57cec5SDimitry Andric }
5970b57cec5SDimitry Andric 
GenerateHelpText(Stream & output_strm)5980b57cec5SDimitry Andric void CommandObject::GenerateHelpText(Stream &output_strm) {
5990b57cec5SDimitry Andric   CommandInterpreter &interpreter = GetCommandInterpreter();
6000b57cec5SDimitry Andric   std::string help_text(GetHelp());
6015ffd83dbSDimitry Andric   if (WantsRawCommandString()) {
6020b57cec5SDimitry Andric     help_text.append("  Expects 'raw' input (see 'help raw-input'.)");
6035ffd83dbSDimitry Andric   }
6045ffd83dbSDimitry Andric   interpreter.OutputFormattedHelpText(output_strm, "", help_text);
6050b57cec5SDimitry Andric   output_strm << "\nSyntax: " << GetSyntax() << "\n";
6060b57cec5SDimitry Andric   Options *options = GetOptions();
6070b57cec5SDimitry Andric   if (options != nullptr) {
6080b57cec5SDimitry Andric     options->GenerateOptionUsage(
60981ad6265SDimitry Andric         output_strm, *this,
6100b57cec5SDimitry Andric         GetCommandInterpreter().GetDebugger().GetTerminalWidth());
6110b57cec5SDimitry Andric   }
6120b57cec5SDimitry Andric   llvm::StringRef long_help = GetHelpLong();
6130b57cec5SDimitry Andric   if (!long_help.empty()) {
6140b57cec5SDimitry Andric     FormatLongHelpText(output_strm, long_help);
6150b57cec5SDimitry Andric   }
6160b57cec5SDimitry Andric   if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) {
6170b57cec5SDimitry Andric     if (WantsRawCommandString() && !WantsCompletion()) {
6180b57cec5SDimitry Andric       // Emit the message about using ' -- ' between the end of the command
6190b57cec5SDimitry Andric       // options and the raw input conditionally, i.e., only if the command
6200b57cec5SDimitry Andric       // object does not want completion.
6210b57cec5SDimitry Andric       interpreter.OutputFormattedHelpText(
6220b57cec5SDimitry Andric           output_strm, "", "",
6230b57cec5SDimitry Andric           "\nImportant Note: Because this command takes 'raw' input, if you "
6240b57cec5SDimitry Andric           "use any command options"
6250b57cec5SDimitry Andric           " you must use ' -- ' between the end of the command options and the "
6260b57cec5SDimitry Andric           "beginning of the raw input.",
6270b57cec5SDimitry Andric           1);
6280b57cec5SDimitry Andric     } else if (GetNumArgumentEntries() > 0) {
6290b57cec5SDimitry Andric       // Also emit a warning about using "--" in case you are using a command
6300b57cec5SDimitry Andric       // that takes options and arguments.
6310b57cec5SDimitry Andric       interpreter.OutputFormattedHelpText(
6320b57cec5SDimitry Andric           output_strm, "", "",
6330b57cec5SDimitry Andric           "\nThis command takes options and free-form arguments.  If your "
6340b57cec5SDimitry Andric           "arguments resemble"
6350b57cec5SDimitry Andric           " option specifiers (i.e., they start with a - or --), you must use "
6360b57cec5SDimitry Andric           "' -- ' between"
6370b57cec5SDimitry Andric           " the end of the command options and the beginning of the arguments.",
6380b57cec5SDimitry Andric           1);
6390b57cec5SDimitry Andric     }
6400b57cec5SDimitry Andric   }
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric 
AddIDsArgumentData(CommandArgumentEntry & arg,CommandArgumentType ID,CommandArgumentType IDRange)6430b57cec5SDimitry Andric void CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg,
6440b57cec5SDimitry Andric                                        CommandArgumentType ID,
6450b57cec5SDimitry Andric                                        CommandArgumentType IDRange) {
6460b57cec5SDimitry Andric   CommandArgumentData id_arg;
6470b57cec5SDimitry Andric   CommandArgumentData id_range_arg;
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   // Create the first variant for the first (and only) argument for this
6500b57cec5SDimitry Andric   // command.
6510b57cec5SDimitry Andric   id_arg.arg_type = ID;
6520b57cec5SDimitry Andric   id_arg.arg_repetition = eArgRepeatOptional;
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   // Create the second variant for the first (and only) argument for this
6550b57cec5SDimitry Andric   // command.
6560b57cec5SDimitry Andric   id_range_arg.arg_type = IDRange;
6570b57cec5SDimitry Andric   id_range_arg.arg_repetition = eArgRepeatOptional;
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   // The first (and only) argument for this command could be either an id or an
6600b57cec5SDimitry Andric   // id_range. Push both variants into the entry for the first argument for
6610b57cec5SDimitry Andric   // this command.
6620b57cec5SDimitry Andric   arg.push_back(id_arg);
6630b57cec5SDimitry Andric   arg.push_back(id_range_arg);
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric 
GetArgumentTypeAsCString(const lldb::CommandArgumentType arg_type)6660b57cec5SDimitry Andric const char *CommandObject::GetArgumentTypeAsCString(
6670b57cec5SDimitry Andric     const lldb::CommandArgumentType arg_type) {
6680b57cec5SDimitry Andric   assert(arg_type < eArgTypeLastArg &&
6690b57cec5SDimitry Andric          "Invalid argument type passed to GetArgumentTypeAsCString");
670fcaf7f86SDimitry Andric   return g_argument_table[arg_type].arg_name;
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric 
GetArgumentDescriptionAsCString(const lldb::CommandArgumentType arg_type)6730b57cec5SDimitry Andric const char *CommandObject::GetArgumentDescriptionAsCString(
6740b57cec5SDimitry Andric     const lldb::CommandArgumentType arg_type) {
6750b57cec5SDimitry Andric   assert(arg_type < eArgTypeLastArg &&
6760b57cec5SDimitry Andric          "Invalid argument type passed to GetArgumentDescriptionAsCString");
677fcaf7f86SDimitry Andric   return g_argument_table[arg_type].help_text;
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric 
GetDummyTarget()6809dba64beSDimitry Andric Target &CommandObject::GetDummyTarget() {
681e8d8bef9SDimitry Andric   return m_interpreter.GetDebugger().GetDummyTarget();
6820b57cec5SDimitry Andric }
6830b57cec5SDimitry Andric 
GetSelectedOrDummyTarget(bool prefer_dummy)6849dba64beSDimitry Andric Target &CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) {
685e8d8bef9SDimitry Andric   return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy);
6869dba64beSDimitry Andric }
6879dba64beSDimitry Andric 
GetSelectedTarget()6889dba64beSDimitry Andric Target &CommandObject::GetSelectedTarget() {
6899dba64beSDimitry Andric   assert(m_flags.AnySet(eCommandRequiresTarget | eCommandProcessMustBePaused |
6909dba64beSDimitry Andric                         eCommandProcessMustBeLaunched | eCommandRequiresFrame |
6919dba64beSDimitry Andric                         eCommandRequiresThread | eCommandRequiresProcess |
6929dba64beSDimitry Andric                         eCommandRequiresRegContext) &&
6939dba64beSDimitry Andric          "GetSelectedTarget called from object that may have no target");
6949dba64beSDimitry Andric   return *m_interpreter.GetDebugger().GetSelectedTarget();
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
GetDefaultThread()6970b57cec5SDimitry Andric Thread *CommandObject::GetDefaultThread() {
6980b57cec5SDimitry Andric   Thread *thread_to_use = m_exe_ctx.GetThreadPtr();
6990b57cec5SDimitry Andric   if (thread_to_use)
7000b57cec5SDimitry Andric     return thread_to_use;
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric   Process *process = m_exe_ctx.GetProcessPtr();
7030b57cec5SDimitry Andric   if (!process) {
7040b57cec5SDimitry Andric     Target *target = m_exe_ctx.GetTargetPtr();
7050b57cec5SDimitry Andric     if (!target) {
7060b57cec5SDimitry Andric       target = m_interpreter.GetDebugger().GetSelectedTarget().get();
7070b57cec5SDimitry Andric     }
7080b57cec5SDimitry Andric     if (target)
7090b57cec5SDimitry Andric       process = target->GetProcessSP().get();
7100b57cec5SDimitry Andric   }
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric   if (process)
7130b57cec5SDimitry Andric     return process->GetThreadList().GetSelectedThread().get();
7140b57cec5SDimitry Andric   else
7150b57cec5SDimitry Andric     return nullptr;
7160b57cec5SDimitry Andric }
7170b57cec5SDimitry Andric 
Execute(const char * args_string,CommandReturnObject & result)718*c9157d92SDimitry Andric void CommandObjectParsed::Execute(const char *args_string,
7190b57cec5SDimitry Andric                                   CommandReturnObject &result) {
7200b57cec5SDimitry Andric   bool handled = false;
7210b57cec5SDimitry Andric   Args cmd_args(args_string);
7220b57cec5SDimitry Andric   if (HasOverrideCallback()) {
7230b57cec5SDimitry Andric     Args full_args(GetCommandName());
7240b57cec5SDimitry Andric     full_args.AppendArguments(cmd_args);
7250b57cec5SDimitry Andric     handled =
7260b57cec5SDimitry Andric         InvokeOverrideCallback(full_args.GetConstArgumentVector(), result);
7270b57cec5SDimitry Andric   }
7280b57cec5SDimitry Andric   if (!handled) {
7290b57cec5SDimitry Andric     for (auto entry : llvm::enumerate(cmd_args.entries())) {
730fe013be4SDimitry Andric       const Args::ArgEntry &value = entry.value();
731fe013be4SDimitry Andric       if (!value.ref().empty() && value.GetQuoteChar() == '`') {
732fe013be4SDimitry Andric         // We have to put the backtick back in place for PreprocessCommand.
733fe013be4SDimitry Andric         std::string opt_string = value.c_str();
734fe013be4SDimitry Andric         Status error;
735fe013be4SDimitry Andric         error = m_interpreter.PreprocessToken(opt_string);
736fe013be4SDimitry Andric         if (error.Success())
737fe013be4SDimitry Andric           cmd_args.ReplaceArgumentAtIndex(entry.index(), opt_string);
7380b57cec5SDimitry Andric       }
7390b57cec5SDimitry Andric     }
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric     if (CheckRequirements(result)) {
7420b57cec5SDimitry Andric       if (ParseOptions(cmd_args, result)) {
7430b57cec5SDimitry Andric         // Call the command-specific version of 'Execute', passing it the
7440b57cec5SDimitry Andric         // already processed arguments.
74581ad6265SDimitry Andric         if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) {
74681ad6265SDimitry Andric           result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.",
74781ad6265SDimitry Andric                                         GetCommandName());
748bdd1243dSDimitry Andric           Cleanup();
749*c9157d92SDimitry Andric           return;
75081ad6265SDimitry Andric         }
751*c9157d92SDimitry Andric         DoExecute(cmd_args, result);
7520b57cec5SDimitry Andric       }
7530b57cec5SDimitry Andric     }
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric     Cleanup();
7560b57cec5SDimitry Andric   }
7570b57cec5SDimitry Andric }
7580b57cec5SDimitry Andric 
Execute(const char * args_string,CommandReturnObject & result)759*c9157d92SDimitry Andric void CommandObjectRaw::Execute(const char *args_string,
7600b57cec5SDimitry Andric                                CommandReturnObject &result) {
7610b57cec5SDimitry Andric   bool handled = false;
7620b57cec5SDimitry Andric   if (HasOverrideCallback()) {
7630b57cec5SDimitry Andric     std::string full_command(GetCommandName());
7640b57cec5SDimitry Andric     full_command += ' ';
7650b57cec5SDimitry Andric     full_command += args_string;
7660b57cec5SDimitry Andric     const char *argv[2] = {nullptr, nullptr};
7670b57cec5SDimitry Andric     argv[0] = full_command.c_str();
7680b57cec5SDimitry Andric     handled = InvokeOverrideCallback(argv, result);
7690b57cec5SDimitry Andric   }
7700b57cec5SDimitry Andric   if (!handled) {
7710b57cec5SDimitry Andric     if (CheckRequirements(result))
772*c9157d92SDimitry Andric       DoExecute(args_string, result);
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric     Cleanup();
7750b57cec5SDimitry Andric   }
7760b57cec5SDimitry Andric }
777