180814287SRaphael Isemann //===-- CommandObject.cpp -------------------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandObject.h" 1030fdc8d8SChris Lattner 1130fdc8d8SChris Lattner #include <map> 12b9c1b51eSKate Stone #include <sstream> 13b9c1b51eSKate Stone #include <string> 1430fdc8d8SChris Lattner 1576e47d48SRaphael Isemann #include <cctype> 1676e47d48SRaphael Isemann #include <cstdlib> 1730fdc8d8SChris Lattner 1830fdc8d8SChris Lattner #include "lldb/Core/Address.h" 1940af72e1SJim Ingham #include "lldb/Interpreter/Options.h" 205f19b907SPavel Labath #include "lldb/Utility/ArchSpec.h" 2118bb1f10SRaphael Isemann #include "llvm/ADT/ScopeExit.h" 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner // These are for the Sourcename completers. 2430fdc8d8SChris Lattner // FIXME: Make a separate file for the completers. 2530fdc8d8SChris Lattner #include "lldb/Core/FileSpecList.h" 26a78bd7ffSZachary Turner #include "lldb/DataFormatters/FormatManager.h" 2730fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2830fdc8d8SChris Lattner #include "lldb/Target/Target.h" 295713a05bSZachary Turner #include "lldb/Utility/FileSpec.h" 3030fdc8d8SChris Lattner 310e0984eeSJim Ingham #include "lldb/Target/Language.h" 320e0984eeSJim Ingham 3330fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 34*7ced9fffSJonas Devlieghere #include "lldb/Interpreter/CommandOptionArgumentTable.h" 3530fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 3630fdc8d8SChris Lattner 3730fdc8d8SChris Lattner using namespace lldb; 3830fdc8d8SChris Lattner using namespace lldb_private; 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner // CommandObject 4130fdc8d8SChris Lattner 42adcd0268SBenjamin Kramer CommandObject::CommandObject(CommandInterpreter &interpreter, 43adcd0268SBenjamin Kramer llvm::StringRef name, llvm::StringRef help, 44adcd0268SBenjamin Kramer llvm::StringRef syntax, uint32_t flags) 45adcd0268SBenjamin Kramer : m_interpreter(interpreter), m_cmd_name(std::string(name)), 468cdcd41eSTatyana Krasnukha m_flags(flags), m_deprecated_command_override_callback(nullptr), 47b9c1b51eSKate Stone m_command_override_callback(nullptr), m_command_override_baton(nullptr) { 48adcd0268SBenjamin Kramer m_cmd_help_short = std::string(help); 49adcd0268SBenjamin Kramer m_cmd_syntax = std::string(syntax); 5030fdc8d8SChris Lattner } 5130fdc8d8SChris Lattner 522b29b432SJonas Devlieghere Debugger &CommandObject::GetDebugger() { return m_interpreter.GetDebugger(); } 532b29b432SJonas Devlieghere 54442f6530SZachary Turner llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; } 5530fdc8d8SChris Lattner 56442f6530SZachary Turner llvm::StringRef CommandObject::GetHelpLong() { return m_cmd_help_long; } 5730fdc8d8SChris Lattner 58442f6530SZachary Turner llvm::StringRef CommandObject::GetSyntax() { 597cff7d46SEugene Zemtsov if (!m_cmd_syntax.empty()) 60442f6530SZachary Turner return m_cmd_syntax; 61442f6530SZachary Turner 62e139cf23SCaroline Tice StreamString syntax_str; 63442f6530SZachary Turner syntax_str.PutCString(GetCommandName()); 64442f6530SZachary Turner 65bef55ac8SEnrico Granata if (!IsDashDashCommand() && GetOptions() != nullptr) 66442f6530SZachary Turner syntax_str.PutCString(" <cmd-options>"); 67442f6530SZachary Turner 68442f6530SZachary Turner if (!m_arguments.empty()) { 69442f6530SZachary Turner syntax_str.PutCString(" "); 70442f6530SZachary Turner 71b9c1b51eSKate Stone if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() && 72b9c1b51eSKate Stone GetOptions()->NumCommandOptions()) 73442f6530SZachary Turner syntax_str.PutCString("-- "); 74e139cf23SCaroline Tice GetFormattedCommandArguments(syntax_str); 75e139cf23SCaroline Tice } 76adcd0268SBenjamin Kramer m_cmd_syntax = std::string(syntax_str.GetString()); 77e139cf23SCaroline Tice 78442f6530SZachary Turner return m_cmd_syntax; 7930fdc8d8SChris Lattner } 8030fdc8d8SChris Lattner 81a449698cSZachary Turner llvm::StringRef CommandObject::GetCommandName() const { return m_cmd_name; } 8230fdc8d8SChris Lattner 83adcd0268SBenjamin Kramer void CommandObject::SetCommandName(llvm::StringRef name) { 84adcd0268SBenjamin Kramer m_cmd_name = std::string(name); 85adcd0268SBenjamin Kramer } 8630fdc8d8SChris Lattner 87adcd0268SBenjamin Kramer void CommandObject::SetHelp(llvm::StringRef str) { 88adcd0268SBenjamin Kramer m_cmd_help_short = std::string(str); 89adcd0268SBenjamin Kramer } 906f79bb2dSEnrico Granata 91adcd0268SBenjamin Kramer void CommandObject::SetHelpLong(llvm::StringRef str) { 92adcd0268SBenjamin Kramer m_cmd_help_long = std::string(str); 93adcd0268SBenjamin Kramer } 9499f0b8f9SEnrico Granata 95adcd0268SBenjamin Kramer void CommandObject::SetSyntax(llvm::StringRef str) { 96adcd0268SBenjamin Kramer m_cmd_syntax = std::string(str); 97adcd0268SBenjamin Kramer } 9830fdc8d8SChris Lattner 99b9c1b51eSKate Stone Options *CommandObject::GetOptions() { 10005097246SAdrian Prantl // By default commands don't have options unless this virtual function is 10105097246SAdrian Prantl // overridden by base classes. 102d78c9576SEd Maste return nullptr; 10330fdc8d8SChris Lattner } 10430fdc8d8SChris Lattner 105b9c1b51eSKate Stone bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) { 10630fdc8d8SChris Lattner // See if the subclass has options? 10730fdc8d8SChris Lattner Options *options = GetOptions(); 108b9c1b51eSKate Stone if (options != nullptr) { 10997206d57SZachary Turner Status error; 110e1cfbc79STodd Fiala 111e1cfbc79STodd Fiala auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); 112e1cfbc79STodd Fiala options->NotifyOptionParsingStarting(&exe_ctx); 11330fdc8d8SChris Lattner 114e1cfbc79STodd Fiala const bool require_validation = true; 1155f56fca4SPavel Labath llvm::Expected<Args> args_or = options->Parse( 1165f56fca4SPavel Labath args, &exe_ctx, GetCommandInterpreter().GetPlatform(true), 117e1cfbc79STodd Fiala require_validation); 11830fdc8d8SChris Lattner 1195f56fca4SPavel Labath if (args_or) { 1205f56fca4SPavel Labath args = std::move(*args_or); 121e1cfbc79STodd Fiala error = options->NotifyOptionParsingFinished(&exe_ctx); 1225f56fca4SPavel Labath } else 1235f56fca4SPavel Labath error = args_or.takeError(); 124f6b8b581SGreg Clayton 125b9c1b51eSKate Stone if (error.Success()) { 126f6b8b581SGreg Clayton if (options->VerifyOptions(result)) 127f6b8b581SGreg Clayton return true; 128b9c1b51eSKate Stone } else { 12930fdc8d8SChris Lattner const char *error_cstr = error.AsCString(); 130b9c1b51eSKate Stone if (error_cstr) { 13130fdc8d8SChris Lattner // We got an error string, lets use that 13286edbf41SGreg Clayton result.AppendError(error_cstr); 133b9c1b51eSKate Stone } else { 13430fdc8d8SChris Lattner // No error string, output the usage information into result 135b9c1b51eSKate Stone options->GenerateOptionUsage( 136e473e79cSDavid Spickett result.GetErrorStream(), *this, 137b9c1b51eSKate Stone GetCommandInterpreter().GetDebugger().GetTerminalWidth()); 13830fdc8d8SChris Lattner } 139f6b8b581SGreg Clayton } 14030fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 14130fdc8d8SChris Lattner return false; 14230fdc8d8SChris Lattner } 14330fdc8d8SChris Lattner return true; 14430fdc8d8SChris Lattner } 14530fdc8d8SChris Lattner 146b9c1b51eSKate Stone bool CommandObject::CheckRequirements(CommandReturnObject &result) { 14705097246SAdrian Prantl // Nothing should be stored in m_exe_ctx between running commands as 14805097246SAdrian Prantl // m_exe_ctx has shared pointers to the target, process, thread and frame and 14905097246SAdrian Prantl // we don't want any CommandObject instances to keep any of these objects 15005097246SAdrian Prantl // around longer than for a single command. Every command should call 15161f1b70aSAdrian Prantl // CommandObject::Cleanup() after it has completed. 15261f1b70aSAdrian Prantl assert(!m_exe_ctx.GetTargetPtr()); 15361f1b70aSAdrian Prantl assert(!m_exe_ctx.GetProcessPtr()); 15461f1b70aSAdrian Prantl assert(!m_exe_ctx.GetThreadPtr()); 15561f1b70aSAdrian Prantl assert(!m_exe_ctx.GetFramePtr()); 156f9fc609fSGreg Clayton 15705097246SAdrian Prantl // Lock down the interpreter's execution context prior to running the command 15805097246SAdrian Prantl // so we guarantee the selected target, process, thread and frame can't go 15905097246SAdrian Prantl // away during the execution 160f9fc609fSGreg Clayton m_exe_ctx = m_interpreter.GetExecutionContext(); 161f9fc609fSGreg Clayton 162f9fc609fSGreg Clayton const uint32_t flags = GetFlags().Get(); 163b9c1b51eSKate Stone if (flags & (eCommandRequiresTarget | eCommandRequiresProcess | 164b9c1b51eSKate Stone eCommandRequiresThread | eCommandRequiresFrame | 165b9c1b51eSKate Stone eCommandTryTargetAPILock)) { 166f9fc609fSGreg Clayton 167b9c1b51eSKate Stone if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) { 168f9fc609fSGreg Clayton result.AppendError(GetInvalidTargetDescription()); 169f9fc609fSGreg Clayton return false; 170f9fc609fSGreg Clayton } 171f9fc609fSGreg Clayton 172b9c1b51eSKate Stone if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) { 173e59b0d2cSJason Molenda if (!m_exe_ctx.HasTargetScope()) 174e59b0d2cSJason Molenda result.AppendError(GetInvalidTargetDescription()); 175e59b0d2cSJason Molenda else 176f9fc609fSGreg Clayton result.AppendError(GetInvalidProcessDescription()); 177f9fc609fSGreg Clayton return false; 178f9fc609fSGreg Clayton } 179f9fc609fSGreg Clayton 180b9c1b51eSKate Stone if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) { 181e59b0d2cSJason Molenda if (!m_exe_ctx.HasTargetScope()) 182e59b0d2cSJason Molenda result.AppendError(GetInvalidTargetDescription()); 183e59b0d2cSJason Molenda else if (!m_exe_ctx.HasProcessScope()) 184e59b0d2cSJason Molenda result.AppendError(GetInvalidProcessDescription()); 185e59b0d2cSJason Molenda else 186f9fc609fSGreg Clayton result.AppendError(GetInvalidThreadDescription()); 187f9fc609fSGreg Clayton return false; 188f9fc609fSGreg Clayton } 189f9fc609fSGreg Clayton 190b9c1b51eSKate Stone if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) { 191e59b0d2cSJason Molenda if (!m_exe_ctx.HasTargetScope()) 192e59b0d2cSJason Molenda result.AppendError(GetInvalidTargetDescription()); 193e59b0d2cSJason Molenda else if (!m_exe_ctx.HasProcessScope()) 194e59b0d2cSJason Molenda result.AppendError(GetInvalidProcessDescription()); 195e59b0d2cSJason Molenda else if (!m_exe_ctx.HasThreadScope()) 196e59b0d2cSJason Molenda result.AppendError(GetInvalidThreadDescription()); 197e59b0d2cSJason Molenda else 198f9fc609fSGreg Clayton result.AppendError(GetInvalidFrameDescription()); 199f9fc609fSGreg Clayton return false; 200f9fc609fSGreg Clayton } 201f9fc609fSGreg Clayton 202b9c1b51eSKate Stone if ((flags & eCommandRequiresRegContext) && 203b9c1b51eSKate Stone (m_exe_ctx.GetRegisterContext() == nullptr)) { 204f9fc609fSGreg Clayton result.AppendError(GetInvalidRegContextDescription()); 205f9fc609fSGreg Clayton return false; 206f9fc609fSGreg Clayton } 207f9fc609fSGreg Clayton 208b9c1b51eSKate Stone if (flags & eCommandTryTargetAPILock) { 209f9fc609fSGreg Clayton Target *target = m_exe_ctx.GetTargetPtr(); 210f9fc609fSGreg Clayton if (target) 211b9c1b51eSKate Stone m_api_locker = 212b9c1b51eSKate Stone std::unique_lock<std::recursive_mutex>(target->GetAPIMutex()); 213f9fc609fSGreg Clayton } 214f9fc609fSGreg Clayton } 215f9fc609fSGreg Clayton 216b9c1b51eSKate Stone if (GetFlags().AnySet(eCommandProcessMustBeLaunched | 217b9c1b51eSKate Stone eCommandProcessMustBePaused)) { 218c14ee32dSGreg Clayton Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 219b9c1b51eSKate Stone if (process == nullptr) { 220b8e8a5f3SJim Ingham // A process that is not running is considered paused. 221b9c1b51eSKate Stone if (GetFlags().Test(eCommandProcessMustBeLaunched)) { 22230fdc8d8SChris Lattner result.AppendError("Process must exist."); 22330fdc8d8SChris Lattner return false; 22430fdc8d8SChris Lattner } 225b9c1b51eSKate Stone } else { 22630fdc8d8SChris Lattner StateType state = process->GetState(); 227b9c1b51eSKate Stone switch (state) { 2287a5388bfSGreg Clayton case eStateInvalid: 22930fdc8d8SChris Lattner case eStateSuspended: 23030fdc8d8SChris Lattner case eStateCrashed: 23130fdc8d8SChris Lattner case eStateStopped: 23230fdc8d8SChris Lattner break; 23330fdc8d8SChris Lattner 234b766a73dSGreg Clayton case eStateConnected: 235b766a73dSGreg Clayton case eStateAttaching: 236b766a73dSGreg Clayton case eStateLaunching: 23730fdc8d8SChris Lattner case eStateDetached: 23830fdc8d8SChris Lattner case eStateExited: 23930fdc8d8SChris Lattner case eStateUnloaded: 240b9c1b51eSKate Stone if (GetFlags().Test(eCommandProcessMustBeLaunched)) { 24130fdc8d8SChris Lattner result.AppendError("Process must be launched."); 24230fdc8d8SChris Lattner return false; 24330fdc8d8SChris Lattner } 24430fdc8d8SChris Lattner break; 24530fdc8d8SChris Lattner 24630fdc8d8SChris Lattner case eStateRunning: 24730fdc8d8SChris Lattner case eStateStepping: 248b9c1b51eSKate Stone if (GetFlags().Test(eCommandProcessMustBePaused)) { 249b9c1b51eSKate Stone result.AppendError("Process is running. Use 'process interrupt' to " 250b9c1b51eSKate Stone "pause execution."); 25130fdc8d8SChris Lattner return false; 25230fdc8d8SChris Lattner } 25330fdc8d8SChris Lattner } 25430fdc8d8SChris Lattner } 255b766a73dSGreg Clayton } 256fb19f11eSWalter Erquinigo 257fb19f11eSWalter Erquinigo if (GetFlags().Test(eCommandProcessMustBeTraced)) { 258fb19f11eSWalter Erquinigo Target *target = m_exe_ctx.GetTargetPtr(); 259fb19f11eSWalter Erquinigo if (target && !target->GetTrace()) { 2601b1c8e4aSDavid Spickett result.AppendError("Process is not being traced."); 261fb19f11eSWalter Erquinigo return false; 262fb19f11eSWalter Erquinigo } 263fb19f11eSWalter Erquinigo } 264fb19f11eSWalter Erquinigo 2655a988416SJim Ingham return true; 26630fdc8d8SChris Lattner } 26730fdc8d8SChris Lattner 268b9c1b51eSKate Stone void CommandObject::Cleanup() { 269f9fc609fSGreg Clayton m_exe_ctx.Clear(); 270bb19a13cSSaleem Abdulrasool if (m_api_locker.owns_lock()) 271bb19a13cSSaleem Abdulrasool m_api_locker.unlock(); 272f9fc609fSGreg Clayton } 273f9fc609fSGreg Clayton 274ae34ed2cSRaphael Isemann void CommandObject::HandleCompletion(CompletionRequest &request) { 275ec31255cSGongyu Deng 276ec31255cSGongyu Deng m_exe_ctx = m_interpreter.GetExecutionContext(); 27718bb1f10SRaphael Isemann auto reset_ctx = llvm::make_scope_exit([this]() { Cleanup(); }); 278ec31255cSGongyu Deng 279e171da5cSBruce Mitchener // Default implementation of WantsCompletion() is !WantsRawCommandString(). 28005097246SAdrian Prantl // Subclasses who want raw command string but desire, for example, argument 28105097246SAdrian Prantl // completion should override WantsCompletion() to return true, instead. 282b9c1b51eSKate Stone if (WantsRawCommandString() && !WantsCompletion()) { 283b9c1b51eSKate Stone // FIXME: Abstract telling the completion to insert the completion 284b9c1b51eSKate Stone // character. 285ae34ed2cSRaphael Isemann return; 286b9c1b51eSKate Stone } else { 28730fdc8d8SChris Lattner // Can we do anything generic with the options? 28830fdc8d8SChris Lattner Options *cur_options = GetOptions(); 289de019b88SJonas Devlieghere CommandReturnObject result(m_interpreter.GetDebugger().GetUseColor()); 29030fdc8d8SChris Lattner OptionElementVector opt_element_vector; 29130fdc8d8SChris Lattner 292b9c1b51eSKate Stone if (cur_options != nullptr) { 2932443bbd4SRaphael Isemann opt_element_vector = cur_options->ParseForCompletion( 2942443bbd4SRaphael Isemann request.GetParsedLine(), request.GetCursorIndex()); 29530fdc8d8SChris Lattner 296a2e76c0bSRaphael Isemann bool handled_by_options = cur_options->HandleOptionCompletion( 297a2e76c0bSRaphael Isemann request, opt_element_vector, GetCommandInterpreter()); 29830fdc8d8SChris Lattner if (handled_by_options) 299ae34ed2cSRaphael Isemann return; 30030fdc8d8SChris Lattner } 30130fdc8d8SChris Lattner 30230fdc8d8SChris Lattner // If we got here, the last word is not an option or an option argument. 303ae34ed2cSRaphael Isemann HandleArgumentCompletion(request, opt_element_vector); 30430fdc8d8SChris Lattner } 30530fdc8d8SChris Lattner } 30630fdc8d8SChris Lattner 30798896839SZachary Turner bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word, 308d033e1ceSEnrico Granata bool search_short_help, 309d033e1ceSEnrico Granata bool search_long_help, 310d033e1ceSEnrico Granata bool search_syntax, 311b9c1b51eSKate Stone bool search_options) { 31230fdc8d8SChris Lattner std::string options_usage_help; 31330fdc8d8SChris Lattner 31430fdc8d8SChris Lattner bool found_word = false; 31530fdc8d8SChris Lattner 316442f6530SZachary Turner llvm::StringRef short_help = GetHelp(); 317442f6530SZachary Turner llvm::StringRef long_help = GetHelpLong(); 318442f6530SZachary Turner llvm::StringRef syntax_help = GetSyntax(); 31930fdc8d8SChris Lattner 320e50f9c41SMartin Storsjö if (search_short_help && short_help.contains_insensitive(search_word)) 32130fdc8d8SChris Lattner found_word = true; 322e50f9c41SMartin Storsjö else if (search_long_help && long_help.contains_insensitive(search_word)) 32330fdc8d8SChris Lattner found_word = true; 324e50f9c41SMartin Storsjö else if (search_syntax && syntax_help.contains_insensitive(search_word)) 32530fdc8d8SChris Lattner found_word = true; 32630fdc8d8SChris Lattner 327b9c1b51eSKate Stone if (!found_word && search_options && GetOptions() != nullptr) { 32830fdc8d8SChris Lattner StreamString usage_help; 329b9c1b51eSKate Stone GetOptions()->GenerateOptionUsage( 330e473e79cSDavid Spickett usage_help, *this, 331b9c1b51eSKate Stone GetCommandInterpreter().GetDebugger().GetTerminalWidth()); 33298896839SZachary Turner if (!usage_help.Empty()) { 33398896839SZachary Turner llvm::StringRef usage_text = usage_help.GetString(); 334e50f9c41SMartin Storsjö if (usage_text.contains_insensitive(search_word)) 33530fdc8d8SChris Lattner found_word = true; 33630fdc8d8SChris Lattner } 33730fdc8d8SChris Lattner } 33830fdc8d8SChris Lattner 33930fdc8d8SChris Lattner return found_word; 34030fdc8d8SChris Lattner } 341e139cf23SCaroline Tice 3423a0e1270SRaphael Isemann bool CommandObject::ParseOptionsAndNotify(Args &args, 3433a0e1270SRaphael Isemann CommandReturnObject &result, 3443a0e1270SRaphael Isemann OptionGroupOptions &group_options, 3453a0e1270SRaphael Isemann ExecutionContext &exe_ctx) { 3463a0e1270SRaphael Isemann if (!ParseOptions(args, result)) 3473a0e1270SRaphael Isemann return false; 3483a0e1270SRaphael Isemann 3493a0e1270SRaphael Isemann Status error(group_options.NotifyOptionParsingFinished(&exe_ctx)); 3503a0e1270SRaphael Isemann if (error.Fail()) { 3513a0e1270SRaphael Isemann result.AppendError(error.AsCString()); 3523a0e1270SRaphael Isemann return false; 3533a0e1270SRaphael Isemann } 3543a0e1270SRaphael Isemann return true; 3553a0e1270SRaphael Isemann } 3563a0e1270SRaphael Isemann 357b9c1b51eSKate Stone int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); } 358e139cf23SCaroline Tice 359e139cf23SCaroline Tice CommandObject::CommandArgumentEntry * 360b9c1b51eSKate Stone CommandObject::GetArgumentEntryAtIndex(int idx) { 3613985c8c6SSaleem Abdulrasool if (static_cast<size_t>(idx) < m_arguments.size()) 362e139cf23SCaroline Tice return &(m_arguments[idx]); 363e139cf23SCaroline Tice 364d78c9576SEd Maste return nullptr; 365e139cf23SCaroline Tice } 366e139cf23SCaroline Tice 367d7e6a4f2SVince Harron const CommandObject::ArgumentTableEntry * 368b9c1b51eSKate Stone CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) { 369e139cf23SCaroline Tice for (int i = 0; i < eArgTypeLastArg; ++i) 370*7ced9fffSJonas Devlieghere if (g_argument_table[i].arg_type == arg_type) 371*7ced9fffSJonas Devlieghere return &(g_argument_table[i]); 372e139cf23SCaroline Tice 373d78c9576SEd Maste return nullptr; 374e139cf23SCaroline Tice } 375e139cf23SCaroline Tice 376b9c1b51eSKate Stone void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type, 377b9c1b51eSKate Stone CommandInterpreter &interpreter) { 378*7ced9fffSJonas Devlieghere const ArgumentTableEntry *entry = &(g_argument_table[arg_type]); 379e139cf23SCaroline Tice 380b9c1b51eSKate Stone // The table is *supposed* to be kept in arg_type order, but someone *could* 381b9c1b51eSKate Stone // have messed it up... 382e139cf23SCaroline Tice 383e139cf23SCaroline Tice if (entry->arg_type != arg_type) 384e139cf23SCaroline Tice entry = CommandObject::FindArgumentDataByType(arg_type); 385e139cf23SCaroline Tice 386e139cf23SCaroline Tice if (!entry) 387e139cf23SCaroline Tice return; 388e139cf23SCaroline Tice 389e139cf23SCaroline Tice StreamString name_str; 390e139cf23SCaroline Tice name_str.Printf("<%s>", entry->arg_name); 391e139cf23SCaroline Tice 392b9c1b51eSKate Stone if (entry->help_function) { 393e0038717SZachary Turner llvm::StringRef help_text = entry->help_function(); 394b9c1b51eSKate Stone if (!entry->help_function.self_formatting) { 395c156427dSZachary Turner interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--", 396b9c1b51eSKate Stone help_text, name_str.GetSize()); 397b9c1b51eSKate Stone } else { 398c156427dSZachary Turner interpreter.OutputHelpText(str, name_str.GetString(), "--", help_text, 39982a7d983SEnrico Granata name_str.GetSize()); 40082a7d983SEnrico Granata } 401b9c1b51eSKate Stone } else 402c156427dSZachary Turner interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--", 403b9c1b51eSKate Stone entry->help_text, name_str.GetSize()); 404e139cf23SCaroline Tice } 405e139cf23SCaroline Tice 406b9c1b51eSKate Stone const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) { 407*7ced9fffSJonas Devlieghere const ArgumentTableEntry *entry = &(g_argument_table[arg_type]); 408deaab222SCaroline Tice 409b9c1b51eSKate Stone // The table is *supposed* to be kept in arg_type order, but someone *could* 410b9c1b51eSKate Stone // have messed it up... 411deaab222SCaroline Tice 412deaab222SCaroline Tice if (entry->arg_type != arg_type) 413deaab222SCaroline Tice entry = CommandObject::FindArgumentDataByType(arg_type); 414deaab222SCaroline Tice 415e6acf355SJohnny Chen if (entry) 416deaab222SCaroline Tice return entry->arg_name; 417e6acf355SJohnny Chen 418c156427dSZachary Turner return nullptr; 419e139cf23SCaroline Tice } 420e139cf23SCaroline Tice 421b9c1b51eSKate Stone bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) { 422a6682a41SJonas Devlieghere return (arg_repeat_type == eArgRepeatPairPlain) || 423b9c1b51eSKate Stone (arg_repeat_type == eArgRepeatPairOptional) || 424b9c1b51eSKate Stone (arg_repeat_type == eArgRepeatPairPlus) || 425b9c1b51eSKate Stone (arg_repeat_type == eArgRepeatPairStar) || 426b9c1b51eSKate Stone (arg_repeat_type == eArgRepeatPairRange) || 427a6682a41SJonas Devlieghere (arg_repeat_type == eArgRepeatPairRangeOptional); 428405fe67fSCaroline Tice } 429405fe67fSCaroline Tice 43034ddc8dbSJohnny Chen static CommandObject::CommandArgumentEntry 431b9c1b51eSKate Stone OptSetFiltered(uint32_t opt_set_mask, 432b9c1b51eSKate Stone CommandObject::CommandArgumentEntry &cmd_arg_entry) { 43334ddc8dbSJohnny Chen CommandObject::CommandArgumentEntry ret_val; 43434ddc8dbSJohnny Chen for (unsigned i = 0; i < cmd_arg_entry.size(); ++i) 43534ddc8dbSJohnny Chen if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association) 43634ddc8dbSJohnny Chen ret_val.push_back(cmd_arg_entry[i]); 43734ddc8dbSJohnny Chen return ret_val; 43834ddc8dbSJohnny Chen } 43934ddc8dbSJohnny Chen 44005097246SAdrian Prantl // Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means 44105097246SAdrian Prantl // take all the argument data into account. On rare cases where some argument 44205097246SAdrian Prantl // sticks with certain option sets, this function returns the option set 44305097246SAdrian Prantl // filtered args. 444b9c1b51eSKate Stone void CommandObject::GetFormattedCommandArguments(Stream &str, 445b9c1b51eSKate Stone uint32_t opt_set_mask) { 446e139cf23SCaroline Tice int num_args = m_arguments.size(); 447b9c1b51eSKate Stone for (int i = 0; i < num_args; ++i) { 448e139cf23SCaroline Tice if (i > 0) 449e139cf23SCaroline Tice str.Printf(" "); 45034ddc8dbSJohnny Chen CommandArgumentEntry arg_entry = 451b9c1b51eSKate Stone opt_set_mask == LLDB_OPT_SET_ALL 452b9c1b51eSKate Stone ? m_arguments[i] 45334ddc8dbSJohnny Chen : OptSetFiltered(opt_set_mask, m_arguments[i]); 45494038c57SVenkata Ramanaiah Nalamothu // This argument is not associated with the current option set, so skip it. 45594038c57SVenkata Ramanaiah Nalamothu if (arg_entry.empty()) 45694038c57SVenkata Ramanaiah Nalamothu continue; 457e139cf23SCaroline Tice int num_alternatives = arg_entry.size(); 458405fe67fSCaroline Tice 459b9c1b51eSKate Stone if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) { 460405fe67fSCaroline Tice const char *first_name = GetArgumentName(arg_entry[0].arg_type); 461405fe67fSCaroline Tice const char *second_name = GetArgumentName(arg_entry[1].arg_type); 462b9c1b51eSKate Stone switch (arg_entry[0].arg_repetition) { 463405fe67fSCaroline Tice case eArgRepeatPairPlain: 464405fe67fSCaroline Tice str.Printf("<%s> <%s>", first_name, second_name); 465405fe67fSCaroline Tice break; 466405fe67fSCaroline Tice case eArgRepeatPairOptional: 467405fe67fSCaroline Tice str.Printf("[<%s> <%s>]", first_name, second_name); 468405fe67fSCaroline Tice break; 469405fe67fSCaroline Tice case eArgRepeatPairPlus: 470b9c1b51eSKate Stone str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, 471b9c1b51eSKate Stone first_name, second_name); 472405fe67fSCaroline Tice break; 473405fe67fSCaroline Tice case eArgRepeatPairStar: 474b9c1b51eSKate Stone str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, 475b9c1b51eSKate Stone first_name, second_name); 476405fe67fSCaroline Tice break; 477405fe67fSCaroline Tice case eArgRepeatPairRange: 478b9c1b51eSKate Stone str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, 479b9c1b51eSKate Stone first_name, second_name); 480405fe67fSCaroline Tice break; 481405fe67fSCaroline Tice case eArgRepeatPairRangeOptional: 482b9c1b51eSKate Stone str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, 483b9c1b51eSKate Stone first_name, second_name); 484405fe67fSCaroline Tice break; 485b9c1b51eSKate Stone // Explicitly test for all the rest of the cases, so if new types get 48605097246SAdrian Prantl // added we will notice the missing case statement(s). 487ca1176aaSCaroline Tice case eArgRepeatPlain: 488ca1176aaSCaroline Tice case eArgRepeatOptional: 489ca1176aaSCaroline Tice case eArgRepeatPlus: 490ca1176aaSCaroline Tice case eArgRepeatStar: 491ca1176aaSCaroline Tice case eArgRepeatRange: 492b9c1b51eSKate Stone // These should not be reached, as they should fail the IsPairType test 493b9c1b51eSKate Stone // above. 494ca1176aaSCaroline Tice break; 495405fe67fSCaroline Tice } 496b9c1b51eSKate Stone } else { 497e139cf23SCaroline Tice StreamString names; 498b9c1b51eSKate Stone for (int j = 0; j < num_alternatives; ++j) { 499e139cf23SCaroline Tice if (j > 0) 500e139cf23SCaroline Tice names.Printf(" | "); 501e139cf23SCaroline Tice names.Printf("%s", GetArgumentName(arg_entry[j].arg_type)); 502e139cf23SCaroline Tice } 503c156427dSZachary Turner 504adcd0268SBenjamin Kramer std::string name_str = std::string(names.GetString()); 505b9c1b51eSKate Stone switch (arg_entry[0].arg_repetition) { 506e139cf23SCaroline Tice case eArgRepeatPlain: 507c156427dSZachary Turner str.Printf("<%s>", name_str.c_str()); 508e139cf23SCaroline Tice break; 509e139cf23SCaroline Tice case eArgRepeatPlus: 510c156427dSZachary Turner str.Printf("<%s> [<%s> [...]]", name_str.c_str(), name_str.c_str()); 511e139cf23SCaroline Tice break; 512e139cf23SCaroline Tice case eArgRepeatStar: 513c156427dSZachary Turner str.Printf("[<%s> [<%s> [...]]]", name_str.c_str(), name_str.c_str()); 514e139cf23SCaroline Tice break; 515e139cf23SCaroline Tice case eArgRepeatOptional: 516c156427dSZachary Turner str.Printf("[<%s>]", name_str.c_str()); 517e139cf23SCaroline Tice break; 518405fe67fSCaroline Tice case eArgRepeatRange: 519c156427dSZachary Turner str.Printf("<%s_1> .. <%s_n>", name_str.c_str(), name_str.c_str()); 520ca1176aaSCaroline Tice break; 521b9c1b51eSKate Stone // Explicitly test for all the rest of the cases, so if new types get 52205097246SAdrian Prantl // added we will notice the missing case statement(s). 523ca1176aaSCaroline Tice case eArgRepeatPairPlain: 524ca1176aaSCaroline Tice case eArgRepeatPairOptional: 525ca1176aaSCaroline Tice case eArgRepeatPairPlus: 526ca1176aaSCaroline Tice case eArgRepeatPairStar: 527ca1176aaSCaroline Tice case eArgRepeatPairRange: 528ca1176aaSCaroline Tice case eArgRepeatPairRangeOptional: 529b9c1b51eSKate Stone // These should not be hit, as they should pass the IsPairType test 53005097246SAdrian Prantl // above, and control should have gone into the other branch of the if 53105097246SAdrian Prantl // statement. 532ca1176aaSCaroline Tice break; 533405fe67fSCaroline Tice } 534e139cf23SCaroline Tice } 535e139cf23SCaroline Tice } 536e139cf23SCaroline Tice } 537e139cf23SCaroline Tice 53814f6b2c0SZachary Turner CommandArgumentType 53914f6b2c0SZachary Turner CommandObject::LookupArgumentName(llvm::StringRef arg_name) { 540e139cf23SCaroline Tice CommandArgumentType return_type = eArgTypeLastArg; 541e139cf23SCaroline Tice 54214f6b2c0SZachary Turner arg_name = arg_name.ltrim('<').rtrim('>'); 543e139cf23SCaroline Tice 544e139cf23SCaroline Tice for (int i = 0; i < eArgTypeLastArg; ++i) 545*7ced9fffSJonas Devlieghere if (arg_name == g_argument_table[i].arg_name) 546*7ced9fffSJonas Devlieghere return_type = g_argument_table[i].arg_type; 547e139cf23SCaroline Tice 548e139cf23SCaroline Tice return return_type; 549e139cf23SCaroline Tice } 550e139cf23SCaroline Tice 551b9c1b51eSKate Stone void CommandObject::FormatLongHelpText(Stream &output_strm, 552442f6530SZachary Turner llvm::StringRef long_help) { 553ea671fbdSKate Stone CommandInterpreter &interpreter = GetCommandInterpreter(); 554adcd0268SBenjamin Kramer std::stringstream lineStream{std::string(long_help)}; 555ea671fbdSKate Stone std::string line; 556ea671fbdSKate Stone while (std::getline(lineStream, line)) { 557ea671fbdSKate Stone if (line.empty()) { 558ea671fbdSKate Stone output_strm << "\n"; 559ea671fbdSKate Stone continue; 560ea671fbdSKate Stone } 561ea671fbdSKate Stone size_t result = line.find_first_not_of(" \t"); 562ea671fbdSKate Stone if (result == std::string::npos) { 563ea671fbdSKate Stone result = 0; 564ea671fbdSKate Stone } 565ea671fbdSKate Stone std::string whitespace_prefix = line.substr(0, result); 566ea671fbdSKate Stone std::string remainder = line.substr(result); 567ff058e73SJonas Devlieghere interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix, 568ff058e73SJonas Devlieghere remainder); 569ea671fbdSKate Stone } 570ea671fbdSKate Stone } 571ea671fbdSKate Stone 572b9c1b51eSKate Stone void CommandObject::GenerateHelpText(CommandReturnObject &result) { 5739b62d1d5SEnrico Granata GenerateHelpText(result.GetOutputStream()); 5749b62d1d5SEnrico Granata 5759b62d1d5SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 5769b62d1d5SEnrico Granata } 5779b62d1d5SEnrico Granata 578b9c1b51eSKate Stone void CommandObject::GenerateHelpText(Stream &output_strm) { 5799b62d1d5SEnrico Granata CommandInterpreter &interpreter = GetCommandInterpreter(); 5809b62d1d5SEnrico Granata std::string help_text(GetHelp()); 581d7432360SJonas Devlieghere if (WantsRawCommandString()) { 5827428a18cSKate Stone help_text.append(" Expects 'raw' input (see 'help raw-input'.)"); 583d7432360SJonas Devlieghere } 584d7432360SJonas Devlieghere interpreter.OutputFormattedHelpText(output_strm, "", help_text); 58503c9f364SZachary Turner output_strm << "\nSyntax: " << GetSyntax() << "\n"; 5867428a18cSKate Stone Options *options = GetOptions(); 587b9c1b51eSKate Stone if (options != nullptr) { 588b9c1b51eSKate Stone options->GenerateOptionUsage( 589e473e79cSDavid Spickett output_strm, *this, 590b9c1b51eSKate Stone GetCommandInterpreter().GetDebugger().GetTerminalWidth()); 5917428a18cSKate Stone } 592442f6530SZachary Turner llvm::StringRef long_help = GetHelpLong(); 593442f6530SZachary Turner if (!long_help.empty()) { 594ea671fbdSKate Stone FormatLongHelpText(output_strm, long_help); 5957428a18cSKate Stone } 596b9c1b51eSKate Stone if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) { 597b9c1b51eSKate Stone if (WantsRawCommandString() && !WantsCompletion()) { 598b9c1b51eSKate Stone // Emit the message about using ' -- ' between the end of the command 59905097246SAdrian Prantl // options and the raw input conditionally, i.e., only if the command 60005097246SAdrian Prantl // object does not want completion. 6017428a18cSKate Stone interpreter.OutputFormattedHelpText( 6027428a18cSKate Stone output_strm, "", "", 603b9c1b51eSKate Stone "\nImportant Note: Because this command takes 'raw' input, if you " 604b9c1b51eSKate Stone "use any command options" 605b9c1b51eSKate Stone " you must use ' -- ' between the end of the command options and the " 606b9c1b51eSKate Stone "beginning of the raw input.", 6077428a18cSKate Stone 1); 608b9c1b51eSKate Stone } else if (GetNumArgumentEntries() > 0) { 609b9c1b51eSKate Stone // Also emit a warning about using "--" in case you are using a command 610b9c1b51eSKate Stone // that takes options and arguments. 6117428a18cSKate Stone interpreter.OutputFormattedHelpText( 612b9c1b51eSKate Stone output_strm, "", "", 613b9c1b51eSKate Stone "\nThis command takes options and free-form arguments. If your " 614b9c1b51eSKate Stone "arguments resemble" 615b9c1b51eSKate Stone " option specifiers (i.e., they start with a - or --), you must use " 616b9c1b51eSKate Stone "' -- ' between" 6177428a18cSKate Stone " the end of the command options and the beginning of the arguments.", 6187428a18cSKate Stone 1); 6199b62d1d5SEnrico Granata } 6209b62d1d5SEnrico Granata } 621bfb75e9bSEnrico Granata } 6229b62d1d5SEnrico Granata 623b9c1b51eSKate Stone void CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, 624b9c1b51eSKate Stone CommandArgumentType ID, 625b9c1b51eSKate Stone CommandArgumentType IDRange) { 626184d7a72SJohnny Chen CommandArgumentData id_arg; 627184d7a72SJohnny Chen CommandArgumentData id_range_arg; 628184d7a72SJohnny Chen 629b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 630b9c1b51eSKate Stone // command. 631de753464SJohnny Chen id_arg.arg_type = ID; 632184d7a72SJohnny Chen id_arg.arg_repetition = eArgRepeatOptional; 633184d7a72SJohnny Chen 634b9c1b51eSKate Stone // Create the second variant for the first (and only) argument for this 635b9c1b51eSKate Stone // command. 636de753464SJohnny Chen id_range_arg.arg_type = IDRange; 637184d7a72SJohnny Chen id_range_arg.arg_repetition = eArgRepeatOptional; 638184d7a72SJohnny Chen 639b9c1b51eSKate Stone // The first (and only) argument for this command could be either an id or an 64005097246SAdrian Prantl // id_range. Push both variants into the entry for the first argument for 64105097246SAdrian Prantl // this command. 642184d7a72SJohnny Chen arg.push_back(id_arg); 643184d7a72SJohnny Chen arg.push_back(id_range_arg); 644184d7a72SJohnny Chen } 645184d7a72SJohnny Chen 646b9c1b51eSKate Stone const char *CommandObject::GetArgumentTypeAsCString( 647b9c1b51eSKate Stone const lldb::CommandArgumentType arg_type) { 648b9c1b51eSKate Stone assert(arg_type < eArgTypeLastArg && 649b9c1b51eSKate Stone "Invalid argument type passed to GetArgumentTypeAsCString"); 650*7ced9fffSJonas Devlieghere return g_argument_table[arg_type].arg_name; 6519d0402b1SGreg Clayton } 6529d0402b1SGreg Clayton 653b9c1b51eSKate Stone const char *CommandObject::GetArgumentDescriptionAsCString( 654b9c1b51eSKate Stone const lldb::CommandArgumentType arg_type) { 655b9c1b51eSKate Stone assert(arg_type < eArgTypeLastArg && 656b9c1b51eSKate Stone "Invalid argument type passed to GetArgumentDescriptionAsCString"); 657*7ced9fffSJonas Devlieghere return g_argument_table[arg_type].help_text; 6589d0402b1SGreg Clayton } 6599d0402b1SGreg Clayton 660cb2380c9SRaphael Isemann Target &CommandObject::GetDummyTarget() { 661b2fa3b92SJonas Devlieghere return m_interpreter.GetDebugger().GetDummyTarget(); 662893c932aSJim Ingham } 663893c932aSJim Ingham 664cb2380c9SRaphael Isemann Target &CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) { 665b2fa3b92SJonas Devlieghere return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy); 666893c932aSJim Ingham } 667893c932aSJim Ingham 66804a4c091SRaphael Isemann Target &CommandObject::GetSelectedTarget() { 66904a4c091SRaphael Isemann assert(m_flags.AnySet(eCommandRequiresTarget | eCommandProcessMustBePaused | 67004a4c091SRaphael Isemann eCommandProcessMustBeLaunched | eCommandRequiresFrame | 67104a4c091SRaphael Isemann eCommandRequiresThread | eCommandRequiresProcess | 67204a4c091SRaphael Isemann eCommandRequiresRegContext) && 67304a4c091SRaphael Isemann "GetSelectedTarget called from object that may have no target"); 67404a4c091SRaphael Isemann return *m_interpreter.GetDebugger().GetSelectedTarget(); 67504a4c091SRaphael Isemann } 67604a4c091SRaphael Isemann 677b9c1b51eSKate Stone Thread *CommandObject::GetDefaultThread() { 6788d94ba0fSJim Ingham Thread *thread_to_use = m_exe_ctx.GetThreadPtr(); 6798d94ba0fSJim Ingham if (thread_to_use) 6808d94ba0fSJim Ingham return thread_to_use; 6818d94ba0fSJim Ingham 6828d94ba0fSJim Ingham Process *process = m_exe_ctx.GetProcessPtr(); 683b9c1b51eSKate Stone if (!process) { 6848d94ba0fSJim Ingham Target *target = m_exe_ctx.GetTargetPtr(); 685b9c1b51eSKate Stone if (!target) { 6868d94ba0fSJim Ingham target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 6878d94ba0fSJim Ingham } 6888d94ba0fSJim Ingham if (target) 6898d94ba0fSJim Ingham process = target->GetProcessSP().get(); 6908d94ba0fSJim Ingham } 6918d94ba0fSJim Ingham 6928d94ba0fSJim Ingham if (process) 6938d94ba0fSJim Ingham return process->GetThreadList().GetSelectedThread().get(); 6948d94ba0fSJim Ingham else 6958d94ba0fSJim Ingham return nullptr; 6968d94ba0fSJim Ingham } 6978d94ba0fSJim Ingham 698b9c1b51eSKate Stone bool CommandObjectParsed::Execute(const char *args_string, 699b9c1b51eSKate Stone CommandReturnObject &result) { 7005a988416SJim Ingham bool handled = false; 7015a988416SJim Ingham Args cmd_args(args_string); 702b9c1b51eSKate Stone if (HasOverrideCallback()) { 7035a988416SJim Ingham Args full_args(GetCommandName()); 7045a988416SJim Ingham full_args.AppendArguments(cmd_args); 705b9c1b51eSKate Stone handled = 706b9c1b51eSKate Stone InvokeOverrideCallback(full_args.GetConstArgumentVector(), result); 7075a988416SJim Ingham } 708b9c1b51eSKate Stone if (!handled) { 70997d2c401SZachary Turner for (auto entry : llvm::enumerate(cmd_args.entries())) { 7100d9a201eSRaphael Isemann if (!entry.value().ref().empty() && entry.value().ref().front() == '`') { 711b9c1b51eSKate Stone cmd_args.ReplaceArgumentAtIndex( 7124eb8449dSZachary Turner entry.index(), 7134eb8449dSZachary Turner m_interpreter.ProcessEmbeddedScriptCommands(entry.value().c_str())); 71497d2c401SZachary Turner } 7155a988416SJim Ingham } 7165a988416SJim Ingham 717b9c1b51eSKate Stone if (CheckRequirements(result)) { 718b9c1b51eSKate Stone if (ParseOptions(cmd_args, result)) { 719b9c1b51eSKate Stone // Call the command-specific version of 'Execute', passing it the 720b9c1b51eSKate Stone // already processed arguments. 721c1b07d61SJim Ingham if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) { 722c1b07d61SJim Ingham result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.", 723c1b07d61SJim Ingham GetCommandName()); 724c1b07d61SJim Ingham return false; 725c1b07d61SJim Ingham } 7265a988416SJim Ingham handled = DoExecute(cmd_args, result); 7275a988416SJim Ingham } 728f9fc609fSGreg Clayton } 729f9fc609fSGreg Clayton 730f9fc609fSGreg Clayton Cleanup(); 731f9fc609fSGreg Clayton } 7325a988416SJim Ingham return handled; 7335a988416SJim Ingham } 7345a988416SJim Ingham 735b9c1b51eSKate Stone bool CommandObjectRaw::Execute(const char *args_string, 736b9c1b51eSKate Stone CommandReturnObject &result) { 7375a988416SJim Ingham bool handled = false; 738b9c1b51eSKate Stone if (HasOverrideCallback()) { 7395a988416SJim Ingham std::string full_command(GetCommandName()); 7405a988416SJim Ingham full_command += ' '; 7415a988416SJim Ingham full_command += args_string; 742d78c9576SEd Maste const char *argv[2] = {nullptr, nullptr}; 7435a988416SJim Ingham argv[0] = full_command.c_str(); 7443b652621SJim Ingham handled = InvokeOverrideCallback(argv, result); 7455a988416SJim Ingham } 746b9c1b51eSKate Stone if (!handled) { 747f9fc609fSGreg Clayton if (CheckRequirements(result)) 7485a988416SJim Ingham handled = DoExecute(args_string, result); 749f9fc609fSGreg Clayton 750f9fc609fSGreg Clayton Cleanup(); 7515a988416SJim Ingham } 7525a988416SJim Ingham return handled; 7535a988416SJim Ingham } 754