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