1cfca06d7SDimitry Andric //===-- CommandObject.cpp -------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/Interpreter/CommandObject.h"
10f034231aSEd Maste
11f034231aSEd Maste #include <map>
1214f1b3e8SDimitry Andric #include <sstream>
1314f1b3e8SDimitry Andric #include <string>
14f034231aSEd Maste
15344a3780SDimitry Andric #include <cctype>
16344a3780SDimitry Andric #include <cstdlib>
17f034231aSEd Maste
18f034231aSEd Maste #include "lldb/Core/Address.h"
194b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
20f034231aSEd Maste #include "lldb/Interpreter/Options.h"
21ef5d0b5eSDimitry Andric #include "lldb/Utility/ArchSpec.h"
22cfca06d7SDimitry Andric #include "llvm/ADT/ScopeExit.h"
23f034231aSEd Maste
24f034231aSEd Maste // These are for the Sourcename completers.
25f034231aSEd Maste // FIXME: Make a separate file for the completers.
265e95aa85SEd Maste #include "lldb/DataFormatters/FormatManager.h"
27f034231aSEd Maste #include "lldb/Target/Process.h"
28f034231aSEd Maste #include "lldb/Target/Target.h"
2974a628f7SDimitry Andric #include "lldb/Utility/FileSpec.h"
307fa27ce4SDimitry Andric #include "lldb/Utility/FileSpecList.h"
31f034231aSEd Maste
32e81d9d49SDimitry Andric #include "lldb/Target/Language.h"
33e81d9d49SDimitry Andric
34f034231aSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
354b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
36f034231aSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
37f034231aSEd Maste
38f034231aSEd Maste using namespace lldb;
39f034231aSEd Maste using namespace lldb_private;
40f034231aSEd Maste
41f034231aSEd Maste // CommandObject
42f034231aSEd Maste
CommandObject(CommandInterpreter & interpreter,llvm::StringRef name,llvm::StringRef help,llvm::StringRef syntax,uint32_t flags)43cfca06d7SDimitry Andric CommandObject::CommandObject(CommandInterpreter &interpreter,
44cfca06d7SDimitry Andric llvm::StringRef name, llvm::StringRef help,
45cfca06d7SDimitry Andric llvm::StringRef syntax, uint32_t flags)
46cfca06d7SDimitry Andric : m_interpreter(interpreter), m_cmd_name(std::string(name)),
47344a3780SDimitry Andric m_flags(flags), m_deprecated_command_override_callback(nullptr),
4814f1b3e8SDimitry Andric m_command_override_callback(nullptr), m_command_override_baton(nullptr) {
49cfca06d7SDimitry Andric m_cmd_help_short = std::string(help);
50cfca06d7SDimitry Andric m_cmd_syntax = std::string(syntax);
51f034231aSEd Maste }
52f034231aSEd Maste
GetDebugger()535f29bb8aSDimitry Andric Debugger &CommandObject::GetDebugger() { return m_interpreter.GetDebugger(); }
545f29bb8aSDimitry Andric
GetHelp()5514f1b3e8SDimitry Andric llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; }
56f034231aSEd Maste
GetHelpLong()5714f1b3e8SDimitry Andric llvm::StringRef CommandObject::GetHelpLong() { return m_cmd_help_long; }
58f034231aSEd Maste
GetSyntax()5914f1b3e8SDimitry Andric llvm::StringRef CommandObject::GetSyntax() {
60ef5d0b5eSDimitry Andric if (!m_cmd_syntax.empty())
6114f1b3e8SDimitry Andric return m_cmd_syntax;
6214f1b3e8SDimitry Andric
63f034231aSEd Maste StreamString syntax_str;
6414f1b3e8SDimitry Andric syntax_str.PutCString(GetCommandName());
6514f1b3e8SDimitry Andric
66f3fbd1c0SDimitry Andric if (!IsDashDashCommand() && GetOptions() != nullptr)
6714f1b3e8SDimitry Andric syntax_str.PutCString(" <cmd-options>");
6814f1b3e8SDimitry Andric
6914f1b3e8SDimitry Andric if (!m_arguments.empty()) {
7014f1b3e8SDimitry Andric syntax_str.PutCString(" ");
7114f1b3e8SDimitry Andric
7214f1b3e8SDimitry Andric if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() &&
7314f1b3e8SDimitry Andric GetOptions()->NumCommandOptions())
7414f1b3e8SDimitry Andric syntax_str.PutCString("-- ");
75f034231aSEd Maste GetFormattedCommandArguments(syntax_str);
76f034231aSEd Maste }
77cfca06d7SDimitry Andric m_cmd_syntax = std::string(syntax_str.GetString());
7814f1b3e8SDimitry Andric
7914f1b3e8SDimitry Andric return m_cmd_syntax;
80f034231aSEd Maste }
81f034231aSEd Maste
GetCommandName() const8214f1b3e8SDimitry Andric llvm::StringRef CommandObject::GetCommandName() const { return m_cmd_name; }
83f034231aSEd Maste
SetCommandName(llvm::StringRef name)84cfca06d7SDimitry Andric void CommandObject::SetCommandName(llvm::StringRef name) {
85cfca06d7SDimitry Andric m_cmd_name = std::string(name);
86cfca06d7SDimitry Andric }
87f034231aSEd Maste
SetHelp(llvm::StringRef str)88cfca06d7SDimitry Andric void CommandObject::SetHelp(llvm::StringRef str) {
89cfca06d7SDimitry Andric m_cmd_help_short = std::string(str);
90cfca06d7SDimitry Andric }
91f034231aSEd Maste
SetHelpLong(llvm::StringRef str)92cfca06d7SDimitry Andric void CommandObject::SetHelpLong(llvm::StringRef str) {
93cfca06d7SDimitry Andric m_cmd_help_long = std::string(str);
94cfca06d7SDimitry Andric }
955e95aa85SEd Maste
SetSyntax(llvm::StringRef str)96cfca06d7SDimitry Andric void CommandObject::SetSyntax(llvm::StringRef str) {
97cfca06d7SDimitry Andric m_cmd_syntax = std::string(str);
98cfca06d7SDimitry Andric }
99f034231aSEd Maste
GetOptions()10014f1b3e8SDimitry Andric Options *CommandObject::GetOptions() {
101f73363f1SDimitry Andric // By default commands don't have options unless this virtual function is
102f73363f1SDimitry Andric // overridden by base classes.
1030cac4ca3SEd Maste return nullptr;
104f034231aSEd Maste }
105f034231aSEd Maste
ParseOptions(Args & args,CommandReturnObject & result)10614f1b3e8SDimitry Andric bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
107f034231aSEd Maste // See if the subclass has options?
108f034231aSEd Maste Options *options = GetOptions();
10914f1b3e8SDimitry Andric if (options != nullptr) {
110b76161e4SDimitry Andric Status error;
111f034231aSEd Maste
11214f1b3e8SDimitry Andric auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
11314f1b3e8SDimitry Andric options->NotifyOptionParsingStarting(&exe_ctx);
11414f1b3e8SDimitry Andric
11514f1b3e8SDimitry Andric const bool require_validation = true;
116f73363f1SDimitry Andric llvm::Expected<Args> args_or = options->Parse(
117f73363f1SDimitry Andric args, &exe_ctx, GetCommandInterpreter().GetPlatform(true),
11814f1b3e8SDimitry Andric require_validation);
119f034231aSEd Maste
120f73363f1SDimitry Andric if (args_or) {
121f73363f1SDimitry Andric args = std::move(*args_or);
12214f1b3e8SDimitry Andric error = options->NotifyOptionParsingFinished(&exe_ctx);
123f73363f1SDimitry Andric } else
124f73363f1SDimitry Andric error = args_or.takeError();
125f034231aSEd Maste
12614f1b3e8SDimitry Andric if (error.Success()) {
127f034231aSEd Maste if (options->VerifyOptions(result))
128f034231aSEd Maste return true;
12914f1b3e8SDimitry Andric } else {
130f034231aSEd Maste const char *error_cstr = error.AsCString();
13114f1b3e8SDimitry Andric if (error_cstr) {
132f034231aSEd Maste // We got an error string, lets use that
133f034231aSEd Maste result.AppendError(error_cstr);
13414f1b3e8SDimitry Andric } else {
135f034231aSEd Maste // No error string, output the usage information into result
13614f1b3e8SDimitry Andric options->GenerateOptionUsage(
137145449b1SDimitry Andric result.GetErrorStream(), *this,
13814f1b3e8SDimitry Andric GetCommandInterpreter().GetDebugger().GetTerminalWidth());
139f034231aSEd Maste }
140f034231aSEd Maste }
141f034231aSEd Maste result.SetStatus(eReturnStatusFailed);
142f034231aSEd Maste return false;
143f034231aSEd Maste }
144f034231aSEd Maste return true;
145f034231aSEd Maste }
146f034231aSEd Maste
CheckRequirements(CommandReturnObject & result)14714f1b3e8SDimitry Andric bool CommandObject::CheckRequirements(CommandReturnObject &result) {
148f73363f1SDimitry Andric // Nothing should be stored in m_exe_ctx between running commands as
149f73363f1SDimitry Andric // m_exe_ctx has shared pointers to the target, process, thread and frame and
150f73363f1SDimitry Andric // we don't want any CommandObject instances to keep any of these objects
151f73363f1SDimitry Andric // around longer than for a single command. Every command should call
1525f29bb8aSDimitry Andric // CommandObject::Cleanup() after it has completed.
1535f29bb8aSDimitry Andric assert(!m_exe_ctx.GetTargetPtr());
1545f29bb8aSDimitry Andric assert(!m_exe_ctx.GetProcessPtr());
1555f29bb8aSDimitry Andric assert(!m_exe_ctx.GetThreadPtr());
1565f29bb8aSDimitry Andric assert(!m_exe_ctx.GetFramePtr());
157f034231aSEd Maste
158f73363f1SDimitry Andric // Lock down the interpreter's execution context prior to running the command
159f73363f1SDimitry Andric // so we guarantee the selected target, process, thread and frame can't go
160f73363f1SDimitry Andric // away during the execution
161f034231aSEd Maste m_exe_ctx = m_interpreter.GetExecutionContext();
162f034231aSEd Maste
163f034231aSEd Maste const uint32_t flags = GetFlags().Get();
16414f1b3e8SDimitry Andric if (flags & (eCommandRequiresTarget | eCommandRequiresProcess |
16514f1b3e8SDimitry Andric eCommandRequiresThread | eCommandRequiresFrame |
16614f1b3e8SDimitry Andric eCommandTryTargetAPILock)) {
167f034231aSEd Maste
16814f1b3e8SDimitry Andric if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) {
169f034231aSEd Maste result.AppendError(GetInvalidTargetDescription());
170f034231aSEd Maste return false;
171f034231aSEd Maste }
172f034231aSEd Maste
17314f1b3e8SDimitry Andric if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) {
174205afe67SEd Maste if (!m_exe_ctx.HasTargetScope())
175205afe67SEd Maste result.AppendError(GetInvalidTargetDescription());
176205afe67SEd Maste else
177f034231aSEd Maste result.AppendError(GetInvalidProcessDescription());
178f034231aSEd Maste return false;
179f034231aSEd Maste }
180f034231aSEd Maste
18114f1b3e8SDimitry Andric if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) {
182205afe67SEd Maste if (!m_exe_ctx.HasTargetScope())
183205afe67SEd Maste result.AppendError(GetInvalidTargetDescription());
184205afe67SEd Maste else if (!m_exe_ctx.HasProcessScope())
185205afe67SEd Maste result.AppendError(GetInvalidProcessDescription());
186205afe67SEd Maste else
187f034231aSEd Maste result.AppendError(GetInvalidThreadDescription());
188f034231aSEd Maste return false;
189f034231aSEd Maste }
190f034231aSEd Maste
19114f1b3e8SDimitry Andric if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) {
192205afe67SEd Maste if (!m_exe_ctx.HasTargetScope())
193205afe67SEd Maste result.AppendError(GetInvalidTargetDescription());
194205afe67SEd Maste else if (!m_exe_ctx.HasProcessScope())
195205afe67SEd Maste result.AppendError(GetInvalidProcessDescription());
196205afe67SEd Maste else if (!m_exe_ctx.HasThreadScope())
197205afe67SEd Maste result.AppendError(GetInvalidThreadDescription());
198205afe67SEd Maste else
199f034231aSEd Maste result.AppendError(GetInvalidFrameDescription());
200f034231aSEd Maste return false;
201f034231aSEd Maste }
202f034231aSEd Maste
20314f1b3e8SDimitry Andric if ((flags & eCommandRequiresRegContext) &&
20414f1b3e8SDimitry Andric (m_exe_ctx.GetRegisterContext() == nullptr)) {
205f034231aSEd Maste result.AppendError(GetInvalidRegContextDescription());
206f034231aSEd Maste return false;
207f034231aSEd Maste }
208f034231aSEd Maste
20914f1b3e8SDimitry Andric if (flags & eCommandTryTargetAPILock) {
210f034231aSEd Maste Target *target = m_exe_ctx.GetTargetPtr();
211f034231aSEd Maste if (target)
21214f1b3e8SDimitry Andric m_api_locker =
21314f1b3e8SDimitry Andric std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());
214f034231aSEd Maste }
215f034231aSEd Maste }
216f034231aSEd Maste
21714f1b3e8SDimitry Andric if (GetFlags().AnySet(eCommandProcessMustBeLaunched |
21814f1b3e8SDimitry Andric eCommandProcessMustBePaused)) {
219f034231aSEd Maste Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
22014f1b3e8SDimitry Andric if (process == nullptr) {
221f034231aSEd Maste // A process that is not running is considered paused.
22214f1b3e8SDimitry Andric if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
223f034231aSEd Maste result.AppendError("Process must exist.");
224f034231aSEd Maste return false;
225f034231aSEd Maste }
22614f1b3e8SDimitry Andric } else {
227f034231aSEd Maste StateType state = process->GetState();
22814f1b3e8SDimitry Andric switch (state) {
229f034231aSEd Maste case eStateInvalid:
230f034231aSEd Maste case eStateSuspended:
231f034231aSEd Maste case eStateCrashed:
232f034231aSEd Maste case eStateStopped:
233f034231aSEd Maste break;
234f034231aSEd Maste
235f034231aSEd Maste case eStateConnected:
236f034231aSEd Maste case eStateAttaching:
237f034231aSEd Maste case eStateLaunching:
238f034231aSEd Maste case eStateDetached:
239f034231aSEd Maste case eStateExited:
240f034231aSEd Maste case eStateUnloaded:
24114f1b3e8SDimitry Andric if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
242f034231aSEd Maste result.AppendError("Process must be launched.");
243f034231aSEd Maste return false;
244f034231aSEd Maste }
245f034231aSEd Maste break;
246f034231aSEd Maste
247f034231aSEd Maste case eStateRunning:
248f034231aSEd Maste case eStateStepping:
24914f1b3e8SDimitry Andric if (GetFlags().Test(eCommandProcessMustBePaused)) {
25014f1b3e8SDimitry Andric result.AppendError("Process is running. Use 'process interrupt' to "
25114f1b3e8SDimitry Andric "pause execution.");
252f034231aSEd Maste return false;
253f034231aSEd Maste }
254f034231aSEd Maste }
255f034231aSEd Maste }
256f034231aSEd Maste }
257b60736ecSDimitry Andric
258b60736ecSDimitry Andric if (GetFlags().Test(eCommandProcessMustBeTraced)) {
259b60736ecSDimitry Andric Target *target = m_exe_ctx.GetTargetPtr();
260b60736ecSDimitry Andric if (target && !target->GetTrace()) {
261344a3780SDimitry Andric result.AppendError("Process is not being traced.");
262b60736ecSDimitry Andric return false;
263b60736ecSDimitry Andric }
264b60736ecSDimitry Andric }
265b60736ecSDimitry Andric
266f034231aSEd Maste return true;
267f034231aSEd Maste }
268f034231aSEd Maste
Cleanup()26914f1b3e8SDimitry Andric void CommandObject::Cleanup() {
270f034231aSEd Maste m_exe_ctx.Clear();
271f3fbd1c0SDimitry Andric if (m_api_locker.owns_lock())
272f3fbd1c0SDimitry Andric m_api_locker.unlock();
273f034231aSEd Maste }
274f034231aSEd Maste
HandleCompletion(CompletionRequest & request)275ead24645SDimitry Andric void CommandObject::HandleCompletion(CompletionRequest &request) {
276cfca06d7SDimitry Andric
277cfca06d7SDimitry Andric m_exe_ctx = m_interpreter.GetExecutionContext();
278cfca06d7SDimitry Andric auto reset_ctx = llvm::make_scope_exit([this]() { Cleanup(); });
279cfca06d7SDimitry Andric
280e81d9d49SDimitry Andric // Default implementation of WantsCompletion() is !WantsRawCommandString().
281f73363f1SDimitry Andric // Subclasses who want raw command string but desire, for example, argument
282f73363f1SDimitry Andric // completion should override WantsCompletion() to return true, instead.
28314f1b3e8SDimitry Andric if (WantsRawCommandString() && !WantsCompletion()) {
28414f1b3e8SDimitry Andric // FIXME: Abstract telling the completion to insert the completion
28514f1b3e8SDimitry Andric // character.
286ead24645SDimitry Andric return;
28714f1b3e8SDimitry Andric } else {
288f034231aSEd Maste // Can we do anything generic with the options?
289f034231aSEd Maste Options *cur_options = GetOptions();
290cfca06d7SDimitry Andric CommandReturnObject result(m_interpreter.GetDebugger().GetUseColor());
291f034231aSEd Maste OptionElementVector opt_element_vector;
292f034231aSEd Maste
29314f1b3e8SDimitry Andric if (cur_options != nullptr) {
294f73363f1SDimitry Andric opt_element_vector = cur_options->ParseForCompletion(
295f73363f1SDimitry Andric request.GetParsedLine(), request.GetCursorIndex());
296f034231aSEd Maste
297f73363f1SDimitry Andric bool handled_by_options = cur_options->HandleOptionCompletion(
298f73363f1SDimitry Andric request, opt_element_vector, GetCommandInterpreter());
299f034231aSEd Maste if (handled_by_options)
300ead24645SDimitry Andric return;
301f034231aSEd Maste }
302f034231aSEd Maste
303f034231aSEd Maste // If we got here, the last word is not an option or an option argument.
304ead24645SDimitry Andric HandleArgumentCompletion(request, opt_element_vector);
305f034231aSEd Maste }
306f034231aSEd Maste }
307f034231aSEd Maste
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)308ac9a064cSDimitry Andric void CommandObject::HandleArgumentCompletion(
309ac9a064cSDimitry Andric CompletionRequest &request, OptionElementVector &opt_element_vector) {
310ac9a064cSDimitry Andric size_t num_arg_entries = GetNumArgumentEntries();
311ac9a064cSDimitry Andric if (num_arg_entries != 1)
312ac9a064cSDimitry Andric return;
313ac9a064cSDimitry Andric
314ac9a064cSDimitry Andric CommandArgumentEntry *entry_ptr = GetArgumentEntryAtIndex(0);
315ac9a064cSDimitry Andric if (!entry_ptr) {
316ac9a064cSDimitry Andric assert(entry_ptr && "We said there was one entry, but there wasn't.");
317ac9a064cSDimitry Andric return; // Not worth crashing if asserts are off...
318ac9a064cSDimitry Andric }
319ac9a064cSDimitry Andric
320ac9a064cSDimitry Andric CommandArgumentEntry &entry = *entry_ptr;
321ac9a064cSDimitry Andric // For now, we only handle the simple case of one homogenous argument type.
322ac9a064cSDimitry Andric if (entry.size() != 1)
323ac9a064cSDimitry Andric return;
324ac9a064cSDimitry Andric
325ac9a064cSDimitry Andric // Look up the completion type, and if it has one, invoke it:
326ac9a064cSDimitry Andric const CommandObject::ArgumentTableEntry *arg_entry =
327ac9a064cSDimitry Andric FindArgumentDataByType(entry[0].arg_type);
328ac9a064cSDimitry Andric const ArgumentRepetitionType repeat = entry[0].arg_repetition;
329ac9a064cSDimitry Andric
330ac9a064cSDimitry Andric if (arg_entry == nullptr || arg_entry->completion_type == lldb::eNoCompletion)
331ac9a064cSDimitry Andric return;
332ac9a064cSDimitry Andric
333ac9a064cSDimitry Andric // FIXME: This should be handled higher in the Command Parser.
334ac9a064cSDimitry Andric // Check the case where this command only takes one argument, and don't do
335ac9a064cSDimitry Andric // the completion if we aren't on the first entry:
336ac9a064cSDimitry Andric if (repeat == eArgRepeatPlain && request.GetCursorIndex() != 0)
337ac9a064cSDimitry Andric return;
338ac9a064cSDimitry Andric
339ac9a064cSDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
340ac9a064cSDimitry Andric GetCommandInterpreter(), arg_entry->completion_type, request, nullptr);
341ac9a064cSDimitry Andric
342ac9a064cSDimitry Andric }
343ac9a064cSDimitry Andric
344ac9a064cSDimitry Andric
HelpTextContainsWord(llvm::StringRef search_word,bool search_short_help,bool search_long_help,bool search_syntax,bool search_options)34514f1b3e8SDimitry Andric bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
346f3fbd1c0SDimitry Andric bool search_short_help,
347f3fbd1c0SDimitry Andric bool search_long_help,
348f3fbd1c0SDimitry Andric bool search_syntax,
34914f1b3e8SDimitry Andric bool search_options) {
350f034231aSEd Maste std::string options_usage_help;
351f034231aSEd Maste
352f034231aSEd Maste bool found_word = false;
353f034231aSEd Maste
35414f1b3e8SDimitry Andric llvm::StringRef short_help = GetHelp();
35514f1b3e8SDimitry Andric llvm::StringRef long_help = GetHelpLong();
35614f1b3e8SDimitry Andric llvm::StringRef syntax_help = GetSyntax();
357f034231aSEd Maste
358344a3780SDimitry Andric if (search_short_help && short_help.contains_insensitive(search_word))
359f034231aSEd Maste found_word = true;
360344a3780SDimitry Andric else if (search_long_help && long_help.contains_insensitive(search_word))
361f034231aSEd Maste found_word = true;
362344a3780SDimitry Andric else if (search_syntax && syntax_help.contains_insensitive(search_word))
363f034231aSEd Maste found_word = true;
364f034231aSEd Maste
36514f1b3e8SDimitry Andric if (!found_word && search_options && GetOptions() != nullptr) {
366f034231aSEd Maste StreamString usage_help;
36714f1b3e8SDimitry Andric GetOptions()->GenerateOptionUsage(
368145449b1SDimitry Andric usage_help, *this,
36914f1b3e8SDimitry Andric GetCommandInterpreter().GetDebugger().GetTerminalWidth());
37014f1b3e8SDimitry Andric if (!usage_help.Empty()) {
37114f1b3e8SDimitry Andric llvm::StringRef usage_text = usage_help.GetString();
372344a3780SDimitry Andric if (usage_text.contains_insensitive(search_word))
373f034231aSEd Maste found_word = true;
374f034231aSEd Maste }
375f034231aSEd Maste }
376f034231aSEd Maste
377f034231aSEd Maste return found_word;
378f034231aSEd Maste }
379f034231aSEd Maste
ParseOptionsAndNotify(Args & args,CommandReturnObject & result,OptionGroupOptions & group_options,ExecutionContext & exe_ctx)380f73363f1SDimitry Andric bool CommandObject::ParseOptionsAndNotify(Args &args,
381f73363f1SDimitry Andric CommandReturnObject &result,
382f73363f1SDimitry Andric OptionGroupOptions &group_options,
383f73363f1SDimitry Andric ExecutionContext &exe_ctx) {
384f73363f1SDimitry Andric if (!ParseOptions(args, result))
385f73363f1SDimitry Andric return false;
386f73363f1SDimitry Andric
387f73363f1SDimitry Andric Status error(group_options.NotifyOptionParsingFinished(&exe_ctx));
388f73363f1SDimitry Andric if (error.Fail()) {
389f73363f1SDimitry Andric result.AppendError(error.AsCString());
390f73363f1SDimitry Andric return false;
391f73363f1SDimitry Andric }
392f73363f1SDimitry Andric return true;
393f73363f1SDimitry Andric }
394f73363f1SDimitry Andric
AddSimpleArgumentList(CommandArgumentType arg_type,ArgumentRepetitionType repetition_type)395ac9a064cSDimitry Andric void CommandObject::AddSimpleArgumentList(
396ac9a064cSDimitry Andric CommandArgumentType arg_type, ArgumentRepetitionType repetition_type) {
397ac9a064cSDimitry Andric
398ac9a064cSDimitry Andric CommandArgumentEntry arg_entry;
399ac9a064cSDimitry Andric CommandArgumentData simple_arg;
400ac9a064cSDimitry Andric
401ac9a064cSDimitry Andric // Define the first (and only) variant of this arg.
402ac9a064cSDimitry Andric simple_arg.arg_type = arg_type;
403ac9a064cSDimitry Andric simple_arg.arg_repetition = repetition_type;
404ac9a064cSDimitry Andric
405ac9a064cSDimitry Andric // There is only one variant this argument could be; put it into the argument
406ac9a064cSDimitry Andric // entry.
407ac9a064cSDimitry Andric arg_entry.push_back(simple_arg);
408ac9a064cSDimitry Andric
409ac9a064cSDimitry Andric // Push the data for the first argument into the m_arguments vector.
410ac9a064cSDimitry Andric m_arguments.push_back(arg_entry);
411ac9a064cSDimitry Andric }
412ac9a064cSDimitry Andric
GetNumArgumentEntries()41314f1b3e8SDimitry Andric int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); }
414f034231aSEd Maste
415f034231aSEd Maste CommandObject::CommandArgumentEntry *
GetArgumentEntryAtIndex(int idx)41614f1b3e8SDimitry Andric CommandObject::GetArgumentEntryAtIndex(int idx) {
4170cac4ca3SEd Maste if (static_cast<size_t>(idx) < m_arguments.size())
418f034231aSEd Maste return &(m_arguments[idx]);
419f034231aSEd Maste
4200cac4ca3SEd Maste return nullptr;
421f034231aSEd Maste }
422f034231aSEd Maste
4235e95aa85SEd Maste const CommandObject::ArgumentTableEntry *
FindArgumentDataByType(CommandArgumentType arg_type)42414f1b3e8SDimitry Andric CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) {
425f034231aSEd Maste for (int i = 0; i < eArgTypeLastArg; ++i)
4264b4fe385SDimitry Andric if (g_argument_table[i].arg_type == arg_type)
4274b4fe385SDimitry Andric return &(g_argument_table[i]);
428f034231aSEd Maste
4290cac4ca3SEd Maste return nullptr;
430f034231aSEd Maste }
431f034231aSEd Maste
GetArgumentHelp(Stream & str,CommandArgumentType arg_type,CommandInterpreter & interpreter)43214f1b3e8SDimitry Andric void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type,
43314f1b3e8SDimitry Andric CommandInterpreter &interpreter) {
4344b4fe385SDimitry Andric const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);
435f034231aSEd Maste
43614f1b3e8SDimitry Andric // The table is *supposed* to be kept in arg_type order, but someone *could*
43714f1b3e8SDimitry Andric // have messed it up...
438f034231aSEd Maste
439f034231aSEd Maste if (entry->arg_type != arg_type)
440f034231aSEd Maste entry = CommandObject::FindArgumentDataByType(arg_type);
441f034231aSEd Maste
442f034231aSEd Maste if (!entry)
443f034231aSEd Maste return;
444f034231aSEd Maste
445f034231aSEd Maste StreamString name_str;
446f034231aSEd Maste name_str.Printf("<%s>", entry->arg_name);
447f034231aSEd Maste
44814f1b3e8SDimitry Andric if (entry->help_function) {
44914f1b3e8SDimitry Andric llvm::StringRef help_text = entry->help_function();
45014f1b3e8SDimitry Andric if (!entry->help_function.self_formatting) {
45114f1b3e8SDimitry Andric interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
45214f1b3e8SDimitry Andric help_text, name_str.GetSize());
45314f1b3e8SDimitry Andric } else {
45414f1b3e8SDimitry Andric interpreter.OutputHelpText(str, name_str.GetString(), "--", help_text,
455f034231aSEd Maste name_str.GetSize());
456f034231aSEd Maste }
4574b4fe385SDimitry Andric } else {
45814f1b3e8SDimitry Andric interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
45914f1b3e8SDimitry Andric entry->help_text, name_str.GetSize());
4604b4fe385SDimitry Andric
4614b4fe385SDimitry Andric // Print enum values and their description if any.
4624b4fe385SDimitry Andric OptionEnumValues enum_values = g_argument_table[arg_type].enum_values;
4634b4fe385SDimitry Andric if (!enum_values.empty()) {
4644b4fe385SDimitry Andric str.EOL();
4654b4fe385SDimitry Andric size_t longest = 0;
4664b4fe385SDimitry Andric for (const OptionEnumValueElement &element : enum_values)
4674b4fe385SDimitry Andric longest =
4684b4fe385SDimitry Andric std::max(longest, llvm::StringRef(element.string_value).size());
4694b4fe385SDimitry Andric str.IndentMore(5);
4704b4fe385SDimitry Andric for (const OptionEnumValueElement &element : enum_values) {
4714b4fe385SDimitry Andric str.Indent();
4724b4fe385SDimitry Andric interpreter.OutputHelpText(str, element.string_value, ":",
4734b4fe385SDimitry Andric element.usage, longest);
4744b4fe385SDimitry Andric }
4754b4fe385SDimitry Andric str.IndentLess(5);
4764b4fe385SDimitry Andric str.EOL();
4774b4fe385SDimitry Andric }
4784b4fe385SDimitry Andric }
479f034231aSEd Maste }
480f034231aSEd Maste
GetArgumentName(CommandArgumentType arg_type)48114f1b3e8SDimitry Andric const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) {
4824b4fe385SDimitry Andric const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);
483f034231aSEd Maste
48414f1b3e8SDimitry Andric // The table is *supposed* to be kept in arg_type order, but someone *could*
48514f1b3e8SDimitry Andric // have messed it up...
486f034231aSEd Maste
487f034231aSEd Maste if (entry->arg_type != arg_type)
488f034231aSEd Maste entry = CommandObject::FindArgumentDataByType(arg_type);
489f034231aSEd Maste
490f034231aSEd Maste if (entry)
491f034231aSEd Maste return entry->arg_name;
492f034231aSEd Maste
49314f1b3e8SDimitry Andric return nullptr;
494f034231aSEd Maste }
495f034231aSEd Maste
IsPairType(ArgumentRepetitionType arg_repeat_type)49614f1b3e8SDimitry Andric bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) {
49794994d37SDimitry Andric return (arg_repeat_type == eArgRepeatPairPlain) ||
49814f1b3e8SDimitry Andric (arg_repeat_type == eArgRepeatPairOptional) ||
49914f1b3e8SDimitry Andric (arg_repeat_type == eArgRepeatPairPlus) ||
50014f1b3e8SDimitry Andric (arg_repeat_type == eArgRepeatPairStar) ||
50114f1b3e8SDimitry Andric (arg_repeat_type == eArgRepeatPairRange) ||
50294994d37SDimitry Andric (arg_repeat_type == eArgRepeatPairRangeOptional);
503f034231aSEd Maste }
504f034231aSEd Maste
505ac9a064cSDimitry Andric std::optional<ArgumentRepetitionType>
ArgRepetitionFromString(llvm::StringRef string)506ac9a064cSDimitry Andric CommandObject::ArgRepetitionFromString(llvm::StringRef string) {
507ac9a064cSDimitry Andric return llvm::StringSwitch<ArgumentRepetitionType>(string)
508ac9a064cSDimitry Andric .Case("plain", eArgRepeatPlain)
509ac9a064cSDimitry Andric .Case("optional", eArgRepeatOptional)
510ac9a064cSDimitry Andric .Case("plus", eArgRepeatPlus)
511ac9a064cSDimitry Andric .Case("star", eArgRepeatStar)
512ac9a064cSDimitry Andric .Case("range", eArgRepeatRange)
513ac9a064cSDimitry Andric .Case("pair-plain", eArgRepeatPairPlain)
514ac9a064cSDimitry Andric .Case("pair-optional", eArgRepeatPairOptional)
515ac9a064cSDimitry Andric .Case("pair-plus", eArgRepeatPairPlus)
516ac9a064cSDimitry Andric .Case("pair-star", eArgRepeatPairStar)
517ac9a064cSDimitry Andric .Case("pair-range", eArgRepeatPairRange)
518ac9a064cSDimitry Andric .Case("pair-range-optional", eArgRepeatPairRangeOptional)
519ac9a064cSDimitry Andric .Default({});
520ac9a064cSDimitry Andric }
521ac9a064cSDimitry Andric
522f034231aSEd Maste static CommandObject::CommandArgumentEntry
OptSetFiltered(uint32_t opt_set_mask,CommandObject::CommandArgumentEntry & cmd_arg_entry)52314f1b3e8SDimitry Andric OptSetFiltered(uint32_t opt_set_mask,
52414f1b3e8SDimitry Andric CommandObject::CommandArgumentEntry &cmd_arg_entry) {
525f034231aSEd Maste CommandObject::CommandArgumentEntry ret_val;
526f034231aSEd Maste for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
527f034231aSEd Maste if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
528f034231aSEd Maste ret_val.push_back(cmd_arg_entry[i]);
529f034231aSEd Maste return ret_val;
530f034231aSEd Maste }
531f034231aSEd Maste
532f73363f1SDimitry Andric // Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means
533f73363f1SDimitry Andric // take all the argument data into account. On rare cases where some argument
534f73363f1SDimitry Andric // sticks with certain option sets, this function returns the option set
535f73363f1SDimitry Andric // filtered args.
GetFormattedCommandArguments(Stream & str,uint32_t opt_set_mask)53614f1b3e8SDimitry Andric void CommandObject::GetFormattedCommandArguments(Stream &str,
53714f1b3e8SDimitry Andric uint32_t opt_set_mask) {
538f034231aSEd Maste int num_args = m_arguments.size();
53914f1b3e8SDimitry Andric for (int i = 0; i < num_args; ++i) {
540f034231aSEd Maste if (i > 0)
541f034231aSEd Maste str.Printf(" ");
542f034231aSEd Maste CommandArgumentEntry arg_entry =
54314f1b3e8SDimitry Andric opt_set_mask == LLDB_OPT_SET_ALL
54414f1b3e8SDimitry Andric ? m_arguments[i]
545f034231aSEd Maste : OptSetFiltered(opt_set_mask, m_arguments[i]);
546f65dcba8SDimitry Andric // This argument is not associated with the current option set, so skip it.
547f65dcba8SDimitry Andric if (arg_entry.empty())
548f65dcba8SDimitry Andric continue;
549f034231aSEd Maste int num_alternatives = arg_entry.size();
550f034231aSEd Maste
55114f1b3e8SDimitry Andric if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) {
552f034231aSEd Maste const char *first_name = GetArgumentName(arg_entry[0].arg_type);
553f034231aSEd Maste const char *second_name = GetArgumentName(arg_entry[1].arg_type);
55414f1b3e8SDimitry Andric switch (arg_entry[0].arg_repetition) {
555f034231aSEd Maste case eArgRepeatPairPlain:
556f034231aSEd Maste str.Printf("<%s> <%s>", first_name, second_name);
557f034231aSEd Maste break;
558f034231aSEd Maste case eArgRepeatPairOptional:
559f034231aSEd Maste str.Printf("[<%s> <%s>]", first_name, second_name);
560f034231aSEd Maste break;
561f034231aSEd Maste case eArgRepeatPairPlus:
56214f1b3e8SDimitry Andric str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name,
56314f1b3e8SDimitry Andric first_name, second_name);
564f034231aSEd Maste break;
565f034231aSEd Maste case eArgRepeatPairStar:
56614f1b3e8SDimitry Andric str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name,
56714f1b3e8SDimitry Andric first_name, second_name);
568f034231aSEd Maste break;
569f034231aSEd Maste case eArgRepeatPairRange:
57014f1b3e8SDimitry Andric str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name,
57114f1b3e8SDimitry Andric first_name, second_name);
572f034231aSEd Maste break;
573f034231aSEd Maste case eArgRepeatPairRangeOptional:
57414f1b3e8SDimitry Andric str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name,
57514f1b3e8SDimitry Andric first_name, second_name);
576f034231aSEd Maste break;
57714f1b3e8SDimitry Andric // Explicitly test for all the rest of the cases, so if new types get
578f73363f1SDimitry Andric // added we will notice the missing case statement(s).
579f034231aSEd Maste case eArgRepeatPlain:
580f034231aSEd Maste case eArgRepeatOptional:
581f034231aSEd Maste case eArgRepeatPlus:
582f034231aSEd Maste case eArgRepeatStar:
583f034231aSEd Maste case eArgRepeatRange:
58414f1b3e8SDimitry Andric // These should not be reached, as they should fail the IsPairType test
58514f1b3e8SDimitry Andric // above.
586f034231aSEd Maste break;
587f034231aSEd Maste }
58814f1b3e8SDimitry Andric } else {
589f034231aSEd Maste StreamString names;
59014f1b3e8SDimitry Andric for (int j = 0; j < num_alternatives; ++j) {
591f034231aSEd Maste if (j > 0)
592f034231aSEd Maste names.Printf(" | ");
593f034231aSEd Maste names.Printf("%s", GetArgumentName(arg_entry[j].arg_type));
594f034231aSEd Maste }
59514f1b3e8SDimitry Andric
596cfca06d7SDimitry Andric std::string name_str = std::string(names.GetString());
59714f1b3e8SDimitry Andric switch (arg_entry[0].arg_repetition) {
598f034231aSEd Maste case eArgRepeatPlain:
59914f1b3e8SDimitry Andric str.Printf("<%s>", name_str.c_str());
600f034231aSEd Maste break;
601f034231aSEd Maste case eArgRepeatPlus:
60214f1b3e8SDimitry Andric str.Printf("<%s> [<%s> [...]]", name_str.c_str(), name_str.c_str());
603f034231aSEd Maste break;
604f034231aSEd Maste case eArgRepeatStar:
60514f1b3e8SDimitry Andric str.Printf("[<%s> [<%s> [...]]]", name_str.c_str(), name_str.c_str());
606f034231aSEd Maste break;
607f034231aSEd Maste case eArgRepeatOptional:
60814f1b3e8SDimitry Andric str.Printf("[<%s>]", name_str.c_str());
609f034231aSEd Maste break;
610f034231aSEd Maste case eArgRepeatRange:
61114f1b3e8SDimitry Andric str.Printf("<%s_1> .. <%s_n>", name_str.c_str(), name_str.c_str());
612f034231aSEd Maste break;
61314f1b3e8SDimitry Andric // Explicitly test for all the rest of the cases, so if new types get
614f73363f1SDimitry Andric // added we will notice the missing case statement(s).
615f034231aSEd Maste case eArgRepeatPairPlain:
616f034231aSEd Maste case eArgRepeatPairOptional:
617f034231aSEd Maste case eArgRepeatPairPlus:
618f034231aSEd Maste case eArgRepeatPairStar:
619f034231aSEd Maste case eArgRepeatPairRange:
620f034231aSEd Maste case eArgRepeatPairRangeOptional:
62114f1b3e8SDimitry Andric // These should not be hit, as they should pass the IsPairType test
622f73363f1SDimitry Andric // above, and control should have gone into the other branch of the if
623f73363f1SDimitry Andric // statement.
624f034231aSEd Maste break;
625f034231aSEd Maste }
626f034231aSEd Maste }
627f034231aSEd Maste }
628f034231aSEd Maste }
629f034231aSEd Maste
630f034231aSEd Maste CommandArgumentType
LookupArgumentName(llvm::StringRef arg_name)63114f1b3e8SDimitry Andric CommandObject::LookupArgumentName(llvm::StringRef arg_name) {
632f034231aSEd Maste CommandArgumentType return_type = eArgTypeLastArg;
633f034231aSEd Maste
63414f1b3e8SDimitry Andric arg_name = arg_name.ltrim('<').rtrim('>');
635f034231aSEd Maste
636f034231aSEd Maste for (int i = 0; i < eArgTypeLastArg; ++i)
6374b4fe385SDimitry Andric if (arg_name == g_argument_table[i].arg_name)
6384b4fe385SDimitry Andric return_type = g_argument_table[i].arg_type;
639f034231aSEd Maste
640f034231aSEd Maste return return_type;
641f034231aSEd Maste }
642f034231aSEd Maste
FormatLongHelpText(Stream & output_strm,llvm::StringRef long_help)64314f1b3e8SDimitry Andric void CommandObject::FormatLongHelpText(Stream &output_strm,
64414f1b3e8SDimitry Andric llvm::StringRef long_help) {
645027f1c96SDimitry Andric CommandInterpreter &interpreter = GetCommandInterpreter();
646cfca06d7SDimitry Andric std::stringstream lineStream{std::string(long_help)};
647027f1c96SDimitry Andric std::string line;
648027f1c96SDimitry Andric while (std::getline(lineStream, line)) {
649027f1c96SDimitry Andric if (line.empty()) {
650027f1c96SDimitry Andric output_strm << "\n";
651027f1c96SDimitry Andric continue;
652027f1c96SDimitry Andric }
653027f1c96SDimitry Andric size_t result = line.find_first_not_of(" \t");
654027f1c96SDimitry Andric if (result == std::string::npos) {
655027f1c96SDimitry Andric result = 0;
656027f1c96SDimitry Andric }
657027f1c96SDimitry Andric std::string whitespace_prefix = line.substr(0, result);
658027f1c96SDimitry Andric std::string remainder = line.substr(result);
659cfca06d7SDimitry Andric interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix,
660cfca06d7SDimitry Andric remainder);
661027f1c96SDimitry Andric }
662027f1c96SDimitry Andric }
663027f1c96SDimitry Andric
GenerateHelpText(CommandReturnObject & result)66414f1b3e8SDimitry Andric void CommandObject::GenerateHelpText(CommandReturnObject &result) {
665f034231aSEd Maste GenerateHelpText(result.GetOutputStream());
666f034231aSEd Maste
667f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
668f034231aSEd Maste }
669f034231aSEd Maste
GenerateHelpText(Stream & output_strm)67014f1b3e8SDimitry Andric void CommandObject::GenerateHelpText(Stream &output_strm) {
671f034231aSEd Maste CommandInterpreter &interpreter = GetCommandInterpreter();
672f034231aSEd Maste std::string help_text(GetHelp());
673cfca06d7SDimitry Andric if (WantsRawCommandString()) {
674f3fbd1c0SDimitry Andric help_text.append(" Expects 'raw' input (see 'help raw-input'.)");
675cfca06d7SDimitry Andric }
676cfca06d7SDimitry Andric interpreter.OutputFormattedHelpText(output_strm, "", help_text);
67714f1b3e8SDimitry Andric output_strm << "\nSyntax: " << GetSyntax() << "\n";
678f3fbd1c0SDimitry Andric Options *options = GetOptions();
67914f1b3e8SDimitry Andric if (options != nullptr) {
68014f1b3e8SDimitry Andric options->GenerateOptionUsage(
681145449b1SDimitry Andric output_strm, *this,
68214f1b3e8SDimitry Andric GetCommandInterpreter().GetDebugger().GetTerminalWidth());
683f3fbd1c0SDimitry Andric }
68414f1b3e8SDimitry Andric llvm::StringRef long_help = GetHelpLong();
68514f1b3e8SDimitry Andric if (!long_help.empty()) {
686027f1c96SDimitry Andric FormatLongHelpText(output_strm, long_help);
687f3fbd1c0SDimitry Andric }
68814f1b3e8SDimitry Andric if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) {
68914f1b3e8SDimitry Andric if (WantsRawCommandString() && !WantsCompletion()) {
69014f1b3e8SDimitry Andric // Emit the message about using ' -- ' between the end of the command
691f73363f1SDimitry Andric // options and the raw input conditionally, i.e., only if the command
692f73363f1SDimitry Andric // object does not want completion.
693f3fbd1c0SDimitry Andric interpreter.OutputFormattedHelpText(
694f3fbd1c0SDimitry Andric output_strm, "", "",
69514f1b3e8SDimitry Andric "\nImportant Note: Because this command takes 'raw' input, if you "
69614f1b3e8SDimitry Andric "use any command options"
69714f1b3e8SDimitry Andric " you must use ' -- ' between the end of the command options and the "
69814f1b3e8SDimitry Andric "beginning of the raw input.",
699f3fbd1c0SDimitry Andric 1);
70014f1b3e8SDimitry Andric } else if (GetNumArgumentEntries() > 0) {
70114f1b3e8SDimitry Andric // Also emit a warning about using "--" in case you are using a command
70214f1b3e8SDimitry Andric // that takes options and arguments.
703f3fbd1c0SDimitry Andric interpreter.OutputFormattedHelpText(
70414f1b3e8SDimitry Andric output_strm, "", "",
70514f1b3e8SDimitry Andric "\nThis command takes options and free-form arguments. If your "
70614f1b3e8SDimitry Andric "arguments resemble"
70714f1b3e8SDimitry Andric " option specifiers (i.e., they start with a - or --), you must use "
70814f1b3e8SDimitry Andric "' -- ' between"
709f3fbd1c0SDimitry Andric " the end of the command options and the beginning of the arguments.",
710f3fbd1c0SDimitry Andric 1);
711f034231aSEd Maste }
712f034231aSEd Maste }
713f034231aSEd Maste }
714f034231aSEd Maste
AddIDsArgumentData(CommandObject::IDType type)715ac9a064cSDimitry Andric void CommandObject::AddIDsArgumentData(CommandObject::IDType type) {
716ac9a064cSDimitry Andric CommandArgumentEntry arg;
717f034231aSEd Maste CommandArgumentData id_arg;
718f034231aSEd Maste CommandArgumentData id_range_arg;
719f034231aSEd Maste
72014f1b3e8SDimitry Andric // Create the first variant for the first (and only) argument for this
72114f1b3e8SDimitry Andric // command.
722ac9a064cSDimitry Andric switch (type) {
723ac9a064cSDimitry Andric case eBreakpointArgs:
724ac9a064cSDimitry Andric id_arg.arg_type = eArgTypeBreakpointID;
725ac9a064cSDimitry Andric id_range_arg.arg_type = eArgTypeBreakpointIDRange;
726ac9a064cSDimitry Andric break;
727ac9a064cSDimitry Andric case eWatchpointArgs:
728ac9a064cSDimitry Andric id_arg.arg_type = eArgTypeWatchpointID;
729ac9a064cSDimitry Andric id_range_arg.arg_type = eArgTypeWatchpointIDRange;
730ac9a064cSDimitry Andric break;
731ac9a064cSDimitry Andric }
732f034231aSEd Maste id_arg.arg_repetition = eArgRepeatOptional;
733f034231aSEd Maste id_range_arg.arg_repetition = eArgRepeatOptional;
734f034231aSEd Maste
73514f1b3e8SDimitry Andric // The first (and only) argument for this command could be either an id or an
736f73363f1SDimitry Andric // id_range. Push both variants into the entry for the first argument for
737f73363f1SDimitry Andric // this command.
738f034231aSEd Maste arg.push_back(id_arg);
739f034231aSEd Maste arg.push_back(id_range_arg);
740ac9a064cSDimitry Andric m_arguments.push_back(arg);
741f034231aSEd Maste }
742f034231aSEd Maste
GetArgumentTypeAsCString(const lldb::CommandArgumentType arg_type)74314f1b3e8SDimitry Andric const char *CommandObject::GetArgumentTypeAsCString(
74414f1b3e8SDimitry Andric const lldb::CommandArgumentType arg_type) {
74514f1b3e8SDimitry Andric assert(arg_type < eArgTypeLastArg &&
74614f1b3e8SDimitry Andric "Invalid argument type passed to GetArgumentTypeAsCString");
7474b4fe385SDimitry Andric return g_argument_table[arg_type].arg_name;
748f034231aSEd Maste }
749f034231aSEd Maste
GetArgumentDescriptionAsCString(const lldb::CommandArgumentType arg_type)75014f1b3e8SDimitry Andric const char *CommandObject::GetArgumentDescriptionAsCString(
75114f1b3e8SDimitry Andric const lldb::CommandArgumentType arg_type) {
75214f1b3e8SDimitry Andric assert(arg_type < eArgTypeLastArg &&
75314f1b3e8SDimitry Andric "Invalid argument type passed to GetArgumentDescriptionAsCString");
7544b4fe385SDimitry Andric return g_argument_table[arg_type].help_text;
755f034231aSEd Maste }
756f034231aSEd Maste
GetDummyTarget()757ead24645SDimitry Andric Target &CommandObject::GetDummyTarget() {
758b60736ecSDimitry Andric return m_interpreter.GetDebugger().GetDummyTarget();
759205afe67SEd Maste }
760205afe67SEd Maste
GetSelectedOrDummyTarget(bool prefer_dummy)761ead24645SDimitry Andric Target &CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) {
762b60736ecSDimitry Andric return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy);
763ead24645SDimitry Andric }
764ead24645SDimitry Andric
GetSelectedTarget()765ead24645SDimitry Andric Target &CommandObject::GetSelectedTarget() {
766ead24645SDimitry Andric assert(m_flags.AnySet(eCommandRequiresTarget | eCommandProcessMustBePaused |
767ead24645SDimitry Andric eCommandProcessMustBeLaunched | eCommandRequiresFrame |
768ead24645SDimitry Andric eCommandRequiresThread | eCommandRequiresProcess |
769ead24645SDimitry Andric eCommandRequiresRegContext) &&
770ead24645SDimitry Andric "GetSelectedTarget called from object that may have no target");
771ead24645SDimitry Andric return *m_interpreter.GetDebugger().GetSelectedTarget();
772205afe67SEd Maste }
773205afe67SEd Maste
GetDefaultThread()77414f1b3e8SDimitry Andric Thread *CommandObject::GetDefaultThread() {
775f3fbd1c0SDimitry Andric Thread *thread_to_use = m_exe_ctx.GetThreadPtr();
776f3fbd1c0SDimitry Andric if (thread_to_use)
777f3fbd1c0SDimitry Andric return thread_to_use;
778f3fbd1c0SDimitry Andric
779f3fbd1c0SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
78014f1b3e8SDimitry Andric if (!process) {
781f3fbd1c0SDimitry Andric Target *target = m_exe_ctx.GetTargetPtr();
78214f1b3e8SDimitry Andric if (!target) {
783f3fbd1c0SDimitry Andric target = m_interpreter.GetDebugger().GetSelectedTarget().get();
784f3fbd1c0SDimitry Andric }
785f3fbd1c0SDimitry Andric if (target)
786f3fbd1c0SDimitry Andric process = target->GetProcessSP().get();
787f3fbd1c0SDimitry Andric }
788f3fbd1c0SDimitry Andric
789f3fbd1c0SDimitry Andric if (process)
790f3fbd1c0SDimitry Andric return process->GetThreadList().GetSelectedThread().get();
791f3fbd1c0SDimitry Andric else
792f3fbd1c0SDimitry Andric return nullptr;
793f3fbd1c0SDimitry Andric }
794f3fbd1c0SDimitry Andric
Execute(const char * args_string,CommandReturnObject & result)795b1c73532SDimitry Andric void CommandObjectParsed::Execute(const char *args_string,
79614f1b3e8SDimitry Andric CommandReturnObject &result) {
797f034231aSEd Maste bool handled = false;
798f034231aSEd Maste Args cmd_args(args_string);
79914f1b3e8SDimitry Andric if (HasOverrideCallback()) {
800f034231aSEd Maste Args full_args(GetCommandName());
801f034231aSEd Maste full_args.AppendArguments(cmd_args);
80214f1b3e8SDimitry Andric handled =
80314f1b3e8SDimitry Andric InvokeOverrideCallback(full_args.GetConstArgumentVector(), result);
804f034231aSEd Maste }
80514f1b3e8SDimitry Andric if (!handled) {
80614f1b3e8SDimitry Andric for (auto entry : llvm::enumerate(cmd_args.entries())) {
8077fa27ce4SDimitry Andric const Args::ArgEntry &value = entry.value();
8087fa27ce4SDimitry Andric if (!value.ref().empty() && value.GetQuoteChar() == '`') {
8097fa27ce4SDimitry Andric // We have to put the backtick back in place for PreprocessCommand.
8107fa27ce4SDimitry Andric std::string opt_string = value.c_str();
8117fa27ce4SDimitry Andric Status error;
8127fa27ce4SDimitry Andric error = m_interpreter.PreprocessToken(opt_string);
8137fa27ce4SDimitry Andric if (error.Success())
8147fa27ce4SDimitry Andric cmd_args.ReplaceArgumentAtIndex(entry.index(), opt_string);
81514f1b3e8SDimitry Andric }
816f034231aSEd Maste }
817f034231aSEd Maste
81814f1b3e8SDimitry Andric if (CheckRequirements(result)) {
81914f1b3e8SDimitry Andric if (ParseOptions(cmd_args, result)) {
82014f1b3e8SDimitry Andric // Call the command-specific version of 'Execute', passing it the
82114f1b3e8SDimitry Andric // already processed arguments.
822145449b1SDimitry Andric if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) {
823145449b1SDimitry Andric result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.",
824145449b1SDimitry Andric GetCommandName());
825e3b55780SDimitry Andric Cleanup();
826b1c73532SDimitry Andric return;
827145449b1SDimitry Andric }
828ac9a064cSDimitry Andric m_interpreter.IncreaseCommandUsage(*this);
829b1c73532SDimitry Andric DoExecute(cmd_args, result);
830f034231aSEd Maste }
831f034231aSEd Maste }
832f034231aSEd Maste
833f034231aSEd Maste Cleanup();
834f034231aSEd Maste }
835f034231aSEd Maste }
836f034231aSEd Maste
Execute(const char * args_string,CommandReturnObject & result)837b1c73532SDimitry Andric void CommandObjectRaw::Execute(const char *args_string,
83814f1b3e8SDimitry Andric CommandReturnObject &result) {
839f034231aSEd Maste bool handled = false;
84014f1b3e8SDimitry Andric if (HasOverrideCallback()) {
841f034231aSEd Maste std::string full_command(GetCommandName());
842f034231aSEd Maste full_command += ' ';
843f034231aSEd Maste full_command += args_string;
8440cac4ca3SEd Maste const char *argv[2] = {nullptr, nullptr};
845f034231aSEd Maste argv[0] = full_command.c_str();
8460cac4ca3SEd Maste handled = InvokeOverrideCallback(argv, result);
847f034231aSEd Maste }
84814f1b3e8SDimitry Andric if (!handled) {
849f034231aSEd Maste if (CheckRequirements(result))
850b1c73532SDimitry Andric DoExecute(args_string, result);
851f034231aSEd Maste
852f034231aSEd Maste Cleanup();
853f034231aSEd Maste }
854f034231aSEd Maste }
855