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