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