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