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