xref: /llvm-project/lldb/source/Commands/CommandObjectCommands.cpp (revision 47cbf4a07bdfe8f5ef56be7a0caf003f91a00a9e)
1 //===-- CommandObjectCommands.cpp -------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 #include "llvm/ADT/StringRef.h"
14 
15 // Project includes
16 #include "CommandObjectCommands.h"
17 #include "CommandObjectHelp.h"
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Core/IOHandler.h"
20 #include "lldb/Host/OptionParser.h"
21 #include "lldb/Interpreter/Args.h"
22 #include "lldb/Interpreter/CommandHistory.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
25 #include "lldb/Interpreter/CommandReturnObject.h"
26 #include "lldb/Interpreter/OptionArgParser.h"
27 #include "lldb/Interpreter/OptionValueBoolean.h"
28 #include "lldb/Interpreter/OptionValueString.h"
29 #include "lldb/Interpreter/OptionValueUInt64.h"
30 #include "lldb/Interpreter/Options.h"
31 #include "lldb/Interpreter/ScriptInterpreter.h"
32 #include "lldb/Utility/StringList.h"
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 //-------------------------------------------------------------------------
38 // CommandObjectCommandsSource
39 //-------------------------------------------------------------------------
40 
41 static OptionDefinition g_history_options[] = {
42     // clang-format off
43   { LLDB_OPT_SET_1, false, "count",       'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." },
44   { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." },
45   { LLDB_OPT_SET_1, false, "end-index",   'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." },
46   { LLDB_OPT_SET_2, false, "clear",       'C', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeBoolean,         "Clears the current command history." },
47     // clang-format on
48 };
49 
50 class CommandObjectCommandsHistory : public CommandObjectParsed {
51 public:
52   CommandObjectCommandsHistory(CommandInterpreter &interpreter)
53       : CommandObjectParsed(interpreter, "command history",
54                             "Dump the history of commands in this session.\n"
55                             "Commands in the history list can be run again "
56                             "using \"!<INDEX>\".   \"!-<OFFSET>\" will re-run "
57                             "the command that is <OFFSET> commands from the end"
58                             " of the list (counting the current command).",
59                             nullptr),
60         m_options() {}
61 
62   ~CommandObjectCommandsHistory() override = default;
63 
64   Options *GetOptions() override { return &m_options; }
65 
66 protected:
67   class CommandOptions : public Options {
68   public:
69     CommandOptions()
70         : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {
71     }
72 
73     ~CommandOptions() override = default;
74 
75     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
76                           ExecutionContext *execution_context) override {
77       Status error;
78       const int short_option = m_getopt_table[option_idx].val;
79 
80       switch (short_option) {
81       case 'c':
82         error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
83         break;
84       case 's':
85         if (option_arg == "end") {
86           m_start_idx.SetCurrentValue(UINT64_MAX);
87           m_start_idx.SetOptionWasSet();
88         } else
89           error = m_start_idx.SetValueFromString(option_arg,
90                                                  eVarSetOperationAssign);
91         break;
92       case 'e':
93         error =
94             m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign);
95         break;
96       case 'C':
97         m_clear.SetCurrentValue(true);
98         m_clear.SetOptionWasSet();
99         break;
100       default:
101         error.SetErrorStringWithFormat("unrecognized option '%c'",
102                                        short_option);
103         break;
104       }
105 
106       return error;
107     }
108 
109     void OptionParsingStarting(ExecutionContext *execution_context) override {
110       m_start_idx.Clear();
111       m_stop_idx.Clear();
112       m_count.Clear();
113       m_clear.Clear();
114     }
115 
116     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
117       return llvm::makeArrayRef(g_history_options);
118     }
119 
120     // Instance variables to hold the values for command options.
121 
122     OptionValueUInt64 m_start_idx;
123     OptionValueUInt64 m_stop_idx;
124     OptionValueUInt64 m_count;
125     OptionValueBoolean m_clear;
126   };
127 
128   bool DoExecute(Args &command, CommandReturnObject &result) override {
129     if (m_options.m_clear.GetCurrentValue() &&
130         m_options.m_clear.OptionWasSet()) {
131       m_interpreter.GetCommandHistory().Clear();
132       result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
133     } else {
134       if (m_options.m_start_idx.OptionWasSet() &&
135           m_options.m_stop_idx.OptionWasSet() &&
136           m_options.m_count.OptionWasSet()) {
137         result.AppendError("--count, --start-index and --end-index cannot be "
138                            "all specified in the same invocation");
139         result.SetStatus(lldb::eReturnStatusFailed);
140       } else {
141         std::pair<bool, uint64_t> start_idx(
142             m_options.m_start_idx.OptionWasSet(),
143             m_options.m_start_idx.GetCurrentValue());
144         std::pair<bool, uint64_t> stop_idx(
145             m_options.m_stop_idx.OptionWasSet(),
146             m_options.m_stop_idx.GetCurrentValue());
147         std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
148                                         m_options.m_count.GetCurrentValue());
149 
150         const CommandHistory &history(m_interpreter.GetCommandHistory());
151 
152         if (start_idx.first && start_idx.second == UINT64_MAX) {
153           if (count.first) {
154             start_idx.second = history.GetSize() - count.second;
155             stop_idx.second = history.GetSize() - 1;
156           } else if (stop_idx.first) {
157             start_idx.second = stop_idx.second;
158             stop_idx.second = history.GetSize() - 1;
159           } else {
160             start_idx.second = 0;
161             stop_idx.second = history.GetSize() - 1;
162           }
163         } else {
164           if (!start_idx.first && !stop_idx.first && !count.first) {
165             start_idx.second = 0;
166             stop_idx.second = history.GetSize() - 1;
167           } else if (start_idx.first) {
168             if (count.first) {
169               stop_idx.second = start_idx.second + count.second - 1;
170             } else if (!stop_idx.first) {
171               stop_idx.second = history.GetSize() - 1;
172             }
173           } else if (stop_idx.first) {
174             if (count.first) {
175               if (stop_idx.second >= count.second)
176                 start_idx.second = stop_idx.second - count.second + 1;
177               else
178                 start_idx.second = 0;
179             }
180           } else /* if (count.first) */
181           {
182             start_idx.second = 0;
183             stop_idx.second = count.second - 1;
184           }
185         }
186         history.Dump(result.GetOutputStream(), start_idx.second,
187                      stop_idx.second);
188       }
189     }
190     return result.Succeeded();
191   }
192 
193   CommandOptions m_options;
194 };
195 
196 //-------------------------------------------------------------------------
197 // CommandObjectCommandsSource
198 //-------------------------------------------------------------------------
199 
200 static OptionDefinition g_source_options[] = {
201     // clang-format off
202   { LLDB_OPT_SET_ALL, false, "stop-on-error",    'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
203   { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
204   { LLDB_OPT_SET_ALL, false, "silent-run",       's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
205     // clang-format on
206 };
207 
208 class CommandObjectCommandsSource : public CommandObjectParsed {
209 public:
210   CommandObjectCommandsSource(CommandInterpreter &interpreter)
211       : CommandObjectParsed(
212             interpreter, "command source",
213             "Read and execute LLDB commands from the file <filename>.",
214             nullptr),
215         m_options() {
216     CommandArgumentEntry arg;
217     CommandArgumentData file_arg;
218 
219     // Define the first (and only) variant of this arg.
220     file_arg.arg_type = eArgTypeFilename;
221     file_arg.arg_repetition = eArgRepeatPlain;
222 
223     // There is only one variant this argument could be; put it into the
224     // argument entry.
225     arg.push_back(file_arg);
226 
227     // Push the data for the first argument into the m_arguments vector.
228     m_arguments.push_back(arg);
229   }
230 
231   ~CommandObjectCommandsSource() override = default;
232 
233   const char *GetRepeatCommand(Args &current_command_args,
234                                uint32_t index) override {
235     return "";
236   }
237 
238   int HandleArgumentCompletion(Args &input, int &cursor_index,
239                                int &cursor_char_position,
240                                OptionElementVector &opt_element_vector,
241                                int match_start_point, int max_return_elements,
242                                bool &word_complete,
243                                StringList &matches) override {
244     auto completion_str = input[cursor_index].ref;
245     completion_str = completion_str.take_front(cursor_char_position);
246 
247     CommandCompletions::InvokeCommonCompletionCallbacks(
248         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
249         completion_str, match_start_point, max_return_elements, nullptr,
250         word_complete, matches);
251     return matches.GetSize();
252   }
253 
254   Options *GetOptions() override { return &m_options; }
255 
256 protected:
257   class CommandOptions : public Options {
258   public:
259     CommandOptions()
260         : Options(), m_stop_on_error(true), m_silent_run(false),
261           m_stop_on_continue(true) {}
262 
263     ~CommandOptions() override = default;
264 
265     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
266                           ExecutionContext *execution_context) override {
267       Status error;
268       const int short_option = m_getopt_table[option_idx].val;
269 
270       switch (short_option) {
271       case 'e':
272         error = m_stop_on_error.SetValueFromString(option_arg);
273         break;
274 
275       case 'c':
276         error = m_stop_on_continue.SetValueFromString(option_arg);
277         break;
278 
279       case 's':
280         error = m_silent_run.SetValueFromString(option_arg);
281         break;
282 
283       default:
284         error.SetErrorStringWithFormat("unrecognized option '%c'",
285                                        short_option);
286         break;
287       }
288 
289       return error;
290     }
291 
292     void OptionParsingStarting(ExecutionContext *execution_context) override {
293       m_stop_on_error.Clear();
294       m_silent_run.Clear();
295       m_stop_on_continue.Clear();
296     }
297 
298     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
299       return llvm::makeArrayRef(g_source_options);
300     }
301 
302     // Instance variables to hold the values for command options.
303 
304     OptionValueBoolean m_stop_on_error;
305     OptionValueBoolean m_silent_run;
306     OptionValueBoolean m_stop_on_continue;
307   };
308 
309   bool DoExecute(Args &command, CommandReturnObject &result) override {
310     if (command.GetArgumentCount() != 1) {
311       result.AppendErrorWithFormat(
312           "'%s' takes exactly one executable filename argument.\n",
313           GetCommandName().str().c_str());
314       result.SetStatus(eReturnStatusFailed);
315       return false;
316     }
317 
318     FileSpec cmd_file(command[0].ref, true);
319     ExecutionContext *exe_ctx = nullptr; // Just use the default context.
320 
321     // If any options were set, then use them
322     if (m_options.m_stop_on_error.OptionWasSet() ||
323         m_options.m_silent_run.OptionWasSet() ||
324         m_options.m_stop_on_continue.OptionWasSet()) {
325       // Use user set settings
326       CommandInterpreterRunOptions options;
327       options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
328       options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
329       options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
330       options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
331 
332       m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
333     } else {
334       // No options were set, inherit any settings from nested "command
335       // source" commands,
336       // or set to sane default settings...
337       CommandInterpreterRunOptions options;
338       m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
339     }
340     return result.Succeeded();
341   }
342 
343   CommandOptions m_options;
344 };
345 
346 #pragma mark CommandObjectCommandsAlias
347 //-------------------------------------------------------------------------
348 // CommandObjectCommandsAlias
349 //-------------------------------------------------------------------------
350 
351 static OptionDefinition g_alias_options[] = {
352     // clang-format off
353   { LLDB_OPT_SET_ALL, false, "help",      'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" },
354   { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" },
355     // clang-format on
356 };
357 
358 static const char *g_python_command_instructions =
359     "Enter your Python command(s). Type 'DONE' to end.\n"
360     "You must define a Python function with this signature:\n"
361     "def my_command_impl(debugger, args, result, internal_dict):\n";
362 
363 class CommandObjectCommandsAlias : public CommandObjectRaw {
364 protected:
365   class CommandOptions : public OptionGroup {
366   public:
367     CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
368 
369     ~CommandOptions() override = default;
370 
371     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
372       return llvm::makeArrayRef(g_alias_options);
373     }
374 
375     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
376                           ExecutionContext *execution_context) override {
377       Status error;
378 
379       const int short_option = GetDefinitions()[option_idx].short_option;
380       std::string option_str(option_value);
381 
382       switch (short_option) {
383       case 'h':
384         m_help.SetCurrentValue(option_str);
385         m_help.SetOptionWasSet();
386         break;
387 
388       case 'H':
389         m_long_help.SetCurrentValue(option_str);
390         m_long_help.SetOptionWasSet();
391         break;
392 
393       default:
394         error.SetErrorStringWithFormat("invalid short option character '%c'",
395                                        short_option);
396         break;
397       }
398 
399       return error;
400     }
401 
402     void OptionParsingStarting(ExecutionContext *execution_context) override {
403       m_help.Clear();
404       m_long_help.Clear();
405     }
406 
407     OptionValueString m_help;
408     OptionValueString m_long_help;
409   };
410 
411   OptionGroupOptions m_option_group;
412   CommandOptions m_command_options;
413 
414 public:
415   Options *GetOptions() override { return &m_option_group; }
416 
417   CommandObjectCommandsAlias(CommandInterpreter &interpreter)
418       : CommandObjectRaw(
419             interpreter, "command alias",
420             "Define a custom command in terms of an existing command."),
421         m_option_group(), m_command_options() {
422     m_option_group.Append(&m_command_options);
423     m_option_group.Finalize();
424 
425     SetHelpLong(
426         "'alias' allows the user to create a short-cut or abbreviation for long \
427 commands, multi-word commands, and commands that take particular options.  \
428 Below are some simple examples of how one might use the 'alias' command:"
429         R"(
430 
431 (lldb) command alias sc script
432 
433     Creates the abbreviation 'sc' for the 'script' command.
434 
435 (lldb) command alias bp breakpoint
436 
437 )"
438         "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
439 breakpoint commands are two-word commands, the user would still need to \
440 enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
441         R"(
442 
443 (lldb) command alias bpl breakpoint list
444 
445     Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
446 
447 )"
448         "An alias can include some options for the command, with the values either \
449 filled in at the time the alias is created, or specified as positional \
450 arguments, to be filled in when the alias is invoked.  The following example \
451 shows how to create aliases with options:"
452         R"(
453 
454 (lldb) command alias bfl breakpoint set -f %1 -l %2
455 
456 )"
457         "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
458 options already part of the alias.  So if the user wants to set a breakpoint \
459 by file and line without explicitly having to use the -f and -l options, the \
460 user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
461 for the actual arguments that will be passed when the alias command is used.  \
462 The number in the placeholder refers to the position/order the actual value \
463 occupies when the alias is used.  All the occurrences of '%1' in the alias \
464 will be replaced with the first argument, all the occurrences of '%2' in the \
465 alias will be replaced with the second argument, and so on.  This also allows \
466 actual arguments to be used multiple times within an alias (see 'process \
467 launch' example below)."
468         R"(
469 
470 )"
471         "Note: the positional arguments must substitute as whole words in the resultant \
472 command, so you can't at present do something like this to append the file extension \
473 \".cpp\":"
474         R"(
475 
476 (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
477 
478 )"
479         "For more complex aliasing, use the \"command regex\" command instead.  In the \
480 'bfl' case above, the actual file value will be filled in with the first argument \
481 following 'bfl' and the actual line number value will be filled in with the second \
482 argument.  The user would use this alias as follows:"
483         R"(
484 
485 (lldb) command alias bfl breakpoint set -f %1 -l %2
486 (lldb) bfl my-file.c 137
487 
488 This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
489 
490 Another example:
491 
492 (lldb) command alias pltty process launch -s -o %1 -e %1
493 (lldb) pltty /dev/tty0
494 
495     Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
496 
497 )"
498         "If the user always wanted to pass the same value to a particular option, the \
499 alias could be defined with that value directly in the alias as a constant, \
500 rather than using a positional placeholder:"
501         R"(
502 
503 (lldb) command alias bl3 breakpoint set -f %1 -l 3
504 
505     Always sets a breakpoint on line 3 of whatever file is indicated.)");
506 
507     CommandArgumentEntry arg1;
508     CommandArgumentEntry arg2;
509     CommandArgumentEntry arg3;
510     CommandArgumentData alias_arg;
511     CommandArgumentData cmd_arg;
512     CommandArgumentData options_arg;
513 
514     // Define the first (and only) variant of this arg.
515     alias_arg.arg_type = eArgTypeAliasName;
516     alias_arg.arg_repetition = eArgRepeatPlain;
517 
518     // There is only one variant this argument could be; put it into the
519     // argument entry.
520     arg1.push_back(alias_arg);
521 
522     // Define the first (and only) variant of this arg.
523     cmd_arg.arg_type = eArgTypeCommandName;
524     cmd_arg.arg_repetition = eArgRepeatPlain;
525 
526     // There is only one variant this argument could be; put it into the
527     // argument entry.
528     arg2.push_back(cmd_arg);
529 
530     // Define the first (and only) variant of this arg.
531     options_arg.arg_type = eArgTypeAliasOptions;
532     options_arg.arg_repetition = eArgRepeatOptional;
533 
534     // There is only one variant this argument could be; put it into the
535     // argument entry.
536     arg3.push_back(options_arg);
537 
538     // Push the data for the first argument into the m_arguments vector.
539     m_arguments.push_back(arg1);
540     m_arguments.push_back(arg2);
541     m_arguments.push_back(arg3);
542   }
543 
544   ~CommandObjectCommandsAlias() override = default;
545 
546 protected:
547   bool DoExecute(const char *raw_command_line,
548                  CommandReturnObject &result) override {
549     if (!raw_command_line || !raw_command_line[0]) {
550       result.AppendError("'command alias' requires at least two arguments");
551       return false;
552     }
553 
554     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
555     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
556 
557     const char *remainder = nullptr;
558 
559     if (raw_command_line[0] == '-') {
560       // We have some options and these options MUST end with --.
561       const char *end_options = nullptr;
562       const char *s = raw_command_line;
563       while (s && s[0]) {
564         end_options = ::strstr(s, "--");
565         if (end_options) {
566           end_options += 2; // Get past the "--"
567           if (::isspace(end_options[0])) {
568             remainder = end_options;
569             while (::isspace(*remainder))
570               ++remainder;
571             break;
572           }
573         }
574         s = end_options;
575       }
576 
577       if (end_options) {
578         Args args(
579             llvm::StringRef(raw_command_line, end_options - raw_command_line));
580         if (!ParseOptions(args, result))
581           return false;
582 
583         Status error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
584         if (error.Fail()) {
585           result.AppendError(error.AsCString());
586           result.SetStatus(eReturnStatusFailed);
587           return false;
588         }
589       }
590     }
591     if (nullptr == remainder)
592       remainder = raw_command_line;
593 
594     llvm::StringRef raw_command_string(remainder);
595     Args args(raw_command_string);
596 
597     if (args.GetArgumentCount() < 2) {
598       result.AppendError("'command alias' requires at least two arguments");
599       result.SetStatus(eReturnStatusFailed);
600       return false;
601     }
602 
603     // Get the alias command.
604 
605     auto alias_command = args[0].ref;
606     if (alias_command.startswith("-")) {
607       result.AppendError("aliases starting with a dash are not supported");
608       if (alias_command == "--help" || alias_command == "--long-help") {
609         result.AppendWarning("if trying to pass options to 'command alias' add "
610                              "a -- at the end of the options");
611       }
612       result.SetStatus(eReturnStatusFailed);
613       return false;
614     }
615 
616     // Strip the new alias name off 'raw_command_string'  (leave it on args,
617     // which gets passed to 'Execute', which
618     // does the stripping itself.
619     size_t pos = raw_command_string.find(alias_command);
620     if (pos == 0) {
621       raw_command_string = raw_command_string.substr(alias_command.size());
622       pos = raw_command_string.find_first_not_of(' ');
623       if ((pos != std::string::npos) && (pos > 0))
624         raw_command_string = raw_command_string.substr(pos);
625     } else {
626       result.AppendError("Error parsing command string.  No alias created.");
627       result.SetStatus(eReturnStatusFailed);
628       return false;
629     }
630 
631     // Verify that the command is alias-able.
632     if (m_interpreter.CommandExists(alias_command)) {
633       result.AppendErrorWithFormat(
634           "'%s' is a permanent debugger command and cannot be redefined.\n",
635           args[0].c_str());
636       result.SetStatus(eReturnStatusFailed);
637       return false;
638     }
639 
640     // Get CommandObject that is being aliased. The command name is read from
641     // the front of raw_command_string. raw_command_string is returned with the
642     // name of the command object stripped off the front.
643     llvm::StringRef original_raw_command_string = raw_command_string;
644     CommandObject *cmd_obj =
645         m_interpreter.GetCommandObjectForCommand(raw_command_string);
646 
647     if (!cmd_obj) {
648       result.AppendErrorWithFormat("invalid command given to 'command alias'. "
649                                    "'%s' does not begin with a valid command."
650                                    "  No alias created.",
651                                    original_raw_command_string.str().c_str());
652       result.SetStatus(eReturnStatusFailed);
653       return false;
654     } else if (!cmd_obj->WantsRawCommandString()) {
655       // Note that args was initialized with the original command, and has not
656       // been updated to this point.
657       // Therefore can we pass it to the version of Execute that does not
658       // need/expect raw input in the alias.
659       return HandleAliasingNormalCommand(args, result);
660     } else {
661       return HandleAliasingRawCommand(alias_command, raw_command_string,
662                                       *cmd_obj, result);
663     }
664     return result.Succeeded();
665   }
666 
667   bool HandleAliasingRawCommand(llvm::StringRef alias_command,
668                                 llvm::StringRef raw_command_string,
669                                 CommandObject &cmd_obj,
670                                 CommandReturnObject &result) {
671     // Verify & handle any options/arguments passed to the alias command
672 
673     OptionArgVectorSP option_arg_vector_sp =
674         OptionArgVectorSP(new OptionArgVector);
675 
676     if (CommandObjectSP cmd_obj_sp =
677             m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
678       if (m_interpreter.AliasExists(alias_command) ||
679           m_interpreter.UserCommandExists(alias_command)) {
680         result.AppendWarningWithFormat(
681             "Overwriting existing definition for '%s'.\n",
682             alias_command.str().c_str());
683       }
684       if (CommandAlias *alias = m_interpreter.AddAlias(
685               alias_command, cmd_obj_sp, raw_command_string)) {
686         if (m_command_options.m_help.OptionWasSet())
687           alias->SetHelp(m_command_options.m_help.GetCurrentValue());
688         if (m_command_options.m_long_help.OptionWasSet())
689           alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
690         result.SetStatus(eReturnStatusSuccessFinishNoResult);
691       } else {
692         result.AppendError("Unable to create requested alias.\n");
693         result.SetStatus(eReturnStatusFailed);
694       }
695 
696     } else {
697       result.AppendError("Unable to create requested alias.\n");
698       result.SetStatus(eReturnStatusFailed);
699     }
700 
701     return result.Succeeded();
702   }
703 
704   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
705     size_t argc = args.GetArgumentCount();
706 
707     if (argc < 2) {
708       result.AppendError("'command alias' requires at least two arguments");
709       result.SetStatus(eReturnStatusFailed);
710       return false;
711     }
712 
713     // Save these in std::strings since we're going to shift them off.
714     const std::string alias_command(args[0].ref);
715     const std::string actual_command(args[1].ref);
716 
717     args.Shift(); // Shift the alias command word off the argument vector.
718     args.Shift(); // Shift the old command word off the argument vector.
719 
720     // Verify that the command is alias'able, and get the appropriate command
721     // object.
722 
723     if (m_interpreter.CommandExists(alias_command)) {
724       result.AppendErrorWithFormat(
725           "'%s' is a permanent debugger command and cannot be redefined.\n",
726           alias_command.c_str());
727       result.SetStatus(eReturnStatusFailed);
728       return false;
729     }
730 
731     CommandObjectSP command_obj_sp(
732         m_interpreter.GetCommandSPExact(actual_command, true));
733     CommandObjectSP subcommand_obj_sp;
734     bool use_subcommand = false;
735     if (!command_obj_sp) {
736       result.AppendErrorWithFormat("'%s' is not an existing command.\n",
737                                    actual_command.c_str());
738       result.SetStatus(eReturnStatusFailed);
739       return false;
740     }
741     CommandObject *cmd_obj = command_obj_sp.get();
742     CommandObject *sub_cmd_obj = nullptr;
743     OptionArgVectorSP option_arg_vector_sp =
744         OptionArgVectorSP(new OptionArgVector);
745 
746     while (cmd_obj->IsMultiwordObject() && !args.empty()) {
747       auto sub_command = args[0].ref;
748       assert(!sub_command.empty());
749       subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
750       if (!subcommand_obj_sp) {
751         result.AppendErrorWithFormat(
752             "'%s' is not a valid sub-command of '%s'.  "
753             "Unable to create alias.\n",
754             args[0].c_str(), actual_command.c_str());
755         result.SetStatus(eReturnStatusFailed);
756         return false;
757       }
758 
759       sub_cmd_obj = subcommand_obj_sp.get();
760       use_subcommand = true;
761       args.Shift(); // Shift the sub_command word off the argument vector.
762       cmd_obj = sub_cmd_obj;
763     }
764 
765     // Verify & handle any options/arguments passed to the alias command
766 
767     std::string args_string;
768 
769     if (!args.empty()) {
770       CommandObjectSP tmp_sp =
771           m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
772       if (use_subcommand)
773         tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(),
774                                                  false);
775 
776       args.GetCommandString(args_string);
777     }
778 
779     if (m_interpreter.AliasExists(alias_command) ||
780         m_interpreter.UserCommandExists(alias_command)) {
781       result.AppendWarningWithFormat(
782           "Overwriting existing definition for '%s'.\n", alias_command.c_str());
783     }
784 
785     if (CommandAlias *alias = m_interpreter.AddAlias(
786             alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
787             args_string)) {
788       if (m_command_options.m_help.OptionWasSet())
789         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
790       if (m_command_options.m_long_help.OptionWasSet())
791         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
792       result.SetStatus(eReturnStatusSuccessFinishNoResult);
793     } else {
794       result.AppendError("Unable to create requested alias.\n");
795       result.SetStatus(eReturnStatusFailed);
796       return false;
797     }
798 
799     return result.Succeeded();
800   }
801 };
802 
803 #pragma mark CommandObjectCommandsUnalias
804 //-------------------------------------------------------------------------
805 // CommandObjectCommandsUnalias
806 //-------------------------------------------------------------------------
807 
808 class CommandObjectCommandsUnalias : public CommandObjectParsed {
809 public:
810   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
811       : CommandObjectParsed(
812             interpreter, "command unalias",
813             "Delete one or more custom commands defined by 'command alias'.",
814             nullptr) {
815     CommandArgumentEntry arg;
816     CommandArgumentData alias_arg;
817 
818     // Define the first (and only) variant of this arg.
819     alias_arg.arg_type = eArgTypeAliasName;
820     alias_arg.arg_repetition = eArgRepeatPlain;
821 
822     // There is only one variant this argument could be; put it into the
823     // argument entry.
824     arg.push_back(alias_arg);
825 
826     // Push the data for the first argument into the m_arguments vector.
827     m_arguments.push_back(arg);
828   }
829 
830   ~CommandObjectCommandsUnalias() override = default;
831 
832 protected:
833   bool DoExecute(Args &args, CommandReturnObject &result) override {
834     CommandObject::CommandMap::iterator pos;
835     CommandObject *cmd_obj;
836 
837     if (args.empty()) {
838       result.AppendError("must call 'unalias' with a valid alias");
839       result.SetStatus(eReturnStatusFailed);
840       return false;
841     }
842 
843     auto command_name = args[0].ref;
844     cmd_obj = m_interpreter.GetCommandObject(command_name);
845     if (!cmd_obj) {
846       result.AppendErrorWithFormat(
847           "'%s' is not a known command.\nTry 'help' to see a "
848           "current list of commands.\n",
849           args[0].c_str());
850       result.SetStatus(eReturnStatusFailed);
851       return false;
852     }
853 
854     if (m_interpreter.CommandExists(command_name)) {
855       if (cmd_obj->IsRemovable()) {
856         result.AppendErrorWithFormat(
857             "'%s' is not an alias, it is a debugger command which can be "
858             "removed using the 'command delete' command.\n",
859             args[0].c_str());
860       } else {
861         result.AppendErrorWithFormat(
862             "'%s' is a permanent debugger command and cannot be removed.\n",
863             args[0].c_str());
864       }
865       result.SetStatus(eReturnStatusFailed);
866       return false;
867     }
868 
869     if (!m_interpreter.RemoveAlias(command_name)) {
870       if (m_interpreter.AliasExists(command_name))
871         result.AppendErrorWithFormat(
872             "Error occurred while attempting to unalias '%s'.\n",
873             args[0].c_str());
874       else
875         result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
876                                      args[0].c_str());
877       result.SetStatus(eReturnStatusFailed);
878       return false;
879     }
880 
881     result.SetStatus(eReturnStatusSuccessFinishNoResult);
882     return result.Succeeded();
883   }
884 };
885 
886 #pragma mark CommandObjectCommandsDelete
887 //-------------------------------------------------------------------------
888 // CommandObjectCommandsDelete
889 //-------------------------------------------------------------------------
890 
891 class CommandObjectCommandsDelete : public CommandObjectParsed {
892 public:
893   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
894       : CommandObjectParsed(
895             interpreter, "command delete",
896             "Delete one or more custom commands defined by 'command regex'.",
897             nullptr) {
898     CommandArgumentEntry arg;
899     CommandArgumentData alias_arg;
900 
901     // Define the first (and only) variant of this arg.
902     alias_arg.arg_type = eArgTypeCommandName;
903     alias_arg.arg_repetition = eArgRepeatPlain;
904 
905     // There is only one variant this argument could be; put it into the
906     // argument entry.
907     arg.push_back(alias_arg);
908 
909     // Push the data for the first argument into the m_arguments vector.
910     m_arguments.push_back(arg);
911   }
912 
913   ~CommandObjectCommandsDelete() override = default;
914 
915 protected:
916   bool DoExecute(Args &args, CommandReturnObject &result) override {
917     CommandObject::CommandMap::iterator pos;
918 
919     if (args.empty()) {
920       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
921                                    "defined regular expression command names",
922                                    GetCommandName().str().c_str());
923       result.SetStatus(eReturnStatusFailed);
924     }
925 
926     auto command_name = args[0].ref;
927     if (!m_interpreter.CommandExists(command_name)) {
928       StreamString error_msg_stream;
929       const bool generate_apropos = true;
930       const bool generate_type_lookup = false;
931       CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
932           &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
933           generate_apropos, generate_type_lookup);
934       result.AppendError(error_msg_stream.GetString());
935       result.SetStatus(eReturnStatusFailed);
936       return false;
937     }
938 
939     if (!m_interpreter.RemoveCommand(command_name)) {
940       result.AppendErrorWithFormat(
941           "'%s' is a permanent debugger command and cannot be removed.\n",
942           args[0].c_str());
943       result.SetStatus(eReturnStatusFailed);
944       return false;
945     }
946 
947     result.SetStatus(eReturnStatusSuccessFinishNoResult);
948     return true;
949   }
950 };
951 
952 //-------------------------------------------------------------------------
953 // CommandObjectCommandsAddRegex
954 //-------------------------------------------------------------------------
955 
956 static OptionDefinition g_regex_options[] = {
957     // clang-format off
958   { LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." },
959   { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
960     // clang-format on
961 };
962 
963 #pragma mark CommandObjectCommandsAddRegex
964 
965 class CommandObjectCommandsAddRegex : public CommandObjectParsed,
966                                       public IOHandlerDelegateMultiline {
967 public:
968   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
969       : CommandObjectParsed(
970             interpreter, "command regex", "Define a custom command in terms of "
971                                           "existing commands by matching "
972                                           "regular expressions.",
973             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
974         IOHandlerDelegateMultiline("",
975                                    IOHandlerDelegate::Completion::LLDBCommand),
976         m_options() {
977     SetHelpLong(
978         R"(
979 )"
980         "This command allows the user to create powerful regular expression commands \
981 with substitutions. The regular expressions and substitutions are specified \
982 using the regular expression substitution format of:"
983         R"(
984 
985     s/<regex>/<subst>/
986 
987 )"
988         "<regex> is a regular expression that can use parenthesis to capture regular \
989 expression input and substitute the captured matches in the output using %1 \
990 for the first match, %2 for the second, and so on."
991         R"(
992 
993 )"
994         "The regular expressions can all be specified on the command line if more than \
995 one argument is provided. If just the command name is provided on the command \
996 line, then the regular expressions and substitutions can be entered on separate \
997 lines, followed by an empty line to terminate the command definition."
998         R"(
999 
1000 EXAMPLES
1001 
1002 )"
1003         "The following example will define a regular expression command named 'f' that \
1004 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
1005 a number follows 'f':"
1006         R"(
1007 
1008     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
1009   }
1010 
1011   ~CommandObjectCommandsAddRegex() override = default;
1012 
1013 protected:
1014   void IOHandlerActivated(IOHandler &io_handler) override {
1015     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1016     if (output_sp) {
1017       output_sp->PutCString("Enter one of more sed substitution commands in "
1018                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
1019                             "substitution list with an empty line.\n");
1020       output_sp->Flush();
1021     }
1022   }
1023 
1024   void IOHandlerInputComplete(IOHandler &io_handler,
1025                               std::string &data) override {
1026     io_handler.SetIsDone(true);
1027     if (m_regex_cmd_ap) {
1028       StringList lines;
1029       if (lines.SplitIntoLines(data)) {
1030         const size_t num_lines = lines.GetSize();
1031         bool check_only = false;
1032         for (size_t i = 0; i < num_lines; ++i) {
1033           llvm::StringRef bytes_strref(lines[i]);
1034           Status error = AppendRegexSubstitution(bytes_strref, check_only);
1035           if (error.Fail()) {
1036             if (!m_interpreter.GetDebugger()
1037                      .GetCommandInterpreter()
1038                      .GetBatchCommandMode()) {
1039               StreamSP out_stream =
1040                   m_interpreter.GetDebugger().GetAsyncOutputStream();
1041               out_stream->Printf("error: %s\n", error.AsCString());
1042             }
1043           }
1044         }
1045       }
1046       if (m_regex_cmd_ap->HasRegexEntries()) {
1047         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1048         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1049       }
1050     }
1051   }
1052 
1053   bool DoExecute(Args &command, CommandReturnObject &result) override {
1054     const size_t argc = command.GetArgumentCount();
1055     if (argc == 0) {
1056       result.AppendError("usage: 'command regex <command-name> "
1057                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1058       result.SetStatus(eReturnStatusFailed);
1059       return false;
1060     }
1061 
1062     Status error;
1063     auto name = command[0].ref;
1064     m_regex_cmd_ap = llvm::make_unique<CommandObjectRegexCommand>(
1065         m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
1066         true);
1067 
1068     if (argc == 1) {
1069       Debugger &debugger = m_interpreter.GetDebugger();
1070       bool color_prompt = debugger.GetUseColor();
1071       const bool multiple_lines = true; // Get multiple lines
1072       IOHandlerSP io_handler_sp(new IOHandlerEditline(
1073           debugger, IOHandler::Type::Other,
1074           "lldb-regex",          // Name of input reader for history
1075           llvm::StringRef("> "), // Prompt
1076           llvm::StringRef(),     // Continuation prompt
1077           multiple_lines, color_prompt,
1078           0, // Don't show line numbers
1079           *this));
1080 
1081       if (io_handler_sp) {
1082         debugger.PushIOHandler(io_handler_sp);
1083         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1084       }
1085     } else {
1086       for (auto &entry : command.entries().drop_front()) {
1087         bool check_only = false;
1088         error = AppendRegexSubstitution(entry.ref, check_only);
1089         if (error.Fail())
1090           break;
1091       }
1092 
1093       if (error.Success()) {
1094         AddRegexCommandToInterpreter();
1095       }
1096     }
1097     if (error.Fail()) {
1098       result.AppendError(error.AsCString());
1099       result.SetStatus(eReturnStatusFailed);
1100     }
1101 
1102     return result.Succeeded();
1103   }
1104 
1105   Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1106                                  bool check_only) {
1107     Status error;
1108 
1109     if (!m_regex_cmd_ap) {
1110       error.SetErrorStringWithFormat(
1111           "invalid regular expression command object for: '%.*s'",
1112           (int)regex_sed.size(), regex_sed.data());
1113       return error;
1114     }
1115 
1116     size_t regex_sed_size = regex_sed.size();
1117 
1118     if (regex_sed_size <= 1) {
1119       error.SetErrorStringWithFormat(
1120           "regular expression substitution string is too short: '%.*s'",
1121           (int)regex_sed.size(), regex_sed.data());
1122       return error;
1123     }
1124 
1125     if (regex_sed[0] != 's') {
1126       error.SetErrorStringWithFormat("regular expression substitution string "
1127                                      "doesn't start with 's': '%.*s'",
1128                                      (int)regex_sed.size(), regex_sed.data());
1129       return error;
1130     }
1131     const size_t first_separator_char_pos = 1;
1132     // use the char that follows 's' as the regex separator character
1133     // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1134     const char separator_char = regex_sed[first_separator_char_pos];
1135     const size_t second_separator_char_pos =
1136         regex_sed.find(separator_char, first_separator_char_pos + 1);
1137 
1138     if (second_separator_char_pos == std::string::npos) {
1139       error.SetErrorStringWithFormat(
1140           "missing second '%c' separator char after '%.*s' in '%.*s'",
1141           separator_char,
1142           (int)(regex_sed.size() - first_separator_char_pos - 1),
1143           regex_sed.data() + (first_separator_char_pos + 1),
1144           (int)regex_sed.size(), regex_sed.data());
1145       return error;
1146     }
1147 
1148     const size_t third_separator_char_pos =
1149         regex_sed.find(separator_char, second_separator_char_pos + 1);
1150 
1151     if (third_separator_char_pos == std::string::npos) {
1152       error.SetErrorStringWithFormat(
1153           "missing third '%c' separator char after '%.*s' in '%.*s'",
1154           separator_char,
1155           (int)(regex_sed.size() - second_separator_char_pos - 1),
1156           regex_sed.data() + (second_separator_char_pos + 1),
1157           (int)regex_sed.size(), regex_sed.data());
1158       return error;
1159     }
1160 
1161     if (third_separator_char_pos != regex_sed_size - 1) {
1162       // Make sure that everything that follows the last regex
1163       // separator char
1164       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1165                                       third_separator_char_pos + 1) !=
1166           std::string::npos) {
1167         error.SetErrorStringWithFormat(
1168             "extra data found after the '%.*s' regular expression substitution "
1169             "string: '%.*s'",
1170             (int)third_separator_char_pos + 1, regex_sed.data(),
1171             (int)(regex_sed.size() - third_separator_char_pos - 1),
1172             regex_sed.data() + (third_separator_char_pos + 1));
1173         return error;
1174       }
1175     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1176       error.SetErrorStringWithFormat(
1177           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1178           separator_char, separator_char, separator_char, (int)regex_sed.size(),
1179           regex_sed.data());
1180       return error;
1181     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1182       error.SetErrorStringWithFormat(
1183           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1184           separator_char, separator_char, separator_char, (int)regex_sed.size(),
1185           regex_sed.data());
1186       return error;
1187     }
1188 
1189     if (!check_only) {
1190       std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1191                                          second_separator_char_pos -
1192                                              first_separator_char_pos - 1));
1193       std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1194                                          third_separator_char_pos -
1195                                              second_separator_char_pos - 1));
1196       m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
1197     }
1198     return error;
1199   }
1200 
1201   void AddRegexCommandToInterpreter() {
1202     if (m_regex_cmd_ap) {
1203       if (m_regex_cmd_ap->HasRegexEntries()) {
1204         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1205         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1206       }
1207     }
1208   }
1209 
1210 private:
1211   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1212 
1213   class CommandOptions : public Options {
1214   public:
1215     CommandOptions() : Options() {}
1216 
1217     ~CommandOptions() override = default;
1218 
1219     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1220                           ExecutionContext *execution_context) override {
1221       Status error;
1222       const int short_option = m_getopt_table[option_idx].val;
1223 
1224       switch (short_option) {
1225       case 'h':
1226         m_help.assign(option_arg);
1227         break;
1228       case 's':
1229         m_syntax.assign(option_arg);
1230         break;
1231       default:
1232         error.SetErrorStringWithFormat("unrecognized option '%c'",
1233                                        short_option);
1234         break;
1235       }
1236 
1237       return error;
1238     }
1239 
1240     void OptionParsingStarting(ExecutionContext *execution_context) override {
1241       m_help.clear();
1242       m_syntax.clear();
1243     }
1244 
1245     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1246       return llvm::makeArrayRef(g_regex_options);
1247     }
1248 
1249     // TODO: Convert these functions to return StringRefs.
1250     const char *GetHelp() {
1251       return (m_help.empty() ? nullptr : m_help.c_str());
1252     }
1253 
1254     const char *GetSyntax() {
1255       return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1256     }
1257 
1258   protected:
1259     // Instance variables to hold the values for command options.
1260 
1261     std::string m_help;
1262     std::string m_syntax;
1263   };
1264 
1265   Options *GetOptions() override { return &m_options; }
1266 
1267   CommandOptions m_options;
1268 };
1269 
1270 class CommandObjectPythonFunction : public CommandObjectRaw {
1271 public:
1272   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1273                               std::string funct, std::string help,
1274                               ScriptedCommandSynchronicity synch)
1275       : CommandObjectRaw(interpreter, name),
1276         m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1277     if (!help.empty())
1278       SetHelp(help);
1279     else {
1280       StreamString stream;
1281       stream.Printf("For more information run 'help %s'", name.c_str());
1282       SetHelp(stream.GetString());
1283     }
1284   }
1285 
1286   ~CommandObjectPythonFunction() override = default;
1287 
1288   bool IsRemovable() const override { return true; }
1289 
1290   const std::string &GetFunctionName() { return m_function_name; }
1291 
1292   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1293 
1294   llvm::StringRef GetHelpLong() override {
1295     if (m_fetched_help_long)
1296       return CommandObjectRaw::GetHelpLong();
1297 
1298     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1299     if (!scripter)
1300       return CommandObjectRaw::GetHelpLong();
1301 
1302     std::string docstring;
1303     m_fetched_help_long =
1304         scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1305     if (!docstring.empty())
1306       SetHelpLong(docstring);
1307     return CommandObjectRaw::GetHelpLong();
1308   }
1309 
1310 protected:
1311   bool DoExecute(const char *raw_command_line,
1312                  CommandReturnObject &result) override {
1313     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1314 
1315     Status error;
1316 
1317     result.SetStatus(eReturnStatusInvalid);
1318 
1319     if (!scripter ||
1320         !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1321                                          raw_command_line, m_synchro, result,
1322                                          error, m_exe_ctx)) {
1323       result.AppendError(error.AsCString());
1324       result.SetStatus(eReturnStatusFailed);
1325     } else {
1326       // Don't change the status if the command already set it...
1327       if (result.GetStatus() == eReturnStatusInvalid) {
1328         if (result.GetOutputData().empty())
1329           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1330         else
1331           result.SetStatus(eReturnStatusSuccessFinishResult);
1332       }
1333     }
1334 
1335     return result.Succeeded();
1336   }
1337 
1338 private:
1339   std::string m_function_name;
1340   ScriptedCommandSynchronicity m_synchro;
1341   bool m_fetched_help_long;
1342 };
1343 
1344 class CommandObjectScriptingObject : public CommandObjectRaw {
1345 public:
1346   CommandObjectScriptingObject(CommandInterpreter &interpreter,
1347                                std::string name,
1348                                StructuredData::GenericSP cmd_obj_sp,
1349                                ScriptedCommandSynchronicity synch)
1350       : CommandObjectRaw(interpreter, name),
1351         m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1352         m_fetched_help_long(false) {
1353     StreamString stream;
1354     stream.Printf("For more information run 'help %s'", name.c_str());
1355     SetHelp(stream.GetString());
1356     if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1357       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1358   }
1359 
1360   ~CommandObjectScriptingObject() override = default;
1361 
1362   bool IsRemovable() const override { return true; }
1363 
1364   StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
1365 
1366   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1367 
1368   llvm::StringRef GetHelp() override {
1369     if (m_fetched_help_short)
1370       return CommandObjectRaw::GetHelp();
1371     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1372     if (!scripter)
1373       return CommandObjectRaw::GetHelp();
1374     std::string docstring;
1375     m_fetched_help_short =
1376         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1377     if (!docstring.empty())
1378       SetHelp(docstring);
1379 
1380     return CommandObjectRaw::GetHelp();
1381   }
1382 
1383   llvm::StringRef GetHelpLong() override {
1384     if (m_fetched_help_long)
1385       return CommandObjectRaw::GetHelpLong();
1386 
1387     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1388     if (!scripter)
1389       return CommandObjectRaw::GetHelpLong();
1390 
1391     std::string docstring;
1392     m_fetched_help_long =
1393         scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1394     if (!docstring.empty())
1395       SetHelpLong(docstring);
1396     return CommandObjectRaw::GetHelpLong();
1397   }
1398 
1399 protected:
1400   bool DoExecute(const char *raw_command_line,
1401                  CommandReturnObject &result) override {
1402     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1403 
1404     Status error;
1405 
1406     result.SetStatus(eReturnStatusInvalid);
1407 
1408     if (!scripter ||
1409         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1410                                          m_synchro, result, error, m_exe_ctx)) {
1411       result.AppendError(error.AsCString());
1412       result.SetStatus(eReturnStatusFailed);
1413     } else {
1414       // Don't change the status if the command already set it...
1415       if (result.GetStatus() == eReturnStatusInvalid) {
1416         if (result.GetOutputData().empty())
1417           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1418         else
1419           result.SetStatus(eReturnStatusSuccessFinishResult);
1420       }
1421     }
1422 
1423     return result.Succeeded();
1424   }
1425 
1426 private:
1427   StructuredData::GenericSP m_cmd_obj_sp;
1428   ScriptedCommandSynchronicity m_synchro;
1429   bool m_fetched_help_short : 1;
1430   bool m_fetched_help_long : 1;
1431 };
1432 
1433 //-------------------------------------------------------------------------
1434 // CommandObjectCommandsScriptImport
1435 //-------------------------------------------------------------------------
1436 
1437 OptionDefinition g_script_import_options[] = {
1438     // clang-format off
1439   { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not." },
1440     // clang-format on
1441 };
1442 
1443 class CommandObjectCommandsScriptImport : public CommandObjectParsed {
1444 public:
1445   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1446       : CommandObjectParsed(interpreter, "command script import",
1447                             "Import a scripting module in LLDB.", nullptr),
1448         m_options() {
1449     CommandArgumentEntry arg1;
1450     CommandArgumentData cmd_arg;
1451 
1452     // Define the first (and only) variant of this arg.
1453     cmd_arg.arg_type = eArgTypeFilename;
1454     cmd_arg.arg_repetition = eArgRepeatPlus;
1455 
1456     // There is only one variant this argument could be; put it into the
1457     // argument entry.
1458     arg1.push_back(cmd_arg);
1459 
1460     // Push the data for the first argument into the m_arguments vector.
1461     m_arguments.push_back(arg1);
1462   }
1463 
1464   ~CommandObjectCommandsScriptImport() override = default;
1465 
1466   int HandleArgumentCompletion(Args &input, int &cursor_index,
1467                                int &cursor_char_position,
1468                                OptionElementVector &opt_element_vector,
1469                                int match_start_point, int max_return_elements,
1470                                bool &word_complete,
1471                                StringList &matches) override {
1472     llvm::StringRef completion_str = input[cursor_index].ref;
1473     completion_str = completion_str.take_front(cursor_char_position);
1474 
1475     CommandCompletions::InvokeCommonCompletionCallbacks(
1476         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1477         completion_str, match_start_point, max_return_elements, nullptr,
1478         word_complete, matches);
1479     return matches.GetSize();
1480   }
1481 
1482   Options *GetOptions() override { return &m_options; }
1483 
1484 protected:
1485   class CommandOptions : public Options {
1486   public:
1487     CommandOptions() : Options() {}
1488 
1489     ~CommandOptions() override = default;
1490 
1491     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1492                           ExecutionContext *execution_context) override {
1493       Status error;
1494       const int short_option = m_getopt_table[option_idx].val;
1495 
1496       switch (short_option) {
1497       case 'r':
1498         m_allow_reload = true;
1499         break;
1500       default:
1501         error.SetErrorStringWithFormat("unrecognized option '%c'",
1502                                        short_option);
1503         break;
1504       }
1505 
1506       return error;
1507     }
1508 
1509     void OptionParsingStarting(ExecutionContext *execution_context) override {
1510       m_allow_reload = true;
1511     }
1512 
1513     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1514       return llvm::makeArrayRef(g_script_import_options);
1515     }
1516 
1517     // Instance variables to hold the values for command options.
1518 
1519     bool m_allow_reload;
1520   };
1521 
1522   bool DoExecute(Args &command, CommandReturnObject &result) override {
1523     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1524         lldb::eScriptLanguagePython) {
1525       result.AppendError("only scripting language supported for module "
1526                          "importing is currently Python");
1527       result.SetStatus(eReturnStatusFailed);
1528       return false;
1529     }
1530 
1531     if (command.empty()) {
1532       result.AppendError("command script import needs one or more arguments");
1533       result.SetStatus(eReturnStatusFailed);
1534       return false;
1535     }
1536 
1537     for (auto &entry : command.entries()) {
1538       Status error;
1539 
1540       const bool init_session = true;
1541       // FIXME: this is necessary because CommandObject::CheckRequirements()
1542       // assumes that commands won't ever be recursively invoked, but it's
1543       // actually possible to craft a Python script that does other "command
1544       // script imports" in __lldb_init_module the real fix is to have recursive
1545       // commands possible with a CommandInvocation object separate from the
1546       // CommandObject itself, so that recursive command invocations won't stomp
1547       // on each other (wrt to execution contents, options, and more)
1548       m_exe_ctx.Clear();
1549       if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
1550               entry.c_str(), m_options.m_allow_reload, init_session, error)) {
1551         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1552       } else {
1553         result.AppendErrorWithFormat("module importing failed: %s",
1554                                      error.AsCString());
1555         result.SetStatus(eReturnStatusFailed);
1556       }
1557     }
1558 
1559     return result.Succeeded();
1560   }
1561 
1562   CommandOptions m_options;
1563 };
1564 
1565 //-------------------------------------------------------------------------
1566 // CommandObjectCommandsScriptAdd
1567 //-------------------------------------------------------------------------
1568 
1569 static OptionEnumValueElement g_script_synchro_type[] = {
1570     {eScriptedCommandSynchronicitySynchronous, "synchronous",
1571      "Run synchronous"},
1572     {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1573      "Run asynchronous"},
1574     {eScriptedCommandSynchronicityCurrentValue, "current",
1575      "Do not alter current setting"},
1576     {0, nullptr, nullptr}};
1577 
1578 static OptionDefinition g_script_add_options[] = {
1579     // clang-format off
1580   { LLDB_OPT_SET_1,   false, "function",      'f', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypePythonFunction,               "Name of the Python function to bind to this command name." },
1581   { LLDB_OPT_SET_2,   false, "class",         'c', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypePythonClass,                  "Name of the Python class to bind to this command name." },
1582   { LLDB_OPT_SET_1,   false, "help"  ,        'h', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypeHelpText,                     "The help text to display for this command." },
1583   { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." },
1584     // clang-format on
1585 };
1586 
1587 class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1588                                        public IOHandlerDelegateMultiline {
1589 public:
1590   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1591       : CommandObjectParsed(interpreter, "command script add",
1592                             "Add a scripted function as an LLDB command.",
1593                             nullptr),
1594         IOHandlerDelegateMultiline("DONE"), m_options() {
1595     CommandArgumentEntry arg1;
1596     CommandArgumentData cmd_arg;
1597 
1598     // Define the first (and only) variant of this arg.
1599     cmd_arg.arg_type = eArgTypeCommandName;
1600     cmd_arg.arg_repetition = eArgRepeatPlain;
1601 
1602     // There is only one variant this argument could be; put it into the
1603     // argument entry.
1604     arg1.push_back(cmd_arg);
1605 
1606     // Push the data for the first argument into the m_arguments vector.
1607     m_arguments.push_back(arg1);
1608   }
1609 
1610   ~CommandObjectCommandsScriptAdd() override = default;
1611 
1612   Options *GetOptions() override { return &m_options; }
1613 
1614 protected:
1615   class CommandOptions : public Options {
1616   public:
1617     CommandOptions()
1618         : Options(), m_class_name(), m_funct_name(), m_short_help(),
1619           m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
1620 
1621     ~CommandOptions() override = default;
1622 
1623     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1624                           ExecutionContext *execution_context) override {
1625       Status error;
1626       const int short_option = m_getopt_table[option_idx].val;
1627 
1628       switch (short_option) {
1629       case 'f':
1630         if (!option_arg.empty())
1631           m_funct_name = option_arg;
1632         break;
1633       case 'c':
1634         if (!option_arg.empty())
1635           m_class_name = option_arg;
1636         break;
1637       case 'h':
1638         if (!option_arg.empty())
1639           m_short_help = option_arg;
1640         break;
1641       case 's':
1642         m_synchronicity =
1643             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1644                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1645         if (!error.Success())
1646           error.SetErrorStringWithFormat(
1647               "unrecognized value for synchronicity '%s'",
1648               option_arg.str().c_str());
1649         break;
1650       default:
1651         error.SetErrorStringWithFormat("unrecognized option '%c'",
1652                                        short_option);
1653         break;
1654       }
1655 
1656       return error;
1657     }
1658 
1659     void OptionParsingStarting(ExecutionContext *execution_context) override {
1660       m_class_name.clear();
1661       m_funct_name.clear();
1662       m_short_help.clear();
1663       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1664     }
1665 
1666     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1667       return llvm::makeArrayRef(g_script_add_options);
1668     }
1669 
1670     // Instance variables to hold the values for command options.
1671 
1672     std::string m_class_name;
1673     std::string m_funct_name;
1674     std::string m_short_help;
1675     ScriptedCommandSynchronicity m_synchronicity;
1676   };
1677 
1678   void IOHandlerActivated(IOHandler &io_handler) override {
1679     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1680     if (output_sp) {
1681       output_sp->PutCString(g_python_command_instructions);
1682       output_sp->Flush();
1683     }
1684   }
1685 
1686   void IOHandlerInputComplete(IOHandler &io_handler,
1687                               std::string &data) override {
1688     StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1689 
1690     ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1691     if (interpreter) {
1692 
1693       StringList lines;
1694       lines.SplitIntoLines(data);
1695       if (lines.GetSize() > 0) {
1696         std::string funct_name_str;
1697         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1698           if (funct_name_str.empty()) {
1699             error_sp->Printf("error: unable to obtain a function name, didn't "
1700                              "add python command.\n");
1701             error_sp->Flush();
1702           } else {
1703             // everything should be fine now, let's add this alias
1704 
1705             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1706                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
1707                 m_synchronicity));
1708 
1709             if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1710                                               true)) {
1711               error_sp->Printf("error: unable to add selected command, didn't "
1712                                "add python command.\n");
1713               error_sp->Flush();
1714             }
1715           }
1716         } else {
1717           error_sp->Printf(
1718               "error: unable to create function, didn't add python command.\n");
1719           error_sp->Flush();
1720         }
1721       } else {
1722         error_sp->Printf("error: empty function, didn't add python command.\n");
1723         error_sp->Flush();
1724       }
1725     } else {
1726       error_sp->Printf(
1727           "error: script interpreter missing, didn't add python command.\n");
1728       error_sp->Flush();
1729     }
1730 
1731     io_handler.SetIsDone(true);
1732   }
1733 
1734 protected:
1735   bool DoExecute(Args &command, CommandReturnObject &result) override {
1736     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1737         lldb::eScriptLanguagePython) {
1738       result.AppendError("only scripting language supported for scripted "
1739                          "commands is currently Python");
1740       result.SetStatus(eReturnStatusFailed);
1741       return false;
1742     }
1743 
1744     if (command.GetArgumentCount() != 1) {
1745       result.AppendError("'command script add' requires one argument");
1746       result.SetStatus(eReturnStatusFailed);
1747       return false;
1748     }
1749 
1750     // Store the options in case we get multi-line input
1751     m_cmd_name = command[0].ref;
1752     m_short_help.assign(m_options.m_short_help);
1753     m_synchronicity = m_options.m_synchronicity;
1754 
1755     if (m_options.m_class_name.empty()) {
1756       if (m_options.m_funct_name.empty()) {
1757         m_interpreter.GetPythonCommandsFromIOHandler(
1758             "     ",  // Prompt
1759             *this,    // IOHandlerDelegate
1760             true,     // Run IOHandler in async mode
1761             nullptr); // Baton for the "io_handler" that will be passed back
1762                       // into our IOHandlerDelegate functions
1763       } else {
1764         CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1765             m_interpreter, m_cmd_name, m_options.m_funct_name,
1766             m_options.m_short_help, m_synchronicity));
1767         if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1768           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1769         } else {
1770           result.AppendError("cannot add command");
1771           result.SetStatus(eReturnStatusFailed);
1772         }
1773       }
1774     } else {
1775       ScriptInterpreter *interpreter =
1776           GetCommandInterpreter().GetScriptInterpreter();
1777       if (!interpreter) {
1778         result.AppendError("cannot find ScriptInterpreter");
1779         result.SetStatus(eReturnStatusFailed);
1780         return false;
1781       }
1782 
1783       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1784           m_options.m_class_name.c_str());
1785       if (!cmd_obj_sp) {
1786         result.AppendError("cannot create helper object");
1787         result.SetStatus(eReturnStatusFailed);
1788         return false;
1789       }
1790 
1791       CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1792           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1793       if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1794         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1795       } else {
1796         result.AppendError("cannot add command");
1797         result.SetStatus(eReturnStatusFailed);
1798       }
1799     }
1800 
1801     return result.Succeeded();
1802   }
1803 
1804   CommandOptions m_options;
1805   std::string m_cmd_name;
1806   std::string m_short_help;
1807   ScriptedCommandSynchronicity m_synchronicity;
1808 };
1809 
1810 //-------------------------------------------------------------------------
1811 // CommandObjectCommandsScriptList
1812 //-------------------------------------------------------------------------
1813 
1814 class CommandObjectCommandsScriptList : public CommandObjectParsed {
1815 public:
1816   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1817       : CommandObjectParsed(interpreter, "command script list",
1818                             "List defined scripted commands.", nullptr) {}
1819 
1820   ~CommandObjectCommandsScriptList() override = default;
1821 
1822   bool DoExecute(Args &command, CommandReturnObject &result) override {
1823     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1824 
1825     result.SetStatus(eReturnStatusSuccessFinishResult);
1826 
1827     return true;
1828   }
1829 };
1830 
1831 //-------------------------------------------------------------------------
1832 // CommandObjectCommandsScriptClear
1833 //-------------------------------------------------------------------------
1834 
1835 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1836 public:
1837   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1838       : CommandObjectParsed(interpreter, "command script clear",
1839                             "Delete all scripted commands.", nullptr) {}
1840 
1841   ~CommandObjectCommandsScriptClear() override = default;
1842 
1843 protected:
1844   bool DoExecute(Args &command, CommandReturnObject &result) override {
1845     m_interpreter.RemoveAllUser();
1846 
1847     result.SetStatus(eReturnStatusSuccessFinishResult);
1848 
1849     return true;
1850   }
1851 };
1852 
1853 //-------------------------------------------------------------------------
1854 // CommandObjectCommandsScriptDelete
1855 //-------------------------------------------------------------------------
1856 
1857 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1858 public:
1859   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1860       : CommandObjectParsed(interpreter, "command script delete",
1861                             "Delete a scripted command.", nullptr) {
1862     CommandArgumentEntry arg1;
1863     CommandArgumentData cmd_arg;
1864 
1865     // Define the first (and only) variant of this arg.
1866     cmd_arg.arg_type = eArgTypeCommandName;
1867     cmd_arg.arg_repetition = eArgRepeatPlain;
1868 
1869     // There is only one variant this argument could be; put it into the
1870     // argument entry.
1871     arg1.push_back(cmd_arg);
1872 
1873     // Push the data for the first argument into the m_arguments vector.
1874     m_arguments.push_back(arg1);
1875   }
1876 
1877   ~CommandObjectCommandsScriptDelete() override = default;
1878 
1879 protected:
1880   bool DoExecute(Args &command, CommandReturnObject &result) override {
1881 
1882     if (command.GetArgumentCount() != 1) {
1883       result.AppendError("'command script delete' requires one argument");
1884       result.SetStatus(eReturnStatusFailed);
1885       return false;
1886     }
1887 
1888     auto cmd_name = command[0].ref;
1889 
1890     if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
1891         !m_interpreter.UserCommandExists(cmd_name)) {
1892       result.AppendErrorWithFormat("command %s not found", command[0].c_str());
1893       result.SetStatus(eReturnStatusFailed);
1894       return false;
1895     }
1896 
1897     m_interpreter.RemoveUser(cmd_name);
1898     result.SetStatus(eReturnStatusSuccessFinishResult);
1899     return true;
1900   }
1901 };
1902 
1903 #pragma mark CommandObjectMultiwordCommandsScript
1904 
1905 //-------------------------------------------------------------------------
1906 // CommandObjectMultiwordCommandsScript
1907 //-------------------------------------------------------------------------
1908 
1909 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1910 public:
1911   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1912       : CommandObjectMultiword(
1913             interpreter, "command script", "Commands for managing custom "
1914                                            "commands implemented by "
1915                                            "interpreter scripts.",
1916             "command script <subcommand> [<subcommand-options>]") {
1917     LoadSubCommand("add", CommandObjectSP(
1918                               new CommandObjectCommandsScriptAdd(interpreter)));
1919     LoadSubCommand(
1920         "delete",
1921         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1922     LoadSubCommand(
1923         "clear",
1924         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1925     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1926                                interpreter)));
1927     LoadSubCommand(
1928         "import",
1929         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1930   }
1931 
1932   ~CommandObjectMultiwordCommandsScript() override = default;
1933 };
1934 
1935 #pragma mark CommandObjectMultiwordCommands
1936 
1937 //-------------------------------------------------------------------------
1938 // CommandObjectMultiwordCommands
1939 //-------------------------------------------------------------------------
1940 
1941 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1942     CommandInterpreter &interpreter)
1943     : CommandObjectMultiword(interpreter, "command",
1944                              "Commands for managing custom LLDB commands.",
1945                              "command <subcommand> [<subcommand-options>]") {
1946   LoadSubCommand("source",
1947                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1948   LoadSubCommand("alias",
1949                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1950   LoadSubCommand("unalias", CommandObjectSP(
1951                                 new CommandObjectCommandsUnalias(interpreter)));
1952   LoadSubCommand("delete",
1953                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1954   LoadSubCommand(
1955       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1956   LoadSubCommand("history", CommandObjectSP(
1957                                 new CommandObjectCommandsHistory(interpreter)));
1958   LoadSubCommand(
1959       "script",
1960       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1961 }
1962 
1963 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1964