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