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/CommandOptionArgumentTable.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/OptionArgParser.h"
19 #include "lldb/Interpreter/OptionValueBoolean.h"
20 #include "lldb/Interpreter/OptionValueString.h"
21 #include "lldb/Interpreter/OptionValueUInt64.h"
22 #include "lldb/Interpreter/Options.h"
23 #include "lldb/Interpreter/ScriptInterpreter.h"
24 #include "lldb/Utility/Args.h"
25 #include "lldb/Utility/StringList.h"
26 #include "llvm/ADT/StringRef.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 // CommandObjectCommandsSource
32 
33 #define LLDB_OPTIONS_source
34 #include "CommandOptions.inc"
35 
36 class CommandObjectCommandsSource : public CommandObjectParsed {
37 public:
38   CommandObjectCommandsSource(CommandInterpreter &interpreter)
39       : CommandObjectParsed(
40             interpreter, "command source",
41             "Read and execute LLDB commands from the file <filename>.",
42             nullptr) {
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   llvm::Optional<std::string> GetRepeatCommand(Args &current_command_args,
61                                                uint32_t index) override {
62     return std::string("");
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         : m_stop_on_error(true), m_silent_run(false), m_stop_on_continue(true),
80           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() = default;
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.Append(&m_command_options);
263     m_option_group.Finalize();
264 
265     SetHelpLong(
266         "'alias' allows the user to create a short-cut or abbreviation for long \
267 commands, multi-word commands, and commands that take particular options.  \
268 Below are some simple examples of how one might use the 'alias' command:"
269         R"(
270 
271 (lldb) command alias sc script
272 
273     Creates the abbreviation 'sc' for the 'script' command.
274 
275 (lldb) command alias bp breakpoint
276 
277 )"
278         "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
279 breakpoint commands are two-word commands, the user would still need to \
280 enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
281         R"(
282 
283 (lldb) command alias bpl breakpoint list
284 
285     Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
286 
287 )"
288         "An alias can include some options for the command, with the values either \
289 filled in at the time the alias is created, or specified as positional \
290 arguments, to be filled in when the alias is invoked.  The following example \
291 shows how to create aliases with options:"
292         R"(
293 
294 (lldb) command alias bfl breakpoint set -f %1 -l %2
295 
296 )"
297         "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
298 options already part of the alias.  So if the user wants to set a breakpoint \
299 by file and line without explicitly having to use the -f and -l options, the \
300 user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
301 for the actual arguments that will be passed when the alias command is used.  \
302 The number in the placeholder refers to the position/order the actual value \
303 occupies when the alias is used.  All the occurrences of '%1' in the alias \
304 will be replaced with the first argument, all the occurrences of '%2' in the \
305 alias will be replaced with the second argument, and so on.  This also allows \
306 actual arguments to be used multiple times within an alias (see 'process \
307 launch' example below)."
308         R"(
309 
310 )"
311         "Note: the positional arguments must substitute as whole words in the resultant \
312 command, so you can't at present do something like this to append the file extension \
313 \".cpp\":"
314         R"(
315 
316 (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
317 
318 )"
319         "For more complex aliasing, use the \"command regex\" command instead.  In the \
320 'bfl' case above, the actual file value will be filled in with the first argument \
321 following 'bfl' and the actual line number value will be filled in with the second \
322 argument.  The user would use this alias as follows:"
323         R"(
324 
325 (lldb) command alias bfl breakpoint set -f %1 -l %2
326 (lldb) bfl my-file.c 137
327 
328 This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
329 
330 Another example:
331 
332 (lldb) command alias pltty process launch -s -o %1 -e %1
333 (lldb) pltty /dev/tty0
334 
335     Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
336 
337 )"
338         "If the user always wanted to pass the same value to a particular option, the \
339 alias could be defined with that value directly in the alias as a constant, \
340 rather than using a positional placeholder:"
341         R"(
342 
343 (lldb) command alias bl3 breakpoint set -f %1 -l 3
344 
345     Always sets a breakpoint on line 3 of whatever file is indicated.)");
346 
347     CommandArgumentEntry arg1;
348     CommandArgumentEntry arg2;
349     CommandArgumentEntry arg3;
350     CommandArgumentData alias_arg;
351     CommandArgumentData cmd_arg;
352     CommandArgumentData options_arg;
353 
354     // Define the first (and only) variant of this arg.
355     alias_arg.arg_type = eArgTypeAliasName;
356     alias_arg.arg_repetition = eArgRepeatPlain;
357 
358     // There is only one variant this argument could be; put it into the
359     // argument entry.
360     arg1.push_back(alias_arg);
361 
362     // Define the first (and only) variant of this arg.
363     cmd_arg.arg_type = eArgTypeCommandName;
364     cmd_arg.arg_repetition = eArgRepeatPlain;
365 
366     // There is only one variant this argument could be; put it into the
367     // argument entry.
368     arg2.push_back(cmd_arg);
369 
370     // Define the first (and only) variant of this arg.
371     options_arg.arg_type = eArgTypeAliasOptions;
372     options_arg.arg_repetition = eArgRepeatOptional;
373 
374     // There is only one variant this argument could be; put it into the
375     // argument entry.
376     arg3.push_back(options_arg);
377 
378     // Push the data for the first argument into the m_arguments vector.
379     m_arguments.push_back(arg1);
380     m_arguments.push_back(arg2);
381     m_arguments.push_back(arg3);
382   }
383 
384   ~CommandObjectCommandsAlias() override = default;
385 
386 protected:
387   bool DoExecute(llvm::StringRef raw_command_line,
388                  CommandReturnObject &result) override {
389     if (raw_command_line.empty()) {
390       result.AppendError("'command alias' requires at least two arguments");
391       return false;
392     }
393 
394     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
395     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
396 
397     OptionsWithRaw args_with_suffix(raw_command_line);
398 
399     if (args_with_suffix.HasArgs())
400       if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,
401                                  m_option_group, exe_ctx))
402         return false;
403 
404     llvm::StringRef raw_command_string = args_with_suffix.GetRawPart();
405     Args args(raw_command_string);
406 
407     if (args.GetArgumentCount() < 2) {
408       result.AppendError("'command alias' requires at least two arguments");
409       return false;
410     }
411 
412     // Get the alias command.
413 
414     auto alias_command = args[0].ref();
415     if (alias_command.startswith("-")) {
416       result.AppendError("aliases starting with a dash are not supported");
417       if (alias_command == "--help" || alias_command == "--long-help") {
418         result.AppendWarning("if trying to pass options to 'command alias' add "
419                              "a -- at the end of the options");
420       }
421       return false;
422     }
423 
424     // Strip the new alias name off 'raw_command_string'  (leave it on args,
425     // which gets passed to 'Execute', which does the stripping itself.
426     size_t pos = raw_command_string.find(alias_command);
427     if (pos == 0) {
428       raw_command_string = raw_command_string.substr(alias_command.size());
429       pos = raw_command_string.find_first_not_of(' ');
430       if ((pos != std::string::npos) && (pos > 0))
431         raw_command_string = raw_command_string.substr(pos);
432     } else {
433       result.AppendError("Error parsing command string.  No alias created.");
434       return false;
435     }
436 
437     // Verify that the command is alias-able.
438     if (m_interpreter.CommandExists(alias_command)) {
439       result.AppendErrorWithFormat(
440           "'%s' is a permanent debugger command and cannot be redefined.\n",
441           args[0].c_str());
442       return false;
443     }
444 
445     if (m_interpreter.UserMultiwordCommandExists(alias_command)) {
446       result.AppendErrorWithFormat(
447           "'%s' is a user container command and cannot be overwritten.\n"
448           "Delete it first with 'command container delete'\n",
449           args[0].c_str());
450       return false;
451     }
452 
453     // Get CommandObject that is being aliased. The command name is read from
454     // the front of raw_command_string. raw_command_string is returned with the
455     // name of the command object stripped off the front.
456     llvm::StringRef original_raw_command_string = raw_command_string;
457     CommandObject *cmd_obj =
458         m_interpreter.GetCommandObjectForCommand(raw_command_string);
459 
460     if (!cmd_obj) {
461       result.AppendErrorWithFormat("invalid command given to 'command alias'. "
462                                    "'%s' does not begin with a valid command."
463                                    "  No alias created.",
464                                    original_raw_command_string.str().c_str());
465       return false;
466     } else if (!cmd_obj->WantsRawCommandString()) {
467       // Note that args was initialized with the original command, and has not
468       // been updated to this point. Therefore can we pass it to the version of
469       // Execute that does not need/expect raw input in the alias.
470       return HandleAliasingNormalCommand(args, result);
471     } else {
472       return HandleAliasingRawCommand(alias_command, raw_command_string,
473                                       *cmd_obj, result);
474     }
475     return result.Succeeded();
476   }
477 
478   bool HandleAliasingRawCommand(llvm::StringRef alias_command,
479                                 llvm::StringRef raw_command_string,
480                                 CommandObject &cmd_obj,
481                                 CommandReturnObject &result) {
482     // Verify & handle any options/arguments passed to the alias command
483 
484     OptionArgVectorSP option_arg_vector_sp =
485         OptionArgVectorSP(new OptionArgVector);
486 
487     const bool include_aliases = true;
488     if (CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact(
489             cmd_obj.GetCommandName(), include_aliases)) {
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     SetHelpLong(
797         R"(
798 )"
799         "This command allows the user to create powerful regular expression commands \
800 with substitutions. The regular expressions and substitutions are specified \
801 using the regular expression substitution format of:"
802         R"(
803 
804     s/<regex>/<subst>/
805 
806 )"
807         "<regex> is a regular expression that can use parenthesis to capture regular \
808 expression input and substitute the captured matches in the output using %1 \
809 for the first match, %2 for the second, and so on."
810         R"(
811 
812 )"
813         "The regular expressions can all be specified on the command line if more than \
814 one argument is provided. If just the command name is provided on the command \
815 line, then the regular expressions and substitutions can be entered on separate \
816 lines, followed by an empty line to terminate the command definition."
817         R"(
818 
819 EXAMPLES
820 
821 )"
822         "The following example will define a regular expression command named 'f' that \
823 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
824 a number follows 'f':"
825         R"(
826 
827     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
828     CommandArgumentData thread_arg{eArgTypeSEDStylePair, eArgRepeatOptional};
829     m_arguments.push_back({thread_arg});
830   }
831 
832   ~CommandObjectCommandsAddRegex() override = default;
833 
834 protected:
835   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
836     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
837     if (output_sp && interactive) {
838       output_sp->PutCString("Enter one or more sed substitution commands in "
839                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
840                             "substitution list with an empty line.\n");
841       output_sp->Flush();
842     }
843   }
844 
845   void IOHandlerInputComplete(IOHandler &io_handler,
846                               std::string &data) override {
847     io_handler.SetIsDone(true);
848     if (m_regex_cmd_up) {
849       StringList lines;
850       if (lines.SplitIntoLines(data)) {
851         bool check_only = false;
852         for (const std::string &line : lines) {
853           Status error = AppendRegexSubstitution(line, check_only);
854           if (error.Fail()) {
855             if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) {
856               StreamSP out_stream = GetDebugger().GetAsyncOutputStream();
857               out_stream->Printf("error: %s\n", error.AsCString());
858             }
859           }
860         }
861       }
862       if (m_regex_cmd_up->HasRegexEntries()) {
863         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
864         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
865       }
866     }
867   }
868 
869   bool DoExecute(Args &command, CommandReturnObject &result) override {
870     const size_t argc = command.GetArgumentCount();
871     if (argc == 0) {
872       result.AppendError("usage: 'command regex <command-name> "
873                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
874       return false;
875     }
876 
877     Status error;
878     auto name = command[0].ref();
879     m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>(
880         m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
881         true);
882 
883     if (argc == 1) {
884       Debugger &debugger = GetDebugger();
885       bool color_prompt = debugger.GetUseColor();
886       const bool multiple_lines = true; // Get multiple lines
887       IOHandlerSP io_handler_sp(new IOHandlerEditline(
888           debugger, IOHandler::Type::Other,
889           "lldb-regex",          // Name of input reader for history
890           llvm::StringRef("> "), // Prompt
891           llvm::StringRef(),     // Continuation prompt
892           multiple_lines, color_prompt,
893           0, // Don't show line numbers
894           *this, nullptr));
895 
896       if (io_handler_sp) {
897         debugger.RunIOHandlerAsync(io_handler_sp);
898         result.SetStatus(eReturnStatusSuccessFinishNoResult);
899       }
900     } else {
901       for (auto &entry : command.entries().drop_front()) {
902         bool check_only = false;
903         error = AppendRegexSubstitution(entry.ref(), check_only);
904         if (error.Fail())
905           break;
906       }
907 
908       if (error.Success()) {
909         AddRegexCommandToInterpreter();
910       }
911     }
912     if (error.Fail()) {
913       result.AppendError(error.AsCString());
914     }
915 
916     return result.Succeeded();
917   }
918 
919   Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
920                                  bool check_only) {
921     Status error;
922 
923     if (!m_regex_cmd_up) {
924       error.SetErrorStringWithFormat(
925           "invalid regular expression command object for: '%.*s'",
926           (int)regex_sed.size(), regex_sed.data());
927       return error;
928     }
929 
930     size_t regex_sed_size = regex_sed.size();
931 
932     if (regex_sed_size <= 1) {
933       error.SetErrorStringWithFormat(
934           "regular expression substitution string is too short: '%.*s'",
935           (int)regex_sed.size(), regex_sed.data());
936       return error;
937     }
938 
939     if (regex_sed[0] != 's') {
940       error.SetErrorStringWithFormat("regular expression substitution string "
941                                      "doesn't start with 's': '%.*s'",
942                                      (int)regex_sed.size(), regex_sed.data());
943       return error;
944     }
945     const size_t first_separator_char_pos = 1;
946     // use the char that follows 's' as the regex separator character so we can
947     // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
948     const char separator_char = regex_sed[first_separator_char_pos];
949     const size_t second_separator_char_pos =
950         regex_sed.find(separator_char, first_separator_char_pos + 1);
951 
952     if (second_separator_char_pos == std::string::npos) {
953       error.SetErrorStringWithFormat(
954           "missing second '%c' separator char after '%.*s' in '%.*s'",
955           separator_char,
956           (int)(regex_sed.size() - first_separator_char_pos - 1),
957           regex_sed.data() + (first_separator_char_pos + 1),
958           (int)regex_sed.size(), regex_sed.data());
959       return error;
960     }
961 
962     const size_t third_separator_char_pos =
963         regex_sed.find(separator_char, second_separator_char_pos + 1);
964 
965     if (third_separator_char_pos == std::string::npos) {
966       error.SetErrorStringWithFormat(
967           "missing third '%c' separator char after '%.*s' in '%.*s'",
968           separator_char,
969           (int)(regex_sed.size() - second_separator_char_pos - 1),
970           regex_sed.data() + (second_separator_char_pos + 1),
971           (int)regex_sed.size(), regex_sed.data());
972       return error;
973     }
974 
975     if (third_separator_char_pos != regex_sed_size - 1) {
976       // Make sure that everything that follows the last regex separator char
977       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
978                                       third_separator_char_pos + 1) !=
979           std::string::npos) {
980         error.SetErrorStringWithFormat(
981             "extra data found after the '%.*s' regular expression substitution "
982             "string: '%.*s'",
983             (int)third_separator_char_pos + 1, regex_sed.data(),
984             (int)(regex_sed.size() - third_separator_char_pos - 1),
985             regex_sed.data() + (third_separator_char_pos + 1));
986         return error;
987       }
988     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
989       error.SetErrorStringWithFormat(
990           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
991           separator_char, separator_char, separator_char, (int)regex_sed.size(),
992           regex_sed.data());
993       return error;
994     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
995       error.SetErrorStringWithFormat(
996           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
997           separator_char, separator_char, separator_char, (int)regex_sed.size(),
998           regex_sed.data());
999       return error;
1000     }
1001 
1002     if (!check_only) {
1003       std::string regex(std::string(regex_sed.substr(
1004           first_separator_char_pos + 1,
1005           second_separator_char_pos - first_separator_char_pos - 1)));
1006       std::string subst(std::string(regex_sed.substr(
1007           second_separator_char_pos + 1,
1008           third_separator_char_pos - second_separator_char_pos - 1)));
1009       m_regex_cmd_up->AddRegexCommand(regex, subst);
1010     }
1011     return error;
1012   }
1013 
1014   void AddRegexCommandToInterpreter() {
1015     if (m_regex_cmd_up) {
1016       if (m_regex_cmd_up->HasRegexEntries()) {
1017         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
1018         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1019       }
1020     }
1021   }
1022 
1023 private:
1024   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up;
1025 
1026   class CommandOptions : public Options {
1027   public:
1028     CommandOptions() = default;
1029 
1030     ~CommandOptions() override = default;
1031 
1032     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1033                           ExecutionContext *execution_context) override {
1034       Status error;
1035       const int short_option = m_getopt_table[option_idx].val;
1036 
1037       switch (short_option) {
1038       case 'h':
1039         m_help.assign(std::string(option_arg));
1040         break;
1041       case 's':
1042         m_syntax.assign(std::string(option_arg));
1043         break;
1044       default:
1045         llvm_unreachable("Unimplemented option");
1046       }
1047 
1048       return error;
1049     }
1050 
1051     void OptionParsingStarting(ExecutionContext *execution_context) override {
1052       m_help.clear();
1053       m_syntax.clear();
1054     }
1055 
1056     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1057       return llvm::makeArrayRef(g_regex_options);
1058     }
1059 
1060     llvm::StringRef GetHelp() { return m_help; }
1061 
1062     llvm::StringRef GetSyntax() { return m_syntax; }
1063 
1064   protected:
1065     // Instance variables to hold the values for command options.
1066 
1067     std::string m_help;
1068     std::string m_syntax;
1069   };
1070 
1071   Options *GetOptions() override { return &m_options; }
1072 
1073   CommandOptions m_options;
1074 };
1075 
1076 class CommandObjectPythonFunction : public CommandObjectRaw {
1077 public:
1078   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1079                               std::string funct, std::string help,
1080                               ScriptedCommandSynchronicity synch)
1081       : CommandObjectRaw(interpreter, name), m_function_name(funct),
1082         m_synchro(synch) {
1083     if (!help.empty())
1084       SetHelp(help);
1085     else {
1086       StreamString stream;
1087       stream.Printf("For more information run 'help %s'", name.c_str());
1088       SetHelp(stream.GetString());
1089     }
1090   }
1091 
1092   ~CommandObjectPythonFunction() override = default;
1093 
1094   bool IsRemovable() const override { return true; }
1095 
1096   const std::string &GetFunctionName() { return m_function_name; }
1097 
1098   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1099 
1100   llvm::StringRef GetHelpLong() override {
1101     if (m_fetched_help_long)
1102       return CommandObjectRaw::GetHelpLong();
1103 
1104     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1105     if (!scripter)
1106       return CommandObjectRaw::GetHelpLong();
1107 
1108     std::string docstring;
1109     m_fetched_help_long =
1110         scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1111     if (!docstring.empty())
1112       SetHelpLong(docstring);
1113     return CommandObjectRaw::GetHelpLong();
1114   }
1115 
1116 protected:
1117   bool DoExecute(llvm::StringRef raw_command_line,
1118                  CommandReturnObject &result) override {
1119     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1120 
1121     Status error;
1122 
1123     result.SetStatus(eReturnStatusInvalid);
1124 
1125     if (!scripter || !scripter->RunScriptBasedCommand(
1126                          m_function_name.c_str(), raw_command_line, m_synchro,
1127                          result, error, m_exe_ctx)) {
1128       result.AppendError(error.AsCString());
1129     } else {
1130       // Don't change the status if the command already set it...
1131       if (result.GetStatus() == eReturnStatusInvalid) {
1132         if (result.GetOutputData().empty())
1133           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1134         else
1135           result.SetStatus(eReturnStatusSuccessFinishResult);
1136       }
1137     }
1138 
1139     return result.Succeeded();
1140   }
1141 
1142 private:
1143   std::string m_function_name;
1144   ScriptedCommandSynchronicity m_synchro;
1145   bool m_fetched_help_long = false;
1146 };
1147 
1148 class CommandObjectScriptingObject : public CommandObjectRaw {
1149 public:
1150   CommandObjectScriptingObject(CommandInterpreter &interpreter,
1151                                std::string name,
1152                                StructuredData::GenericSP cmd_obj_sp,
1153                                ScriptedCommandSynchronicity synch)
1154       : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
1155         m_synchro(synch), m_fetched_help_short(false),
1156         m_fetched_help_long(false) {
1157     StreamString stream;
1158     stream.Printf("For more information run 'help %s'", name.c_str());
1159     SetHelp(stream.GetString());
1160     if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter())
1161       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1162   }
1163 
1164   ~CommandObjectScriptingObject() override = default;
1165 
1166   bool IsRemovable() const override { return true; }
1167 
1168   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1169 
1170   llvm::StringRef GetHelp() override {
1171     if (m_fetched_help_short)
1172       return CommandObjectRaw::GetHelp();
1173     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1174     if (!scripter)
1175       return CommandObjectRaw::GetHelp();
1176     std::string docstring;
1177     m_fetched_help_short =
1178         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1179     if (!docstring.empty())
1180       SetHelp(docstring);
1181 
1182     return CommandObjectRaw::GetHelp();
1183   }
1184 
1185   llvm::StringRef GetHelpLong() override {
1186     if (m_fetched_help_long)
1187       return CommandObjectRaw::GetHelpLong();
1188 
1189     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1190     if (!scripter)
1191       return CommandObjectRaw::GetHelpLong();
1192 
1193     std::string docstring;
1194     m_fetched_help_long =
1195         scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1196     if (!docstring.empty())
1197       SetHelpLong(docstring);
1198     return CommandObjectRaw::GetHelpLong();
1199   }
1200 
1201 protected:
1202   bool DoExecute(llvm::StringRef raw_command_line,
1203                  CommandReturnObject &result) override {
1204     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1205 
1206     Status error;
1207 
1208     result.SetStatus(eReturnStatusInvalid);
1209 
1210     if (!scripter ||
1211         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1212                                          m_synchro, result, error, m_exe_ctx)) {
1213       result.AppendError(error.AsCString());
1214     } else {
1215       // Don't change the status if the command already set it...
1216       if (result.GetStatus() == eReturnStatusInvalid) {
1217         if (result.GetOutputData().empty())
1218           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1219         else
1220           result.SetStatus(eReturnStatusSuccessFinishResult);
1221       }
1222     }
1223 
1224     return result.Succeeded();
1225   }
1226 
1227 private:
1228   StructuredData::GenericSP m_cmd_obj_sp;
1229   ScriptedCommandSynchronicity m_synchro;
1230   bool m_fetched_help_short : 1;
1231   bool m_fetched_help_long : 1;
1232 };
1233 
1234 // CommandObjectCommandsScriptImport
1235 #define LLDB_OPTIONS_script_import
1236 #include "CommandOptions.inc"
1237 
1238 class CommandObjectCommandsScriptImport : public CommandObjectParsed {
1239 public:
1240   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1241       : CommandObjectParsed(interpreter, "command script import",
1242                             "Import a scripting module in LLDB.", nullptr) {
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() = default;
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 #define LLDB_OPTIONS_script_add
1359 #include "CommandOptions.inc"
1360 
1361 class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1362                                        public IOHandlerDelegateMultiline {
1363 public:
1364   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1365       : CommandObjectParsed(interpreter, "command script add",
1366                             "Add a scripted function as an LLDB command.",
1367                             "Add a scripted function as an lldb command. "
1368                             "If you provide a single argument, the command "
1369                             "will be added at the root level of the command "
1370                             "hierarchy.  If there are more arguments they "
1371                             "must be a path to a user-added container "
1372                             "command, and the last element will be the new "
1373                             "command name."),
1374         IOHandlerDelegateMultiline("DONE") {
1375     CommandArgumentEntry arg1;
1376     CommandArgumentData cmd_arg;
1377 
1378     // This is one or more command names, which form the path to the command
1379     // you want to add.
1380     cmd_arg.arg_type = eArgTypeCommand;
1381     cmd_arg.arg_repetition = eArgRepeatPlus;
1382 
1383     // There is only one variant this argument could be; put it into the
1384     // argument entry.
1385     arg1.push_back(cmd_arg);
1386 
1387     // Push the data for the first argument into the m_arguments vector.
1388     m_arguments.push_back(arg1);
1389   }
1390 
1391   ~CommandObjectCommandsScriptAdd() override = default;
1392 
1393   Options *GetOptions() override { return &m_options; }
1394 
1395   void
1396   HandleArgumentCompletion(CompletionRequest &request,
1397                            OptionElementVector &opt_element_vector) override {
1398     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1399                                                       opt_element_vector);
1400   }
1401 
1402 protected:
1403   class CommandOptions : public Options {
1404   public:
1405     CommandOptions() = default;
1406 
1407     ~CommandOptions() override = default;
1408 
1409     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1410                           ExecutionContext *execution_context) override {
1411       Status error;
1412       const int short_option = m_getopt_table[option_idx].val;
1413 
1414       switch (short_option) {
1415       case 'f':
1416         if (!option_arg.empty())
1417           m_funct_name = std::string(option_arg);
1418         break;
1419       case 'c':
1420         if (!option_arg.empty())
1421           m_class_name = std::string(option_arg);
1422         break;
1423       case 'h':
1424         if (!option_arg.empty())
1425           m_short_help = std::string(option_arg);
1426         break;
1427       case 'o':
1428         m_overwrite_lazy = eLazyBoolYes;
1429         break;
1430       case 's':
1431         m_synchronicity =
1432             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1433                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1434         if (!error.Success())
1435           error.SetErrorStringWithFormat(
1436               "unrecognized value for synchronicity '%s'",
1437               option_arg.str().c_str());
1438         break;
1439       default:
1440         llvm_unreachable("Unimplemented option");
1441       }
1442 
1443       return error;
1444     }
1445 
1446     void OptionParsingStarting(ExecutionContext *execution_context) override {
1447       m_class_name.clear();
1448       m_funct_name.clear();
1449       m_short_help.clear();
1450       m_overwrite_lazy = eLazyBoolCalculate;
1451       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1452     }
1453 
1454     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1455       return llvm::makeArrayRef(g_script_add_options);
1456     }
1457 
1458     // Instance variables to hold the values for command options.
1459 
1460     std::string m_class_name;
1461     std::string m_funct_name;
1462     std::string m_short_help;
1463     LazyBool m_overwrite_lazy = eLazyBoolCalculate;
1464     ScriptedCommandSynchronicity m_synchronicity =
1465         eScriptedCommandSynchronicitySynchronous;
1466   };
1467 
1468   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
1469     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
1470     if (output_sp && interactive) {
1471       output_sp->PutCString(g_python_command_instructions);
1472       output_sp->Flush();
1473     }
1474   }
1475 
1476   void IOHandlerInputComplete(IOHandler &io_handler,
1477                               std::string &data) override {
1478     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
1479 
1480     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1481     if (interpreter) {
1482       StringList lines;
1483       lines.SplitIntoLines(data);
1484       if (lines.GetSize() > 0) {
1485         std::string funct_name_str;
1486         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1487           if (funct_name_str.empty()) {
1488             error_sp->Printf("error: unable to obtain a function name, didn't "
1489                              "add python command.\n");
1490             error_sp->Flush();
1491           } else {
1492             // everything should be fine now, let's add this alias
1493 
1494             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1495                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
1496                 m_synchronicity));
1497             if (!m_container) {
1498               Status error = m_interpreter.AddUserCommand(
1499                   m_cmd_name, command_obj_sp, m_overwrite);
1500               if (error.Fail()) {
1501                 error_sp->Printf("error: unable to add selected command: '%s'",
1502                                  error.AsCString());
1503                 error_sp->Flush();
1504               }
1505             } else {
1506               llvm::Error llvm_error = m_container->LoadUserSubcommand(
1507                   m_cmd_name, command_obj_sp, m_overwrite);
1508               if (llvm_error) {
1509                 error_sp->Printf("error: unable to add selected command: '%s'",
1510                                llvm::toString(std::move(llvm_error)).c_str());
1511                 error_sp->Flush();
1512               }
1513             }
1514           }
1515         } else {
1516           error_sp->Printf(
1517               "error: unable to create function, didn't add python command\n");
1518           error_sp->Flush();
1519         }
1520       } else {
1521         error_sp->Printf("error: empty function, didn't add python command\n");
1522         error_sp->Flush();
1523       }
1524     } else {
1525       error_sp->Printf(
1526           "error: script interpreter missing, didn't add python command\n");
1527       error_sp->Flush();
1528     }
1529 
1530     io_handler.SetIsDone(true);
1531   }
1532 
1533   bool DoExecute(Args &command, CommandReturnObject &result) override {
1534     if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
1535       result.AppendError("only scripting language supported for scripted "
1536                          "commands is currently Python");
1537       return false;
1538     }
1539 
1540     if (command.GetArgumentCount() == 0) {
1541       result.AppendError("'command script add' requires at least one argument");
1542       return false;
1543     }
1544     // Store the options in case we get multi-line input, also figure out the
1545     // default if not user supplied:
1546     switch (m_options.m_overwrite_lazy) {
1547       case eLazyBoolCalculate:
1548         m_overwrite = !GetDebugger().GetCommandInterpreter().GetRequireCommandOverwrite();
1549         break;
1550       case eLazyBoolYes:
1551         m_overwrite = true;
1552         break;
1553       case eLazyBoolNo:
1554         m_overwrite = false;
1555     }
1556 
1557     Status path_error;
1558     m_container = GetCommandInterpreter().VerifyUserMultiwordCmdPath(
1559         command, true, path_error);
1560 
1561     if (path_error.Fail()) {
1562       result.AppendErrorWithFormat("error in command path: %s",
1563                                    path_error.AsCString());
1564       return false;
1565     }
1566 
1567     if (!m_container) {
1568       // This is getting inserted into the root of the interpreter.
1569       m_cmd_name = std::string(command[0].ref());
1570     } else {
1571       size_t num_args = command.GetArgumentCount();
1572       m_cmd_name = std::string(command[num_args - 1].ref());
1573     }
1574 
1575     m_short_help.assign(m_options.m_short_help);
1576     m_synchronicity = m_options.m_synchronicity;
1577 
1578     // Handle the case where we prompt for the script code first:
1579     if (m_options.m_class_name.empty() && m_options.m_funct_name.empty()) {
1580       m_interpreter.GetPythonCommandsFromIOHandler("     ", // Prompt
1581                                                    *this);  // IOHandlerDelegate
1582       return result.Succeeded();
1583     }
1584 
1585     CommandObjectSP new_cmd_sp;
1586     if (m_options.m_class_name.empty()) {
1587       new_cmd_sp.reset(new CommandObjectPythonFunction(
1588           m_interpreter, m_cmd_name, m_options.m_funct_name,
1589           m_options.m_short_help, m_synchronicity));
1590     } else {
1591       ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1592       if (!interpreter) {
1593         result.AppendError("cannot find ScriptInterpreter");
1594         return false;
1595       }
1596 
1597       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1598           m_options.m_class_name.c_str());
1599       if (!cmd_obj_sp) {
1600         result.AppendError("cannot create helper object");
1601         return false;
1602       }
1603 
1604       new_cmd_sp.reset(new CommandObjectScriptingObject(
1605           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1606     }
1607 
1608     // Assume we're going to succeed...
1609     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1610     if (!m_container) {
1611       Status add_error =
1612           m_interpreter.AddUserCommand(m_cmd_name, new_cmd_sp, m_overwrite);
1613       if (add_error.Fail())
1614         result.AppendErrorWithFormat("cannot add command: %s",
1615                                      add_error.AsCString());
1616     } else {
1617       llvm::Error llvm_error =
1618           m_container->LoadUserSubcommand(m_cmd_name, new_cmd_sp, m_overwrite);
1619       if (llvm_error)
1620         result.AppendErrorWithFormat("cannot add command: %s",
1621                                      llvm::toString(std::move(llvm_error)).c_str());
1622     }
1623     return result.Succeeded();
1624   }
1625 
1626   CommandOptions m_options;
1627   std::string m_cmd_name;
1628   CommandObjectMultiword *m_container = nullptr;
1629   std::string m_short_help;
1630   bool m_overwrite = false;
1631   ScriptedCommandSynchronicity m_synchronicity =
1632       eScriptedCommandSynchronicitySynchronous;
1633 };
1634 
1635 // CommandObjectCommandsScriptList
1636 
1637 class CommandObjectCommandsScriptList : public CommandObjectParsed {
1638 public:
1639   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1640       : CommandObjectParsed(interpreter, "command script list",
1641                             "List defined top-level scripted commands.",
1642                             nullptr) {}
1643 
1644   ~CommandObjectCommandsScriptList() override = default;
1645 
1646   bool DoExecute(Args &command, CommandReturnObject &result) override {
1647     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1648 
1649     result.SetStatus(eReturnStatusSuccessFinishResult);
1650 
1651     return true;
1652   }
1653 };
1654 
1655 // CommandObjectCommandsScriptClear
1656 
1657 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1658 public:
1659   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1660       : CommandObjectParsed(interpreter, "command script clear",
1661                             "Delete all scripted commands.", nullptr) {}
1662 
1663   ~CommandObjectCommandsScriptClear() override = default;
1664 
1665 protected:
1666   bool DoExecute(Args &command, CommandReturnObject &result) override {
1667     m_interpreter.RemoveAllUser();
1668 
1669     result.SetStatus(eReturnStatusSuccessFinishResult);
1670 
1671     return true;
1672   }
1673 };
1674 
1675 // CommandObjectCommandsScriptDelete
1676 
1677 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1678 public:
1679   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1680       : CommandObjectParsed(
1681             interpreter, "command script delete",
1682             "Delete a scripted command by specifying the path to the command.",
1683             nullptr) {
1684     CommandArgumentEntry arg1;
1685     CommandArgumentData cmd_arg;
1686 
1687     // This is a list of command names forming the path to the command
1688     // to be deleted.
1689     cmd_arg.arg_type = eArgTypeCommand;
1690     cmd_arg.arg_repetition = eArgRepeatPlus;
1691 
1692     // There is only one variant this argument could be; put it into the
1693     // argument entry.
1694     arg1.push_back(cmd_arg);
1695 
1696     // Push the data for the first argument into the m_arguments vector.
1697     m_arguments.push_back(arg1);
1698   }
1699 
1700   ~CommandObjectCommandsScriptDelete() override = default;
1701 
1702   void
1703   HandleArgumentCompletion(CompletionRequest &request,
1704                            OptionElementVector &opt_element_vector) override {
1705     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1706                                                       opt_element_vector);
1707   }
1708 
1709 protected:
1710   bool DoExecute(Args &command, CommandReturnObject &result) override {
1711 
1712     llvm::StringRef root_cmd = command[0].ref();
1713     size_t num_args = command.GetArgumentCount();
1714 
1715     if (root_cmd.empty()) {
1716       result.AppendErrorWithFormat("empty root command name");
1717       return false;
1718     }
1719     if (!m_interpreter.HasUserCommands() &&
1720         !m_interpreter.HasUserMultiwordCommands()) {
1721       result.AppendErrorWithFormat("can only delete user defined commands, "
1722                                    "but no user defined commands found");
1723       return false;
1724     }
1725 
1726     CommandObjectSP cmd_sp = m_interpreter.GetCommandSPExact(root_cmd);
1727     if (!cmd_sp) {
1728       result.AppendErrorWithFormat("command '%s' not found.",
1729                                    command[0].c_str());
1730       return false;
1731     }
1732     if (!cmd_sp->IsUserCommand()) {
1733       result.AppendErrorWithFormat("command '%s' is not a user command.",
1734                                    command[0].c_str());
1735       return false;
1736     }
1737     if (cmd_sp->GetAsMultiwordCommand() && num_args == 1) {
1738       result.AppendErrorWithFormat("command '%s' is a multi-word command.\n "
1739                                    "Delete with \"command container delete\"",
1740                                    command[0].c_str());
1741       return false;
1742     }
1743 
1744     if (command.GetArgumentCount() == 1) {
1745       m_interpreter.RemoveUser(root_cmd);
1746       result.SetStatus(eReturnStatusSuccessFinishResult);
1747       return true;
1748     }
1749     // We're deleting a command from a multiword command.  Verify the command
1750     // path:
1751     Status error;
1752     CommandObjectMultiword *container =
1753         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1754                                                            error);
1755     if (error.Fail()) {
1756       result.AppendErrorWithFormat("could not resolve command path: %s",
1757                                    error.AsCString());
1758       return false;
1759     }
1760     if (!container) {
1761       // This means that command only had a leaf command, so the container is
1762       // the root.  That should have been handled above.
1763       result.AppendErrorWithFormat("could not find a container for '%s'",
1764                                    command[0].c_str());
1765       return false;
1766     }
1767     const char *leaf_cmd = command[num_args - 1].c_str();
1768     llvm::Error llvm_error = container->RemoveUserSubcommand(leaf_cmd,
1769                                             /* multiword not okay */ false);
1770     if (llvm_error) {
1771       result.AppendErrorWithFormat("could not delete command '%s': %s",
1772                                    leaf_cmd,
1773                                    llvm::toString(std::move(llvm_error)).c_str());
1774       return false;
1775     }
1776 
1777     Stream &out_stream = result.GetOutputStream();
1778 
1779     out_stream << "Deleted command:";
1780     for (size_t idx = 0; idx < num_args; idx++) {
1781       out_stream << ' ';
1782       out_stream << command[idx].c_str();
1783     }
1784     out_stream << '\n';
1785     result.SetStatus(eReturnStatusSuccessFinishResult);
1786     return true;
1787   }
1788 };
1789 
1790 #pragma mark CommandObjectMultiwordCommandsScript
1791 
1792 // CommandObjectMultiwordCommandsScript
1793 
1794 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1795 public:
1796   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1797       : CommandObjectMultiword(
1798             interpreter, "command script",
1799             "Commands for managing custom "
1800             "commands implemented by "
1801             "interpreter scripts.",
1802             "command script <subcommand> [<subcommand-options>]") {
1803     LoadSubCommand("add", CommandObjectSP(
1804                               new CommandObjectCommandsScriptAdd(interpreter)));
1805     LoadSubCommand(
1806         "delete",
1807         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1808     LoadSubCommand(
1809         "clear",
1810         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1811     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1812                                interpreter)));
1813     LoadSubCommand(
1814         "import",
1815         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1816   }
1817 
1818   ~CommandObjectMultiwordCommandsScript() override = default;
1819 };
1820 
1821 #pragma mark CommandObjectCommandContainer
1822 #define LLDB_OPTIONS_container_add
1823 #include "CommandOptions.inc"
1824 
1825 class CommandObjectCommandsContainerAdd : public CommandObjectParsed {
1826 public:
1827   CommandObjectCommandsContainerAdd(CommandInterpreter &interpreter)
1828       : CommandObjectParsed(
1829             interpreter, "command container add",
1830             "Add a container command to lldb.  Adding to built-"
1831             "in container commands is not allowed.",
1832             "command container add [[path1]...] container-name") {
1833     CommandArgumentEntry arg1;
1834     CommandArgumentData cmd_arg;
1835 
1836     // This is one or more command names, which form the path to the command
1837     // you want to add.
1838     cmd_arg.arg_type = eArgTypeCommand;
1839     cmd_arg.arg_repetition = eArgRepeatPlus;
1840 
1841     // There is only one variant this argument could be; put it into the
1842     // argument entry.
1843     arg1.push_back(cmd_arg);
1844 
1845     // Push the data for the first argument into the m_arguments vector.
1846     m_arguments.push_back(arg1);
1847   }
1848 
1849   ~CommandObjectCommandsContainerAdd() override = default;
1850 
1851   Options *GetOptions() override { return &m_options; }
1852 
1853   void
1854   HandleArgumentCompletion(CompletionRequest &request,
1855                            OptionElementVector &opt_element_vector) override {
1856     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1857                                                       opt_element_vector);
1858   }
1859 
1860 protected:
1861   class CommandOptions : public Options {
1862   public:
1863     CommandOptions() = default;
1864 
1865     ~CommandOptions() override = default;
1866 
1867     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1868                           ExecutionContext *execution_context) override {
1869       Status error;
1870       const int short_option = m_getopt_table[option_idx].val;
1871 
1872       switch (short_option) {
1873       case 'h':
1874         if (!option_arg.empty())
1875           m_short_help = std::string(option_arg);
1876         break;
1877       case 'o':
1878         m_overwrite = true;
1879         break;
1880       case 'H':
1881         if (!option_arg.empty())
1882           m_long_help = std::string(option_arg);
1883         break;
1884       default:
1885         llvm_unreachable("Unimplemented option");
1886       }
1887 
1888       return error;
1889     }
1890 
1891     void OptionParsingStarting(ExecutionContext *execution_context) override {
1892       m_short_help.clear();
1893       m_long_help.clear();
1894       m_overwrite = false;
1895     }
1896 
1897     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1898       return llvm::makeArrayRef(g_container_add_options);
1899     }
1900 
1901     // Instance variables to hold the values for command options.
1902 
1903     std::string m_short_help;
1904     std::string m_long_help;
1905     bool m_overwrite = false;
1906   };
1907   bool DoExecute(Args &command, CommandReturnObject &result) override {
1908     size_t num_args = command.GetArgumentCount();
1909 
1910     if (num_args == 0) {
1911       result.AppendError("no command was specified");
1912       return false;
1913     }
1914 
1915     if (num_args == 1) {
1916       // We're adding this as a root command, so use the interpreter.
1917       const char *cmd_name = command.GetArgumentAtIndex(0);
1918       auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1919           GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1920           m_options.m_long_help.c_str()));
1921       cmd_sp->GetAsMultiwordCommand()->SetRemovable(true);
1922       Status add_error = GetCommandInterpreter().AddUserCommand(
1923           cmd_name, cmd_sp, m_options.m_overwrite);
1924       if (add_error.Fail()) {
1925         result.AppendErrorWithFormat("error adding command: %s",
1926                                      add_error.AsCString());
1927         return false;
1928       }
1929       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1930       return true;
1931     }
1932 
1933     // We're adding this to a subcommand, first find the subcommand:
1934     Status path_error;
1935     CommandObjectMultiword *add_to_me =
1936         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1937                                                            path_error);
1938 
1939     if (!add_to_me) {
1940       result.AppendErrorWithFormat("error adding command: %s",
1941                                    path_error.AsCString());
1942       return false;
1943     }
1944 
1945     const char *cmd_name = command.GetArgumentAtIndex(num_args - 1);
1946     auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1947         GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1948         m_options.m_long_help.c_str()));
1949     llvm::Error llvm_error =
1950         add_to_me->LoadUserSubcommand(cmd_name, cmd_sp, m_options.m_overwrite);
1951     if (llvm_error) {
1952       result.AppendErrorWithFormat("error adding subcommand: %s",
1953                                    llvm::toString(std::move(llvm_error)).c_str());
1954       return false;
1955     }
1956 
1957     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1958     return true;
1959   }
1960 
1961 private:
1962   CommandOptions m_options;
1963 };
1964 
1965 #define LLDB_OPTIONS_multiword_delete
1966 #include "CommandOptions.inc"
1967 class CommandObjectCommandsContainerDelete : public CommandObjectParsed {
1968 public:
1969   CommandObjectCommandsContainerDelete(CommandInterpreter &interpreter)
1970       : CommandObjectParsed(
1971             interpreter, "command container delete",
1972             "Delete a container command previously added to "
1973             "lldb.",
1974             "command container delete [[path1] ...] container-cmd") {
1975     CommandArgumentEntry arg1;
1976     CommandArgumentData cmd_arg;
1977 
1978     // This is one or more command names, which form the path to the command
1979     // you want to add.
1980     cmd_arg.arg_type = eArgTypeCommand;
1981     cmd_arg.arg_repetition = eArgRepeatPlus;
1982 
1983     // There is only one variant this argument could be; put it into the
1984     // argument entry.
1985     arg1.push_back(cmd_arg);
1986 
1987     // Push the data for the first argument into the m_arguments vector.
1988     m_arguments.push_back(arg1);
1989   }
1990 
1991   ~CommandObjectCommandsContainerDelete() override = default;
1992 
1993   void
1994   HandleArgumentCompletion(CompletionRequest &request,
1995                            OptionElementVector &opt_element_vector) override {
1996     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1997                                                       opt_element_vector);
1998   }
1999 
2000 protected:
2001   bool DoExecute(Args &command, CommandReturnObject &result) override {
2002     size_t num_args = command.GetArgumentCount();
2003 
2004     if (num_args == 0) {
2005       result.AppendError("No command was specified.");
2006       return false;
2007     }
2008 
2009     if (num_args == 1) {
2010       // We're removing a root command, so we need to delete it from the
2011       // interpreter.
2012       const char *cmd_name = command.GetArgumentAtIndex(0);
2013       // Let's do a little more work here so we can do better error reporting.
2014       CommandInterpreter &interp = GetCommandInterpreter();
2015       CommandObjectSP cmd_sp = interp.GetCommandSPExact(cmd_name);
2016       if (!cmd_sp) {
2017         result.AppendErrorWithFormat("container command %s doesn't exist.",
2018                                      cmd_name);
2019         return false;
2020       }
2021       if (!cmd_sp->IsUserCommand()) {
2022         result.AppendErrorWithFormat(
2023             "container command %s is not a user command", cmd_name);
2024         return false;
2025       }
2026       if (!cmd_sp->GetAsMultiwordCommand()) {
2027         result.AppendErrorWithFormat("command %s is not a container command",
2028                                      cmd_name);
2029         return false;
2030       }
2031 
2032       bool did_remove = GetCommandInterpreter().RemoveUserMultiword(cmd_name);
2033       if (!did_remove) {
2034         result.AppendErrorWithFormat("error removing command %s.", cmd_name);
2035         return false;
2036       }
2037 
2038       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2039       return true;
2040     }
2041 
2042     // We're removing a subcommand, first find the subcommand's owner:
2043     Status path_error;
2044     CommandObjectMultiword *container =
2045         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
2046                                                            path_error);
2047 
2048     if (!container) {
2049       result.AppendErrorWithFormat("error removing container command: %s",
2050                                    path_error.AsCString());
2051       return false;
2052     }
2053     const char *leaf = command.GetArgumentAtIndex(num_args - 1);
2054     llvm::Error llvm_error =
2055         container->RemoveUserSubcommand(leaf, /* multiword okay */ true);
2056     if (llvm_error) {
2057       result.AppendErrorWithFormat("error removing container command: %s",
2058                                    llvm::toString(std::move(llvm_error)).c_str());
2059       return false;
2060     }
2061     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2062     return true;
2063   }
2064 };
2065 
2066 class CommandObjectCommandContainer : public CommandObjectMultiword {
2067 public:
2068   CommandObjectCommandContainer(CommandInterpreter &interpreter)
2069       : CommandObjectMultiword(
2070             interpreter, "command container",
2071             "Commands for adding container commands to lldb.  "
2072             "Container commands are containers for other commands.  You can "
2073             "add nested container commands by specifying a command path, "
2074             "but you can't add commands into the built-in command hierarchy.",
2075             "command container <subcommand> [<subcommand-options>]") {
2076     LoadSubCommand("add", CommandObjectSP(new CommandObjectCommandsContainerAdd(
2077                               interpreter)));
2078     LoadSubCommand(
2079         "delete",
2080         CommandObjectSP(new CommandObjectCommandsContainerDelete(interpreter)));
2081   }
2082 
2083   ~CommandObjectCommandContainer() override = default;
2084 };
2085 
2086 #pragma mark CommandObjectMultiwordCommands
2087 
2088 // CommandObjectMultiwordCommands
2089 
2090 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
2091     CommandInterpreter &interpreter)
2092     : CommandObjectMultiword(interpreter, "command",
2093                              "Commands for managing custom LLDB commands.",
2094                              "command <subcommand> [<subcommand-options>]") {
2095   LoadSubCommand("source",
2096                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
2097   LoadSubCommand("alias",
2098                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
2099   LoadSubCommand("unalias", CommandObjectSP(
2100                                 new CommandObjectCommandsUnalias(interpreter)));
2101   LoadSubCommand("delete",
2102                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
2103   LoadSubCommand("container", CommandObjectSP(new CommandObjectCommandContainer(
2104                                   interpreter)));
2105   LoadSubCommand(
2106       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
2107   LoadSubCommand(
2108       "script",
2109       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
2110 }
2111 
2112 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
2113