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