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