xref: /freebsd/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- CommandObject.cpp -------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Interpreter/CommandObject.h"
10 
11 #include <map>
12 #include <sstream>
13 #include <string>
14 
15 #include <cctype>
16 #include <cstdlib>
17 
18 #include "lldb/Core/Address.h"
19 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
20 #include "lldb/Interpreter/Options.h"
21 #include "lldb/Utility/ArchSpec.h"
22 #include "llvm/ADT/ScopeExit.h"
23 
24 // These are for the Sourcename completers.
25 // FIXME: Make a separate file for the completers.
26 #include "lldb/DataFormatters/FormatManager.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Utility/FileSpec.h"
30 #include "lldb/Utility/FileSpecList.h"
31 
32 #include "lldb/Target/Language.h"
33 
34 #include "lldb/Interpreter/CommandInterpreter.h"
35 #include "lldb/Interpreter/CommandReturnObject.h"
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 
40 // CommandObject
41 
CommandObject(CommandInterpreter & interpreter,llvm::StringRef name,llvm::StringRef help,llvm::StringRef syntax,uint32_t flags)42 CommandObject::CommandObject(CommandInterpreter &interpreter,
43                              llvm::StringRef name, llvm::StringRef help,
44                              llvm::StringRef syntax, uint32_t flags)
45     : m_interpreter(interpreter), m_cmd_name(std::string(name)),
46       m_flags(flags), m_deprecated_command_override_callback(nullptr),
47       m_command_override_callback(nullptr), m_command_override_baton(nullptr) {
48   m_cmd_help_short = std::string(help);
49   m_cmd_syntax = std::string(syntax);
50 }
51 
GetDebugger()52 Debugger &CommandObject::GetDebugger() { return m_interpreter.GetDebugger(); }
53 
GetHelp()54 llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; }
55 
GetHelpLong()56 llvm::StringRef CommandObject::GetHelpLong() { return m_cmd_help_long; }
57 
GetSyntax()58 llvm::StringRef CommandObject::GetSyntax() {
59   if (!m_cmd_syntax.empty())
60     return m_cmd_syntax;
61 
62   StreamString syntax_str;
63   syntax_str.PutCString(GetCommandName());
64 
65   if (!IsDashDashCommand() && GetOptions() != nullptr)
66     syntax_str.PutCString(" <cmd-options>");
67 
68   if (!m_arguments.empty()) {
69     syntax_str.PutCString(" ");
70 
71     if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() &&
72         GetOptions()->NumCommandOptions())
73       syntax_str.PutCString("-- ");
74     GetFormattedCommandArguments(syntax_str);
75   }
76   m_cmd_syntax = std::string(syntax_str.GetString());
77 
78   return m_cmd_syntax;
79 }
80 
GetCommandName() const81 llvm::StringRef CommandObject::GetCommandName() const { return m_cmd_name; }
82 
SetCommandName(llvm::StringRef name)83 void CommandObject::SetCommandName(llvm::StringRef name) {
84   m_cmd_name = std::string(name);
85 }
86 
SetHelp(llvm::StringRef str)87 void CommandObject::SetHelp(llvm::StringRef str) {
88   m_cmd_help_short = std::string(str);
89 }
90 
SetHelpLong(llvm::StringRef str)91 void CommandObject::SetHelpLong(llvm::StringRef str) {
92   m_cmd_help_long = std::string(str);
93 }
94 
SetSyntax(llvm::StringRef str)95 void CommandObject::SetSyntax(llvm::StringRef str) {
96   m_cmd_syntax = std::string(str);
97 }
98 
GetOptions()99 Options *CommandObject::GetOptions() {
100   // By default commands don't have options unless this virtual function is
101   // overridden by base classes.
102   return nullptr;
103 }
104 
ParseOptions(Args & args,CommandReturnObject & result)105 bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
106   // See if the subclass has options?
107   Options *options = GetOptions();
108   if (options != nullptr) {
109     Status error;
110 
111     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
112     options->NotifyOptionParsingStarting(&exe_ctx);
113 
114     const bool require_validation = true;
115     llvm::Expected<Args> args_or = options->Parse(
116         args, &exe_ctx, GetCommandInterpreter().GetPlatform(true),
117         require_validation);
118 
119     if (args_or) {
120       args = std::move(*args_or);
121       error = options->NotifyOptionParsingFinished(&exe_ctx);
122     } else {
123       error = Status::FromError(args_or.takeError());
124     }
125 
126     if (error.Fail()) {
127       result.SetError(error.takeError());
128       result.SetStatus(eReturnStatusFailed);
129       return false;
130     }
131 
132     if (llvm::Error error = options->VerifyOptions()) {
133       result.SetError(std::move(error));
134       result.SetStatus(eReturnStatusFailed);
135       return false;
136     }
137 
138     result.SetStatus(eReturnStatusSuccessFinishNoResult);
139     return true;
140   }
141   return true;
142 }
143 
CheckRequirements(CommandReturnObject & result)144 bool CommandObject::CheckRequirements(CommandReturnObject &result) {
145   // Nothing should be stored in m_exe_ctx between running commands as
146   // m_exe_ctx has shared pointers to the target, process, thread and frame and
147   // we don't want any CommandObject instances to keep any of these objects
148   // around longer than for a single command. Every command should call
149   // CommandObject::Cleanup() after it has completed.
150   assert(!m_exe_ctx.GetTargetPtr());
151   assert(!m_exe_ctx.GetProcessPtr());
152   assert(!m_exe_ctx.GetThreadPtr());
153   assert(!m_exe_ctx.GetFramePtr());
154 
155   // Lock down the interpreter's execution context prior to running the command
156   // so we guarantee the selected target, process, thread and frame can't go
157   // away during the execution
158   m_exe_ctx = m_interpreter.GetExecutionContext();
159 
160   const uint32_t flags = GetFlags().Get();
161   if (flags & (eCommandRequiresTarget | eCommandRequiresProcess |
162                eCommandRequiresThread | eCommandRequiresFrame |
163                eCommandTryTargetAPILock)) {
164 
165     if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) {
166       result.AppendError(GetInvalidTargetDescription());
167       return false;
168     }
169 
170     if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) {
171       if (!m_exe_ctx.HasTargetScope())
172         result.AppendError(GetInvalidTargetDescription());
173       else
174         result.AppendError(GetInvalidProcessDescription());
175       return false;
176     }
177 
178     if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) {
179       if (!m_exe_ctx.HasTargetScope())
180         result.AppendError(GetInvalidTargetDescription());
181       else if (!m_exe_ctx.HasProcessScope())
182         result.AppendError(GetInvalidProcessDescription());
183       else
184         result.AppendError(GetInvalidThreadDescription());
185       return false;
186     }
187 
188     if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) {
189       if (!m_exe_ctx.HasTargetScope())
190         result.AppendError(GetInvalidTargetDescription());
191       else if (!m_exe_ctx.HasProcessScope())
192         result.AppendError(GetInvalidProcessDescription());
193       else if (!m_exe_ctx.HasThreadScope())
194         result.AppendError(GetInvalidThreadDescription());
195       else
196         result.AppendError(GetInvalidFrameDescription());
197       return false;
198     }
199 
200     if ((flags & eCommandRequiresRegContext) &&
201         (m_exe_ctx.GetRegisterContext() == nullptr)) {
202       result.AppendError(GetInvalidRegContextDescription());
203       return false;
204     }
205 
206     if (flags & eCommandTryTargetAPILock) {
207       Target *target = m_exe_ctx.GetTargetPtr();
208       if (target)
209         m_api_locker =
210             std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());
211     }
212   }
213 
214   if (GetFlags().AnySet(eCommandProcessMustBeLaunched |
215                         eCommandProcessMustBePaused)) {
216     Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
217     if (process == nullptr) {
218       // A process that is not running is considered paused.
219       if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
220         result.AppendError("Process must exist.");
221         return false;
222       }
223     } else {
224       StateType state = process->GetState();
225       switch (state) {
226       case eStateInvalid:
227       case eStateSuspended:
228       case eStateCrashed:
229       case eStateStopped:
230         break;
231 
232       case eStateConnected:
233       case eStateAttaching:
234       case eStateLaunching:
235       case eStateDetached:
236       case eStateExited:
237       case eStateUnloaded:
238         if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
239           result.AppendError("Process must be launched.");
240           return false;
241         }
242         break;
243 
244       case eStateRunning:
245       case eStateStepping:
246         if (GetFlags().Test(eCommandProcessMustBePaused)) {
247           result.AppendError("Process is running.  Use 'process interrupt' to "
248                              "pause execution.");
249           return false;
250         }
251       }
252     }
253   }
254 
255   if (GetFlags().Test(eCommandProcessMustBeTraced)) {
256     Target *target = m_exe_ctx.GetTargetPtr();
257     if (target && !target->GetTrace()) {
258       result.AppendError("Process is not being traced.");
259       return false;
260     }
261   }
262 
263   return true;
264 }
265 
Cleanup()266 void CommandObject::Cleanup() {
267   m_exe_ctx.Clear();
268   if (m_api_locker.owns_lock())
269     m_api_locker.unlock();
270 }
271 
HandleCompletion(CompletionRequest & request)272 void CommandObject::HandleCompletion(CompletionRequest &request) {
273 
274   m_exe_ctx = m_interpreter.GetExecutionContext();
275   auto reset_ctx = llvm::make_scope_exit([this]() { Cleanup(); });
276 
277   // Default implementation of WantsCompletion() is !WantsRawCommandString().
278   // Subclasses who want raw command string but desire, for example, argument
279   // completion should override WantsCompletion() to return true, instead.
280   if (WantsRawCommandString() && !WantsCompletion()) {
281     // FIXME: Abstract telling the completion to insert the completion
282     // character.
283     return;
284   } else {
285     // Can we do anything generic with the options?
286     Options *cur_options = GetOptions();
287     OptionElementVector opt_element_vector;
288 
289     if (cur_options != nullptr) {
290       opt_element_vector = cur_options->ParseForCompletion(
291           request.GetParsedLine(), request.GetCursorIndex());
292 
293       bool handled_by_options = cur_options->HandleOptionCompletion(
294           request, opt_element_vector, GetCommandInterpreter());
295       if (handled_by_options)
296         return;
297     }
298 
299     // If we got here, the last word is not an option or an option argument.
300     HandleArgumentCompletion(request, opt_element_vector);
301   }
302 }
303 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)304 void CommandObject::HandleArgumentCompletion(
305     CompletionRequest &request, OptionElementVector &opt_element_vector) {
306   size_t num_arg_entries = GetNumArgumentEntries();
307   if (num_arg_entries != 1)
308     return;
309 
310   CommandArgumentEntry *entry_ptr = GetArgumentEntryAtIndex(0);
311   if (!entry_ptr) {
312     assert(entry_ptr && "We said there was one entry, but there wasn't.");
313     return; // Not worth crashing if asserts are off...
314   }
315 
316   CommandArgumentEntry &entry = *entry_ptr;
317   // For now, we only handle the simple case of one homogenous argument type.
318   if (entry.size() != 1)
319     return;
320 
321   // Look up the completion type, and if it has one, invoke it:
322   const CommandObject::ArgumentTableEntry *arg_entry =
323       FindArgumentDataByType(entry[0].arg_type);
324   const ArgumentRepetitionType repeat = entry[0].arg_repetition;
325 
326   if (arg_entry == nullptr || arg_entry->completion_type == lldb::eNoCompletion)
327     return;
328 
329   // FIXME: This should be handled higher in the Command Parser.
330   // Check the case where this command only takes one argument, and don't do
331   // the completion if we aren't on the first entry:
332   if (repeat == eArgRepeatPlain && request.GetCursorIndex() != 0)
333     return;
334 
335   lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
336       GetCommandInterpreter(), arg_entry->completion_type, request, nullptr);
337 
338 }
339 
HelpTextContainsWord(llvm::StringRef search_word,bool search_short_help,bool search_long_help,bool search_syntax,bool search_options)340 bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
341                                          bool search_short_help,
342                                          bool search_long_help,
343                                          bool search_syntax,
344                                          bool search_options) {
345   bool found_word = false;
346 
347   llvm::StringRef short_help = GetHelp();
348   llvm::StringRef long_help = GetHelpLong();
349   llvm::StringRef syntax_help = GetSyntax();
350 
351   if (search_short_help && short_help.contains_insensitive(search_word))
352     found_word = true;
353   else if (search_long_help && long_help.contains_insensitive(search_word))
354     found_word = true;
355   else if (search_syntax && syntax_help.contains_insensitive(search_word))
356     found_word = true;
357 
358   if (!found_word && search_options && GetOptions() != nullptr) {
359     StreamString usage_help;
360     GetOptions()->GenerateOptionUsage(
361         usage_help, *this,
362         GetCommandInterpreter().GetDebugger().GetTerminalWidth());
363     if (!usage_help.Empty()) {
364       llvm::StringRef usage_text = usage_help.GetString();
365       if (usage_text.contains_insensitive(search_word))
366         found_word = true;
367     }
368   }
369 
370   return found_word;
371 }
372 
ParseOptionsAndNotify(Args & args,CommandReturnObject & result,OptionGroupOptions & group_options,ExecutionContext & exe_ctx)373 bool CommandObject::ParseOptionsAndNotify(Args &args,
374                                           CommandReturnObject &result,
375                                           OptionGroupOptions &group_options,
376                                           ExecutionContext &exe_ctx) {
377   if (!ParseOptions(args, result))
378     return false;
379 
380   Status error(group_options.NotifyOptionParsingFinished(&exe_ctx));
381   if (error.Fail()) {
382     result.AppendError(error.AsCString());
383     return false;
384   }
385   return true;
386 }
387 
AddSimpleArgumentList(CommandArgumentType arg_type,ArgumentRepetitionType repetition_type)388 void CommandObject::AddSimpleArgumentList(
389     CommandArgumentType arg_type, ArgumentRepetitionType repetition_type) {
390 
391   CommandArgumentEntry arg_entry;
392   CommandArgumentData simple_arg;
393 
394   // Define the first (and only) variant of this arg.
395   simple_arg.arg_type = arg_type;
396   simple_arg.arg_repetition = repetition_type;
397 
398   // There is only one variant this argument could be; put it into the argument
399   // entry.
400   arg_entry.push_back(simple_arg);
401 
402   // Push the data for the first argument into the m_arguments vector.
403   m_arguments.push_back(arg_entry);
404 }
405 
GetNumArgumentEntries()406 int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); }
407 
408 CommandObject::CommandArgumentEntry *
GetArgumentEntryAtIndex(int idx)409 CommandObject::GetArgumentEntryAtIndex(int idx) {
410   if (static_cast<size_t>(idx) < m_arguments.size())
411     return &(m_arguments[idx]);
412 
413   return nullptr;
414 }
415 
416 const CommandObject::ArgumentTableEntry *
FindArgumentDataByType(CommandArgumentType arg_type)417 CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) {
418   for (int i = 0; i < eArgTypeLastArg; ++i)
419     if (g_argument_table[i].arg_type == arg_type)
420       return &(g_argument_table[i]);
421 
422   return nullptr;
423 }
424 
GetArgumentHelp(Stream & str,CommandArgumentType arg_type,CommandInterpreter & interpreter)425 void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type,
426                                     CommandInterpreter &interpreter) {
427   const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);
428 
429   // The table is *supposed* to be kept in arg_type order, but someone *could*
430   // have messed it up...
431 
432   if (entry->arg_type != arg_type)
433     entry = CommandObject::FindArgumentDataByType(arg_type);
434 
435   if (!entry)
436     return;
437 
438   StreamString name_str;
439   name_str.Printf("<%s>", entry->arg_name);
440 
441   if (entry->help_function) {
442     llvm::StringRef help_text = entry->help_function();
443     if (!entry->help_function.self_formatting) {
444       interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
445                                           help_text, name_str.GetSize());
446     } else {
447       interpreter.OutputHelpText(str, name_str.GetString(), "--", help_text,
448                                  name_str.GetSize());
449     }
450   } else {
451     interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
452                                         entry->help_text, name_str.GetSize());
453 
454     // Print enum values and their description if any.
455     OptionEnumValues enum_values = g_argument_table[arg_type].enum_values;
456     if (!enum_values.empty()) {
457       str.EOL();
458       size_t longest = 0;
459       for (const OptionEnumValueElement &element : enum_values)
460         longest =
461             std::max(longest, llvm::StringRef(element.string_value).size());
462       str.IndentMore(5);
463       for (const OptionEnumValueElement &element : enum_values) {
464         str.Indent();
465         interpreter.OutputHelpText(str, element.string_value, ":",
466                                    element.usage, longest);
467       }
468       str.IndentLess(5);
469       str.EOL();
470     }
471   }
472 }
473 
GetArgumentName(CommandArgumentType arg_type)474 const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) {
475   const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);
476 
477   // The table is *supposed* to be kept in arg_type order, but someone *could*
478   // have messed it up...
479 
480   if (entry->arg_type != arg_type)
481     entry = CommandObject::FindArgumentDataByType(arg_type);
482 
483   if (entry)
484     return entry->arg_name;
485 
486   return nullptr;
487 }
488 
IsPairType(ArgumentRepetitionType arg_repeat_type)489 bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) {
490   return (arg_repeat_type == eArgRepeatPairPlain) ||
491          (arg_repeat_type == eArgRepeatPairOptional) ||
492          (arg_repeat_type == eArgRepeatPairPlus) ||
493          (arg_repeat_type == eArgRepeatPairStar) ||
494          (arg_repeat_type == eArgRepeatPairRange) ||
495          (arg_repeat_type == eArgRepeatPairRangeOptional);
496 }
497 
498 std::optional<ArgumentRepetitionType>
ArgRepetitionFromString(llvm::StringRef string)499 CommandObject::ArgRepetitionFromString(llvm::StringRef string) {
500   return llvm::StringSwitch<ArgumentRepetitionType>(string)
501   .Case("plain", eArgRepeatPlain)
502   .Case("optional", eArgRepeatOptional)
503   .Case("plus", eArgRepeatPlus)
504   .Case("star", eArgRepeatStar)
505   .Case("range", eArgRepeatRange)
506   .Case("pair-plain", eArgRepeatPairPlain)
507   .Case("pair-optional", eArgRepeatPairOptional)
508   .Case("pair-plus", eArgRepeatPairPlus)
509   .Case("pair-star", eArgRepeatPairStar)
510   .Case("pair-range", eArgRepeatPairRange)
511   .Case("pair-range-optional", eArgRepeatPairRangeOptional)
512   .Default({});
513 }
514 
515 static CommandObject::CommandArgumentEntry
OptSetFiltered(uint32_t opt_set_mask,CommandObject::CommandArgumentEntry & cmd_arg_entry)516 OptSetFiltered(uint32_t opt_set_mask,
517                CommandObject::CommandArgumentEntry &cmd_arg_entry) {
518   CommandObject::CommandArgumentEntry ret_val;
519   for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
520     if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
521       ret_val.push_back(cmd_arg_entry[i]);
522   return ret_val;
523 }
524 
525 // Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means
526 // take all the argument data into account.  On rare cases where some argument
527 // sticks with certain option sets, this function returns the option set
528 // filtered args.
GetFormattedCommandArguments(Stream & str,uint32_t opt_set_mask)529 void CommandObject::GetFormattedCommandArguments(Stream &str,
530                                                  uint32_t opt_set_mask) {
531   int num_args = m_arguments.size();
532   for (int i = 0; i < num_args; ++i) {
533     if (i > 0)
534       str.Printf(" ");
535     CommandArgumentEntry arg_entry =
536         opt_set_mask == LLDB_OPT_SET_ALL
537             ? m_arguments[i]
538             : OptSetFiltered(opt_set_mask, m_arguments[i]);
539     // This argument is not associated with the current option set, so skip it.
540     if (arg_entry.empty())
541       continue;
542     int num_alternatives = arg_entry.size();
543 
544     if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) {
545       const char *first_name = GetArgumentName(arg_entry[0].arg_type);
546       const char *second_name = GetArgumentName(arg_entry[1].arg_type);
547       switch (arg_entry[0].arg_repetition) {
548       case eArgRepeatPairPlain:
549         str.Printf("<%s> <%s>", first_name, second_name);
550         break;
551       case eArgRepeatPairOptional:
552         str.Printf("[<%s> <%s>]", first_name, second_name);
553         break;
554       case eArgRepeatPairPlus:
555         str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name,
556                    first_name, second_name);
557         break;
558       case eArgRepeatPairStar:
559         str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name,
560                    first_name, second_name);
561         break;
562       case eArgRepeatPairRange:
563         str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name,
564                    first_name, second_name);
565         break;
566       case eArgRepeatPairRangeOptional:
567         str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name,
568                    first_name, second_name);
569         break;
570       // Explicitly test for all the rest of the cases, so if new types get
571       // added we will notice the missing case statement(s).
572       case eArgRepeatPlain:
573       case eArgRepeatOptional:
574       case eArgRepeatPlus:
575       case eArgRepeatStar:
576       case eArgRepeatRange:
577         // These should not be reached, as they should fail the IsPairType test
578         // above.
579         break;
580       }
581     } else {
582       StreamString names;
583       for (int j = 0; j < num_alternatives; ++j) {
584         if (j > 0)
585           names.Printf(" | ");
586         names.Printf("%s", GetArgumentName(arg_entry[j].arg_type));
587       }
588 
589       std::string name_str = std::string(names.GetString());
590       switch (arg_entry[0].arg_repetition) {
591       case eArgRepeatPlain:
592         str.Printf("<%s>", name_str.c_str());
593         break;
594       case eArgRepeatPlus:
595         str.Printf("<%s> [<%s> [...]]", name_str.c_str(), name_str.c_str());
596         break;
597       case eArgRepeatStar:
598         str.Printf("[<%s> [<%s> [...]]]", name_str.c_str(), name_str.c_str());
599         break;
600       case eArgRepeatOptional:
601         str.Printf("[<%s>]", name_str.c_str());
602         break;
603       case eArgRepeatRange:
604         str.Printf("<%s_1> .. <%s_n>", name_str.c_str(), name_str.c_str());
605         break;
606       // Explicitly test for all the rest of the cases, so if new types get
607       // added we will notice the missing case statement(s).
608       case eArgRepeatPairPlain:
609       case eArgRepeatPairOptional:
610       case eArgRepeatPairPlus:
611       case eArgRepeatPairStar:
612       case eArgRepeatPairRange:
613       case eArgRepeatPairRangeOptional:
614         // These should not be hit, as they should pass the IsPairType test
615         // above, and control should have gone into the other branch of the if
616         // statement.
617         break;
618       }
619     }
620   }
621 }
622 
623 CommandArgumentType
LookupArgumentName(llvm::StringRef arg_name)624 CommandObject::LookupArgumentName(llvm::StringRef arg_name) {
625   CommandArgumentType return_type = eArgTypeLastArg;
626 
627   arg_name = arg_name.ltrim('<').rtrim('>');
628 
629   for (int i = 0; i < eArgTypeLastArg; ++i)
630     if (arg_name == g_argument_table[i].arg_name)
631       return_type = g_argument_table[i].arg_type;
632 
633   return return_type;
634 }
635 
FormatLongHelpText(Stream & output_strm,llvm::StringRef long_help)636 void CommandObject::FormatLongHelpText(Stream &output_strm,
637                                        llvm::StringRef long_help) {
638   CommandInterpreter &interpreter = GetCommandInterpreter();
639   std::stringstream lineStream{std::string(long_help)};
640   std::string line;
641   while (std::getline(lineStream, line)) {
642     if (line.empty()) {
643       output_strm << "\n";
644       continue;
645     }
646     size_t result = line.find_first_not_of(" \t");
647     if (result == std::string::npos) {
648       result = 0;
649     }
650     std::string whitespace_prefix = line.substr(0, result);
651     std::string remainder = line.substr(result);
652     interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix,
653                                         remainder);
654   }
655 }
656 
GenerateHelpText(CommandReturnObject & result)657 void CommandObject::GenerateHelpText(CommandReturnObject &result) {
658   GenerateHelpText(result.GetOutputStream());
659 
660   result.SetStatus(eReturnStatusSuccessFinishNoResult);
661 }
662 
GenerateHelpText(Stream & output_strm)663 void CommandObject::GenerateHelpText(Stream &output_strm) {
664   CommandInterpreter &interpreter = GetCommandInterpreter();
665   std::string help_text(GetHelp());
666   if (WantsRawCommandString()) {
667     help_text.append("  Expects 'raw' input (see 'help raw-input'.)");
668   }
669   interpreter.OutputFormattedHelpText(output_strm, "", help_text);
670   output_strm << "\nSyntax: " << GetSyntax() << "\n";
671   Options *options = GetOptions();
672   if (options != nullptr) {
673     options->GenerateOptionUsage(
674         output_strm, *this,
675         GetCommandInterpreter().GetDebugger().GetTerminalWidth());
676   }
677   llvm::StringRef long_help = GetHelpLong();
678   if (!long_help.empty()) {
679     FormatLongHelpText(output_strm, long_help);
680   }
681   if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) {
682     if (WantsRawCommandString() && !WantsCompletion()) {
683       // Emit the message about using ' -- ' between the end of the command
684       // options and the raw input conditionally, i.e., only if the command
685       // object does not want completion.
686       interpreter.OutputFormattedHelpText(
687           output_strm, "", "",
688           "\nImportant Note: Because this command takes 'raw' input, if you "
689           "use any command options"
690           " you must use ' -- ' between the end of the command options and the "
691           "beginning of the raw input.",
692           1);
693     } else if (GetNumArgumentEntries() > 0) {
694       // Also emit a warning about using "--" in case you are using a command
695       // that takes options and arguments.
696       interpreter.OutputFormattedHelpText(
697           output_strm, "", "",
698           "\nThis command takes options and free-form arguments.  If your "
699           "arguments resemble"
700           " option specifiers (i.e., they start with a - or --), you must use "
701           "' -- ' between"
702           " the end of the command options and the beginning of the arguments.",
703           1);
704     }
705   }
706 }
707 
AddIDsArgumentData(CommandObject::IDType type)708 void CommandObject::AddIDsArgumentData(CommandObject::IDType type) {
709   CommandArgumentEntry arg;
710   CommandArgumentData id_arg;
711   CommandArgumentData id_range_arg;
712 
713   // Create the first variant for the first (and only) argument for this
714   // command.
715   switch (type) {
716   case eBreakpointArgs:
717     id_arg.arg_type = eArgTypeBreakpointID;
718     id_range_arg.arg_type = eArgTypeBreakpointIDRange;
719     break;
720   case eWatchpointArgs:
721     id_arg.arg_type = eArgTypeWatchpointID;
722     id_range_arg.arg_type = eArgTypeWatchpointIDRange;
723     break;
724   }
725   id_arg.arg_repetition = eArgRepeatOptional;
726   id_range_arg.arg_repetition = eArgRepeatOptional;
727 
728   // The first (and only) argument for this command could be either an id or an
729   // id_range. Push both variants into the entry for the first argument for
730   // this command.
731   arg.push_back(id_arg);
732   arg.push_back(id_range_arg);
733   m_arguments.push_back(arg);
734 }
735 
GetArgumentTypeAsCString(const lldb::CommandArgumentType arg_type)736 const char *CommandObject::GetArgumentTypeAsCString(
737     const lldb::CommandArgumentType arg_type) {
738   assert(arg_type < eArgTypeLastArg &&
739          "Invalid argument type passed to GetArgumentTypeAsCString");
740   return g_argument_table[arg_type].arg_name;
741 }
742 
GetArgumentDescriptionAsCString(const lldb::CommandArgumentType arg_type)743 const char *CommandObject::GetArgumentDescriptionAsCString(
744     const lldb::CommandArgumentType arg_type) {
745   assert(arg_type < eArgTypeLastArg &&
746          "Invalid argument type passed to GetArgumentDescriptionAsCString");
747   return g_argument_table[arg_type].help_text;
748 }
749 
GetDummyTarget()750 Target &CommandObject::GetDummyTarget() {
751   return m_interpreter.GetDebugger().GetDummyTarget();
752 }
753 
GetTarget()754 Target &CommandObject::GetTarget() {
755   // Prefer the frozen execution context in the command object.
756   if (Target *target = m_exe_ctx.GetTargetPtr())
757     return *target;
758 
759   // Fallback to the command interpreter's execution context in case we get
760   // called after DoExecute has finished. For example, when doing multi-line
761   // expression that uses an input reader or breakpoint callbacks.
762   if (Target *target = m_interpreter.GetExecutionContext().GetTargetPtr())
763     return *target;
764 
765   // Finally, if we have no other target, get the selected target.
766   if (TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget())
767     return *target_sp;
768 
769   // We only have the dummy target.
770   return GetDummyTarget();
771 }
772 
GetDefaultThread()773 Thread *CommandObject::GetDefaultThread() {
774   Thread *thread_to_use = m_exe_ctx.GetThreadPtr();
775   if (thread_to_use)
776     return thread_to_use;
777 
778   Process *process = m_exe_ctx.GetProcessPtr();
779   if (!process) {
780     Target *target = m_exe_ctx.GetTargetPtr();
781     if (!target) {
782       target = m_interpreter.GetDebugger().GetSelectedTarget().get();
783     }
784     if (target)
785       process = target->GetProcessSP().get();
786   }
787 
788   if (process)
789     return process->GetThreadList().GetSelectedThread().get();
790   else
791     return nullptr;
792 }
793 
Execute(const char * args_string,CommandReturnObject & result)794 void CommandObjectParsed::Execute(const char *args_string,
795                                   CommandReturnObject &result) {
796   bool handled = false;
797   Args cmd_args(args_string);
798   if (HasOverrideCallback()) {
799     Args full_args(GetCommandName());
800     full_args.AppendArguments(cmd_args);
801     handled =
802         InvokeOverrideCallback(full_args.GetConstArgumentVector(), result);
803   }
804   if (!handled) {
805     for (auto entry : llvm::enumerate(cmd_args.entries())) {
806       const Args::ArgEntry &value = entry.value();
807       if (!value.ref().empty() && value.GetQuoteChar() == '`') {
808         // We have to put the backtick back in place for PreprocessCommand.
809         std::string opt_string = value.c_str();
810         Status error;
811         error = m_interpreter.PreprocessToken(opt_string);
812         if (error.Success())
813           cmd_args.ReplaceArgumentAtIndex(entry.index(), opt_string);
814       }
815     }
816 
817     if (CheckRequirements(result)) {
818       if (ParseOptions(cmd_args, result)) {
819         // Call the command-specific version of 'Execute', passing it the
820         // already processed arguments.
821         if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) {
822           result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.",
823                                         GetCommandName());
824           Cleanup();
825           return;
826         }
827         m_interpreter.IncreaseCommandUsage(*this);
828         DoExecute(cmd_args, result);
829       }
830     }
831 
832     Cleanup();
833   }
834 }
835 
Execute(const char * args_string,CommandReturnObject & result)836 void CommandObjectRaw::Execute(const char *args_string,
837                                CommandReturnObject &result) {
838   bool handled = false;
839   if (HasOverrideCallback()) {
840     std::string full_command(GetCommandName());
841     full_command += ' ';
842     full_command += args_string;
843     const char *argv[2] = {nullptr, nullptr};
844     argv[0] = full_command.c_str();
845     handled = InvokeOverrideCallback(argv, result);
846   }
847   if (!handled) {
848     if (CheckRequirements(result))
849       DoExecute(args_string, result);
850 
851     Cleanup();
852   }
853 }
854