xref: /src/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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