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