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