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