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